
Inline adoc files when they are included exactly once. Also fix language tags because this inlining gives us better information on what language the code is written in.
73 lines
2.7 KiB
Plaintext
73 lines
2.7 KiB
Plaintext
SOQL queries, just as SQL queries, are sensitive to injection attacks. An injection attack happens when a user-controlled value is inserted in a query without proper sanitization. This enables attackers to access sensitive information or even perform unauthorized data modification.
|
|
|
|
|
|
This rule raises an issue when one of the methods ``++Database.query++``, ``++Database.countQuery++`` is called with a string which was build by:
|
|
|
|
* calling ``++String.format++``
|
|
* concatenation (string + string)
|
|
* calling ``++String.replace++``, ``++String.replaceAll++``, ``++String.replaceFirst++``
|
|
|
|
AND the strings provided were not hardcoded nor sanitized by ``++string.escapeSingleQuotes++``
|
|
|
|
|
|
== Ask Yourself Whether
|
|
|
|
* The SOQL query is built using string formatting technics, such as concatenating variables.
|
|
* Some of the values are coming from an untrusted source and are not sanitized.
|
|
|
|
There is a risk if you answered yes to any of those questions.
|
|
|
|
|
|
== Recommended Secure Coding Practices
|
|
|
|
* Use static queries with bind variables whenever possible. This is the best way to prevent SOQL injections. Even when there is no injection possible it will at least make code review easier.
|
|
* If you really have to use dynamic queries, sanitize all values with while-listing, type-casting or ``++string.escapeSingleQuotes()++``. See the links below for examples.
|
|
|
|
|
|
== Sensitive Code Example
|
|
|
|
----
|
|
public class My {
|
|
public getContact(String firstname) {
|
|
String query = 'SELECT id FROM Contact WHERE firstname =\''+firstname+'\'';
|
|
return Database.execute(query); // Sensitive
|
|
}
|
|
}
|
|
----
|
|
|
|
|
|
== Compliant Solution
|
|
|
|
[source,apex]
|
|
----
|
|
public class My {
|
|
public getContactSafe(String firstname) {
|
|
String query = 'SELECT id FROM Contact WHERE firstname =\''+String.escapeSingleQuotes(firstname)+'\'';
|
|
return Database.execute(query); // Compliant
|
|
}
|
|
}
|
|
----
|
|
|
|
|
|
== See
|
|
|
|
* https://owasp.org/Top10/A03_2021-Injection/[OWASP Top 10 2021 Category A3] - Injection
|
|
* https://trailhead.salesforce.com/en/content/learn/modules/secure-serverside-development/mitigate-soql-injection[Prevent SOQL Injection in Your Code]
|
|
* https://owasp.org/www-project-top-ten/2017/A1_2017-Injection[OWASP Top 10 2017 Category A1] - Injection
|
|
* https://cwe.mitre.org/data/definitions/20[MITRE, CWE-20] - Improper Input Validation
|
|
* https://cwe.mitre.org/data/definitions/89[MITRE, CWE-89] - Improper Neutralization of Special Elements used in an SQL Command
|
|
* https://www.sans.org/top25-software-errors/#cat1[SANS Top 25] - Insecure Interaction Between Components
|
|
|
|
ifdef::env-github,rspecator-view[]
|
|
|
|
'''
|
|
== Implementation Specification
|
|
(visible only on this page)
|
|
|
|
=== Message
|
|
|
|
Make sure that formatting this SOQL query is safe here.
|
|
|
|
|
|
endif::env-github,rspecator-view[]
|