Hello there, ('ω')ノ
SQLインジェクション(SQLi)は、多くの場合 SELECT
クエリの WHERE
句内で発生します。しかし、SQLiはこれに限らず、クエリのさまざまな部分で発生する可能性があります。経験豊富なテスターでも見逃しがちなSQLiの発生ポイントを理解することが重要です。
1. UPDATE 文でのSQLインジェクション
UPDATE
文では、SET
句や WHERE
句の入力値を適切に処理しない場合にSQLインジェクションが発生します。
脆弱なクエリ例:
UPDATE users SET email = '$new_email' WHERE user_id = '$user_id';
もし new_email
に次のような入力がされた場合:
test@example.com', is_admin = 1 --
この結果、クエリが次のように変わり、管理者権限を取得できてしまいます。
UPDATE users SET email = 'test@example.com', is_admin = 1 -- ' WHERE user_id = '5';
✅ 対策:
- プリペアドステートメント(バインド変数)を使用する
- 入力値のバリデーションを行う
2. INSERT 文でのSQLインジェクション
INSERT
文では、挿入される値の部分 にSQLiが発生することがあります。
脆弱なクエリ例:
INSERT INTO users (username, email, password) VALUES ('$username', '$email', '$password');
攻撃者が次のような入力を送信した場合:
test', 'test@example.com', 'password'), ('hacker', 'hacker@example.com', 'hacked
この結果、クエリが次のようになり、攻撃者のアカウントが勝手に作成されます。
INSERT INTO users (username, email, password) VALUES ('test', 'test@example.com', 'password'), ('hacker', 'hacker@example.com', 'hacked');
✅ 対策:
- プリペアドステートメントを使用する
- 入力値を適切にエスケープする
- テーブルの権限を最小限にする(INSERT制限)
3. SELECT 文のテーブル名やカラム名でのSQLインジェクション
通常、SELECT
クエリでは WHERE
句の部分にSQLiが発生しがちですが、テーブル名やカラム名の動的な指定 でもSQLiが発生することがあります。
脆弱なクエリ例:
SELECT $column_name FROM users WHERE user_id = '$user_id';
もし column_name
に次のような入力がされた場合:
password FROM users; DROP TABLE users; --
クエリが次のように変化し、データベースが破壊される可能性があります。
SELECT password FROM users; DROP TABLE users; -- FROM users WHERE user_id = '5';
✅ 対策:
- テーブル名やカラム名を動的に指定する場合、許可リスト(ホワイトリスト)を使用する
- ユーザー入力を直接SQLの構造部分に含めない
4. ORDER BY 句でのSQLインジェクション
ORDER BY
句の中でSQLiが発生することもあります。
脆弱なクエリ例:
SELECT * FROM users ORDER BY '$order_by';
攻撃者が次のように入力すると:
id; DROP TABLE users --
これにより、SQLが次のように変わり、データベースが破壊される可能性があります。
SELECT * FROM users ORDER BY id; DROP TABLE users -- ;
✅ 対策:
- ORDER BY
で使用可能なカラムを許可リストにする
- 直接ユーザー入力をSQL構文に含めない
- プリペアドステートメントを使用する(ORDER BYには一部制約あり)
まとめ
SQLインジェクションは WHERE
句以外にもさまざまな場所で発生する可能性があります。特に、UPDATE、INSERT、テーブル名・カラム名、ORDER BY の部分での脆弱性は見逃されやすいため、意識的にチェックする必要があります。
防御策まとめ
✅ プリペアドステートメントを使用する(最優先)
✅ ユーザー入力を直接SQLの構造部分に含めない
✅ ホワイトリスト(許可リスト)を使用してテーブル名やカラム名を制限
✅ データベースの権限を最小限にする
SQLiを完全に防ぐためには、常に「ユーザー入力がSQLにどのように影響するか?」を考え、適切な対策を実施することが重要です。
Best regards, (^^ゞ