Hello there, ('ω')ノ
SQLインジェクションの基本的な概念を理解したところで、今回は コメントアウト(--)を利用した攻撃 や OR 1=1 を使った全データ取得 について詳しく解説します。これらの手法を理解することで、より高度なSQLi攻撃の検出と防御が可能になります。
1. コメントアウト(--)を利用したSQLインジェクション
脆弱なアプリケーションの挙動
あるショッピングサイトでは、次のURLを使用して特定のカテゴリの商品を表示しています。
https://insecure-website.com/products?category=Gifts
このリクエストによって、次のSQLクエリが実行されます。
SELECT * FROM products WHERE category = 'Gifts' AND released = 1;
この released = 1 という条件は、「未発売の商品」を隠すために追加されています。
攻撃方法:コメントアウトを利用する
攻撃者は、次のように -- を使用して released = 1 を無効化できます。
https://insecure-website.com/products?category=Gifts'--
このリクエストによって、次のようなSQLクエリに変化します。
SELECT * FROM products WHERE category = 'Gifts'--' AND released = 1;
ここで -- はSQLのコメント記号 なので、AND released = 1 の部分は無視され、クエリは WHERE category = 'Gifts' だけが適用 されるようになります。
✅ 結果: 未発売の商品 (released = 0) もすべて表示されてしまう。
2. OR 1=1 を利用してすべての商品を取得
-- を使うだけでなく、攻撃者は OR 1=1 を加えることで、より広範囲のデータを取得できます。
攻撃例:OR 1=1 を使用
https://insecure-website.com/products?category=Gifts' OR 1=1--
このリクエストにより、以下のSQLクエリが実行されます。
SELECT * FROM products WHERE category = 'Gifts' OR 1=1--' AND released = 1;
1=1 は常に真 なので、このクエリは すべての商品を取得 するようになります。
✅ 結果: 全カテゴリの商品が表示される(攻撃者はどんなカテゴリがあるのか知らなくても、すべての商品を取得可能)。
3. OR 1=1 の危険性
攻撃者が OR 1=1 を使用すると、思わぬデータ破壊 を引き起こす可能性があります。
例えば、アプリケーションが同じリクエストパラメータを UPDATE や DELETE 文にも使っていた場合、次のような影響が発生します。
DELETE 文に影響を与える例
DELETE FROM products WHERE category = 'Gifts' OR 1=1;
✅ 結果: OR 1=1 によって すべての商品が削除されてしまう。
💡 重要: 攻撃を試す際は、対象のクエリが SELECT だけではなく、UPDATE や DELETE にも影響を及ぼさないか慎重に確認する必要があります。
4. SQLインジェクションを防ぐ方法
このような攻撃を防ぐには、以下の対策を徹底する必要があります。
1. プリペアドステートメントの使用(最優先)
SQLインジェクションを確実に防ぐためには、プリペアドステートメント(バインド変数) を使用するのが最も効果的です。
✅ 安全なコード例(PHP + PDO)
$stmt = $pdo->prepare("SELECT * FROM products WHERE category = ? AND released = 1"); $stmt->execute([$category]);
この方法では、ユーザーの入力値がSQLクエリに直接埋め込まれることがないため、安全に処理されます。
2. ユーザー入力のバリデーション
categoryパラメータは 許可リスト(ホワイトリスト) を使って制限する。- 例えば、
categoryをGifts, Electronics, Clothingなどのリスト内にあるかどうかチェックする。
✅ 許可リストの実装(PHP)
$allowed_categories = ['Gifts', 'Electronics', 'Clothing'];
if (!in_array($category, $allowed_categories)) {
die("Invalid category");
}
3. SQLエラーメッセージを非表示にする
- データベースのエラーメッセージをそのまま表示しない。
500 Internal Server Errorなどの一般的なエラーメッセージを返す。
✅ 安全なエラーハンドリング(PHP)
try {
$stmt = $pdo->prepare("SELECT * FROM products WHERE category = ? AND released = 1");
$stmt->execute([$category]);
} catch (Exception $e) {
error_log($e->getMessage());
die("An error occurred.");
}
4. データベースの権限を最小限にする
- アプリケーションのDBユーザーには、
SELECT権限のみを付与し、DELETEやUPDATEの権限を制限する。
✅ 安全な権限設定(MySQL)
GRANT SELECT ON shop.products TO 'app_user'@'localhost';
まとめ
🎯 攻撃手法のポイント
1. -- を利用して AND released = 1 の部分をコメントアウトし、隠されたデータを取得
2. OR 1=1 を追加して、データベース内のすべてのデータを取得
3. OR 1=1 が DELETE 文や UPDATE 文に影響を与えると、すべてのデータが削除される危険性がある
🛡 防御策(必ず実装すること!)
✅ プリペアドステートメントを使用する(最優先)
✅ ユーザー入力を許可リストで制限する
✅ エラーメッセージを非表示にする
✅ データベースの権限を最小限にする
SQLインジェクションは、適切な対策を講じることで確実に防ぐことが可能 です。開発の際には、常に 「このコードはSQLiに対して安全か?」 を意識し、安全なアプリケーションを構築しましょう!
Best regards, (^^ゞ