SQL Injection - Explanation of Scenarios

ここでは、SQLインジェクションの脆弱性を持つページ (sql-vulnerable.php) で試すことができる攻撃シナリオと、その入力例、そして対策ページでの挙動について説明します。

SQLインジェクション攻撃のシナリオと入力例

1. 全登録ユーザーを表示する

このシナリオでは、正規のユーザーIDを指定する代わりに、特別なSQL構文を挿入することで、WHERE句を常に真にするか、または別のSELECT文と結合して、テーブル全体の内容を表示させます。

攻撃対象ページ: app/src/sqlinjection/sql-vulnerable.php

通常の入力: user001

入力例 (全ユーザー表示):

' OR '1'='1

説明:

この入力は、元のSQLクエリ (SELECT id, first_name, last_name FROM users WHERE id = 'user001') を次のように変更します。

SELECT id, first_name, last_name FROM users WHERE id = '' OR '1'='1'

'1'='1' は常に真であるため、WHERE句全体が真となり、users テーブルのすべての行が返されます。


2. クレジットカード番号を表示する

このシナリオでは、UNIONベースのSQLインジェクションを使用します。これは、元のクエリに別のSELECT文を結合して、通常は表示されないカラム(この場合はcredit_card_number)の情報を取得しようとします。

攻撃対象ページ: app/src/sqlinjection/sql-vulnerable.php

入力例 (クレジットカード番号表示):

' UNION SELECT id, credit_card_number, 'dummy' FROM users --

説明:

この入力は、元のSQLクエリ (SELECT id, first_name, last_name FROM users WHERE id = 'user001') を次のように変更します。

SELECT id, first_name, last_name FROM users WHERE id = '' UNION SELECT id, credit_card_number, 'dummy' FROM users --

この攻撃では、UNIONするSELECT文のカラム数と型が、元のSELECT文と一致する必要があります。sql-vulnerable.phpid, first_name, last_name の3カラムを表示するため、これに合わせて id, credit_card_number, 'dummy' と3つの要素を選んでいます。credit_card_numberfirst_name または last_name の場所に表示されます。

SQLインジェクション対策のページ

プリペアドステートメントによる対策 (sql-safe-prep.php)

このページでは、プリペアドステートメント を使用してSQLインジェクション対策を行っています。プリペアドステートメントは、SQL文の構造とデータを分離することで、悪意のある入力がSQLコマンドとして解釈されるのを防ぎます。これにより、上記の攻撃シナリオの入力例を試しても、データベースからは意図しないデータが取得されることはありません。

エスケープ処理による対策 (sql-safe-escape.php)

このページでは、エスケープ処理 を使用してSQLインジェクション対策を行っています。具体的には、PDOの quote() メソッドを用いて、ユーザーからの入力に含まれる特殊文字(シングルクォーテーションなど)をエスケープします。これにより、入力データが悪意のあるSQLコードとして解釈されることを防ぎ、安全にSQLクエリを構築することができます。ただし、プリペアドステートメントの方がより安全で一般的な推奨対策です。

重要: これらの入力例を sql-vulnerable.php のユーザーID入力欄に入れて、挙動を確認してください。一方で、sql-safe-prep.php および sql-safe-escape.php ではこれらの入力例を試しても、期待される攻撃結果は得られません。これはプリペアドステートメントやエスケープ処理によって入力値が安全に処理されるためです。

試す際は、まず app/src/sqlinjection/initialize.php にアクセスしてデータベースを初期化してください。