diff --git a/swift/ql/src/queries/Security/CWE-089/SqlInjection.qhelp b/swift/ql/src/queries/Security/CWE-089/SqlInjection.qhelp index 808d5052ea5..6975d95d48a 100644 --- a/swift/ql/src/queries/Security/CWE-089/SqlInjection.qhelp +++ b/swift/ql/src/queries/Security/CWE-089/SqlInjection.qhelp @@ -12,13 +12,13 @@ If a database query (such as a SQL query) is built from user-provided data witho

-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 without sufficient sanitization. +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 example, a SQL query is prepared using string interpolation to directly include a user-controlled value userControlledString in the query. An attacker could craft userControlledString to change the overall meaning of the SQL query. +

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

@@ -35,4 +35,4 @@ Most database connector libraries offer a way to safely embed untrusted data int
  • OWASP: SQL Injection Prevention Cheat Sheet.
  • - \ No newline at end of file + diff --git a/swift/ql/src/queries/Security/CWE-089/SqlInjectionBad.swift b/swift/ql/src/queries/Security/CWE-089/SqlInjectionBad.swift index 0b5c250a67b..085b1b54798 100644 --- a/swift/ql/src/queries/Security/CWE-089/SqlInjectionBad.swift +++ b/swift/ql/src/queries/Security/CWE-089/SqlInjectionBad.swift @@ -1,3 +1,12 @@ -let unsafeQuery = "SELECT * FROM users WHERE username='\(userControlledString)'" // BAD +// with SQLite.swift -try db.execute(unsafeQuery) \ No newline at end of file +let unsafeQuery = "SELECT * FROM users WHERE username='\(userControlledString)'" + +try db.execute(unsafeQuery) // BAD + +let stmt = try db.prepare(unsafeQuery) // also BAD +try stmt.run() + +// with SQLite3 C API + +let result = sqlite3_exec(db, unsafeQuery, nil, nil, nil) // BAD diff --git a/swift/ql/src/queries/Security/CWE-089/SqlInjectionGood.swift b/swift/ql/src/queries/Security/CWE-089/SqlInjectionGood.swift index 8db8a9367b2..8d4228fca50 100644 --- a/swift/ql/src/queries/Security/CWE-089/SqlInjectionGood.swift +++ b/swift/ql/src/queries/Security/CWE-089/SqlInjectionGood.swift @@ -1,4 +1,19 @@ +// with SQLite.swift + let safeQuery = "SELECT * FROM users WHERE username=?" let stmt = try db.prepare(safeQuery, userControlledString) // GOOD -try stmt2.run() \ No newline at end of file +try stmt.run() + +// with sqlite3 C API + +var stmt2: OpaquePointer? + +if (sqlite3_prepare_v2(db, safeQuery, -1, &stmt2, nil) == SQLITE_OK) { + if (sqlite3_bind_text(stmt2, 1, userControlledString, -1, SQLITE_TRANSIENT) == SQLITE_OK) { // GOOD + let result = sqlite3_step(stmt2) + + // ... + } + sqlite3_finalize(stmt2) +}