内部クエリの特定とエンコーディングの剥ぎ取り
対象システムに対して初期パラメータを送信し、応答パターンを観察するところから解析を開始します。
name=abc&pw=a
上記を送信すると「wrong user」が返却されます。次にシングルクォートを追加した以下のペイロードを試します。
name=1%27&pw=a
応答内にBase32エンコードされた文字列が含まれていることが確認できます。これをデコードすると、さらにBase64エンコードされたデータが得られます。二段階のデコードを実施することで、バックエンドで実際に実行されているSQL文の骨子が明らかにされます。
SELECT * FROM user WHERE username = '$name'
これにより、name パラメータがインジェクションの起点であることが確定します。
フィルタリング機構の分析とバイパス
問題環境では or、=、(、) といったキーワードがブラックリスト規制されているようです。ただし、文字列比較が大文字小文字を区別しない特性を突くことで、Or や OR のような記法を用いてブロックを回避できます。
name=1' Or 1#&pw=a
このクエリを発行すると「wrong pass」という応答が返ります。これはSQL文の結合に成功し、処理が認証フェーズに進んでいることを示唆していますが、パスワード検証の段階で弾かれている状態です。
認証フローの解析と攻撃ベクトルの構築
一般的なWebアプリケーションでは、SQLクエリ内でユーザー名とパスワードの両方を WHERE 句に含めて認証しますが、本問題の実装は異なります。内部スクリプトのロジックを追跡すると、まず指定されたユーザー名に一致するレコードをデータベースから取得し、その結果セットの2番目のカラム(パスワードハッシュ)と、リクエストで送信された pw パラメータのMD5ハッシュ値をアプリケーション層で直接比較しています。
この実装差異は、UNION SELECT を用いた列の上書き攻撃に対して脆弱性を生んでいます。データベースに格納された実在するパスワードハッシュを特定する必要はなく、クエリ結果の形状を操作してスクリプト側の比較演算をすり抜けることが可能です。
カラム数の位置合わせとデータ型の確認のため、以下のテストペイロードを送信します。
name=1' union select 1,'admin',3#&pw=a
応答から、パスワードハッシュが3番目のカラムに格納されている構造であることが推測されます。次に、送信する pw パラメータ(例:a)のMD5ハッシュ値(0cc175b9c0f1b6a831c399e269772661)を3番目のカラムに直接埋め込みます。
name=1' union select 1,'admin','0cc175b9c0f1b6a831c399e269772661'#&pw=a
この状態では、データベースからは「admin」というユーザー名と、事前に計算したハッシュ値が返却されます。アプリケーション層の比較ロジックにおいて、入力値のハッシュと取得したハッシュが完全に一致するため、認証チェックが成功し、機密データの取得が完了します。
脆弱性の本質と防御観点
本ケースが示す技術的要因は、認証処理の境界線における実装の分断です。クエリ内で WHERE username = ? AND password = ? として完全に閉じるのではなく、データベース検索結果をアプリケーション層で2次検証するアーキテクチャは、UNION 構文を用いた結果セットの操作に対して脆弱性を孕みます。入力の厳密なサニタイズと、データベース層での原子性の高い認証チェックの実装が、此类のバイパスを根本的に遮断する上で不可欠です。