swift.sqllite.sqllite-injection-audit.swift-potential-sqlite-injection

profile photo of semgrepsemgrep
Author
unknown
Download Count*

Potential Client-side SQL injection which has different impacts depending on the SQL use-case. The impact may include the circumvention of local authentication mechanisms, obtaining of sensitive data from the app, or manipulation of client-side behavior. It wasn't possible to make certain that the source is untrusted, but the application should avoid concatenating dynamic data into SQL queries and should instead leverage parameterized queries.

Run Locally

Run in CI

Defintion

rules:
  - id: swift-potential-sqlite-injection
    message: Potential Client-side SQL injection which has different impacts
      depending on the SQL use-case. The impact may include the circumvention of
      local authentication mechanisms, obtaining of sensitive data from the app,
      or manipulation of client-side behavior. It wasn't possible to make
      certain that the source is untrusted, but the application should avoid
      concatenating dynamic data into SQL queries and should instead leverage
      parameterized queries.
    severity: WARNING
    metadata:
      likelihood: MEDIUM
      impact: MEDIUM
      confidence: LOW
      category: security
      cwe:
        - "CWE-89: Improper Neutralization of Special Elements used in an SQL
          Command ('SQL Injection')"
      masvs:
        - "MASVS-CODE-4: The app validates and sanitizes all untrusted inputs."
      references:
        - https://developer.apple.com/library/archive/documentation/Security/Conceptual/SecureCodingGuide/Articles/ValidatingInput.html
      subcategory:
        - vuln
      technology:
        - ios
        - macos
      license: Commons Clause License Condition v1.0[LGPL-2.1-only]
      vulnerability_class:
        - SQL Injection
    languages:
      - swift
    mode: taint
    pattern-sources:
      - pattern-either:
          - pattern: |
              "...\($X)..."
          - pattern: |
              $SQL = "..." + $X
          - pattern: |
              $SQL = $X + "..."
    pattern-sinks:
      - patterns:
          - pattern-either:
              - pattern: sqlite3_exec($DB, $SQL, ...)
              - pattern: sqlite3_prepare_v2($DB, $SQL, ...)
          - focus-metavariable:
              - $SQL

Examples

sqllite-injection-audit.swift

let username = someField.text()
let password = a.text()

let sql = "SELECT * FROM semgrep_users WHERE username = '\(username)' AND password = '\(password)'"

// ruleid:swift-potential-sqlite-injection
let result = sqlite3_exec(db, sql, nil, nil, nil)
sqlite3_close(db)

let sql = "SELECT * FROM semgrep_users WHERE username = 'admin' AND password = '\(password)'"
// ruleid:swift-potential-sqlite-injection
let result = sqlite3_exec(db, sql, nil, nil, nil)
sqlite3_close(db)


let sql = "SELECT * FROM semgrep_users WHERE username = ? AND password = ?"
var stmt: OpaquePointer?
// okid:swift-potential-sqlite-injection
if sqlite3_prepare_v2(db, sql, -1, &stmt, nil) == SQLITE_OK {
    sqlite3_bind_text(stmt, 1, username, -1, nil)
    sqlite3_bind_text(stmt, 2, password, -1, nil)
    if sqlite3_step(stmt) == SQLITE_DONE {
        // SUCCESS
    }
}

sqlite3_finalize(stmt)
sqlite3_close(db)

let sql = "SELECT * FROM semgrep_users WHERE username = 'admin' AND password = 'admin'"
// okid:swift-potential-sqlite-injection
let result = sqlite3_exec(db, sql, nil, nil, nil)
sqlite3_close(db)


let theUsername = "admin"
let sql = "SELECT * FROM semgrep_users WHERE username = '" + theUsername + "' AND password = 'admin'"
// FP but cant do much about this I dont think
// ruleid:swift-potential-sqlite-injection
let result = sqlite3_exec(db, sql, nil, nil, nil)
sqlite3_close(db)

let newUser = getUsernameFromServer()
let sql = "SELECT * FROM semgrep_users WHERE username = '" + newUser + "' AND password = 'admin'"
// ruleid:swift-potential-sqlite-injection
let result = sqlite3_exec(db, sql, nil, nil, nil)
sqlite3_close(db)


let sql = "SELECT * FROM semgrep_users WHERE username = 'admin' AND password = '" + password + "'"
// ruleid:swift-potential-sqlite-injection
let result = sqlite3_exec(db, sql, nil, nil, nil)
sqlite3_close(db)


let sql = "SELECT * FROM semgrep_users WHERE username = ? AND password = '" + password + "'"
// ruleid:swift-potential-sqlite-injection
if sqlite3_prepare_v2(db, sql, -1, &stmt, nil) == SQLITE_OK {
    sqlite3_bind_text(stmt, 1, username, -1, nil)
    if sqlite3_step(stmt) == SQLITE_DONE {
        // SUCCESS
    }
}

sqlite3_finalize(stmt)
sqlite3_close(db)