SwiftのSQLインジェクション

SwiftのSQLインジェクション

説明

ユーザー入力から組み立てたSQLを実行すると、攻撃者にクエリの構造を変更され、認証の回避やデータの取得、変更、削除につながるおそれがあります。

想定される影響

  • 認証や権限チェックの回避
  • 機密データの取得や改ざん
  • データの削除やサービスの停止

対処方法

  1. SQL文字列にユーザー入力を連結したり、文字列補間で埋め込んだりしないでください。
  2. SQLiteのバインディング、プリペアドステートメント、ORMのクエリビルダーなど、クエリの構造と値を分離するAPIを使います。
  3. テーブル名や列名など、値としてバインドできない識別子は許可リストから選びます。

例

変更前

swift
let query = "SELECT * FROM users WHERE name = '\(username)'"
try db.execute(query)

変更後

swift
import GRDB

func findUser(db: Database, username: String) throws -> Row? {
    return try Row.fetchOne(
        db,
        sql: "SELECT * FROM users WHERE name = ?",
        arguments: [username])
}

説明:

  • 変更前: ユーザー入力がSQLの構造に直接組み込まれます。
  • 変更後: GRDBの Row.fetchOne にバインド引数を渡して結果を取得します。クエリの構造と値を分離するため、入力をデータとして扱えます。

参考資料