Link Search Menu Expand Document

SQL Injection in iOS

Play SecureFlag Play iOS Labs on this vulnerability with SecureFlag!

Vulnerable example

The following snippet outlines a vulnerable SQL(ITE) query performed in iOS Swift:

let sql = "SELECT * FROM user WHERE username = '\(username)' AND password = '\(password)'"
let result = sqlite3_exec(db, sql, nil, nil, nil)
// ...
sqlite3_close(db)

The string interpolation syntax merely inserts the username and password values into the query, and wrapping them in ' is obviously not enough to prevent the injection if those are user-controlled values.

In fact, one could provide a valid username, say admin, and use ' OR 1 LIMIT '1 as the password to return the associated record, even without knowing the password. The resulting query would then be:

SELECT * FROM user WHERE username = 'admin' AND password = '' OR 1 LIMIT '1';

Prevention

As usual, the most effective prevention is to use prepared statements:

let sql = "SELECT * FROM user WHERE username = ? AND password = ?"
var updateStatement: OpaquePointer?
if sqlite3_prepare_v2(db, sql, -1, &updateStatement, nil) == SQLITE_OK {
    sqlite3_bind_text(updateStatement, 1, username, -1, nil)
    if sqlite3_step(updateStatement) == SQLITE_DONE {
        print("OK")
        // ...
    } else {
        print("ERROR")
    }
} else {
    print("ERROR")
}

sqlite3_finalize(updateStatement)
sqlite3_close(db)

References

CWE - CWE-89: Improper Neutralization of Special Elements used in an SQL Command

OWASP - SQL Injection

OWASP - SQL Injection Prevention Cheat Sheet