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, (^^ゞ