diff --git a/rust/ql/src/queries/security/CWE-089/SqlInjection.qhelp b/rust/ql/src/queries/security/CWE-089/SqlInjection.qhelp new file mode 100644 index 000000000000..bcf54fca5828 --- /dev/null +++ b/rust/ql/src/queries/security/CWE-089/SqlInjection.qhelp @@ -0,0 +1,39 @@ + + + + +

+If a database query (such as a SQL query) is built from user-provided data without sufficient sanitization, a user may be able to run malicious database queries. An attacker can craft the part of the query they control to change the overall meaning of the query. +

+ +
+ + +

+Most database connector libraries offer a way to safely embed untrusted data into a query using query parameters or prepared statements. You should use these features to build queries, rather than string concatenation or similar methods. You can also escape (sanitize) user-controlled strings so that they can be included directly in an SQL command. A library function should be used for escaping, because this approach is only safe if the escaping function is robust against all possible inputs. +

+ +
+ + +

+In the following examples, an SQL query is prepared using string formatting to directly include a user-controlled value remote_controlled_string. An attacker could craft remote_controlled_string to change the overall meaning of the SQL query. +

+ + + +

A better way to do this is with a prepared statement, binding remote_controlled_string to a parameter of that statement. An attacker who controls remote_controlled_string now cannot change the overall meaning of the query. +

+ + + +
+ + +
  • Wikipedia: SQL injection.
  • +
  • OWASP: SQL Injection Prevention Cheat Sheet.
  • + +
    +
    diff --git a/rust/ql/src/queries/security/CWE-089/SqlInjectionBad.rs b/rust/ql/src/queries/security/CWE-089/SqlInjectionBad.rs new file mode 100644 index 000000000000..cd0086b7eb27 --- /dev/null +++ b/rust/ql/src/queries/security/CWE-089/SqlInjectionBad.rs @@ -0,0 +1,7 @@ +// with SQLx + +let unsafe_query = format!("SELECT * FROM people WHERE firstname='{remote_controlled_string}'"); + +let _ = conn.execute(unsafe_query.as_str()).await?; // BAD (arbitrary SQL injection is possible) + +let _ = sqlx::query(unsafe_query.as_str()).fetch_all(&mut conn).await?; // $ BAD (arbitrary SQL injection is possible) diff --git a/rust/ql/src/queries/security/CWE-089/SqlInjectionGood.rs b/rust/ql/src/queries/security/CWE-089/SqlInjectionGood.rs new file mode 100644 index 000000000000..238665cc2739 --- /dev/null +++ b/rust/ql/src/queries/security/CWE-089/SqlInjectionGood.rs @@ -0,0 +1,5 @@ +// with SQLx + +let prepared_query = "SELECT * FROM people WHERE firstname=?"; + +let _ = sqlx::query(prepared_query_1).bind(&remote_controlled_string).fetch_all(&mut conn).await?; // GOOD (prepared statement with bound parameter)