ここでは、SQLインジェクションの脆弱性を持つページ (sql-vulnerable.php) で試すことができる攻撃シナリオと、その入力例、そして対策ページでの挙動について説明します。
このシナリオでは、正規のユーザー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 テーブルのすべての行が返されます。
このシナリオでは、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 --
id = '' は空文字列との比較なので、最初のSELECT文は結果を返しません。UNION SELECT id, credit_card_number, 'dummy' FROM users は、users テーブルからid、credit_card_number、および固定文字列'dummy'を選択します。-- はSQLコメントアウトで、id = ' の後のシングルクォーテーションを閉じた残りの部分をコメントアウトします。この攻撃では、UNIONするSELECT文のカラム数と型が、元のSELECT文と一致する必要があります。sql-vulnerable.php は id, first_name, last_name の3カラムを表示するため、これに合わせて id, credit_card_number, 'dummy' と3つの要素を選んでいます。credit_card_number は first_name または last_name の場所に表示されます。
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 にアクセスしてデータベースを初期化してください。