家の鍵は1つ?それとも2つ?「HTTPパラメータ汚染」で泥棒がすり抜ける仕組み
こんにちは!普段はシステムの裏側を覗き見たり、強固なはずのセキュリティをどう突破するかを研究しているエンジニアです。今日は、皆さんが普段作っているWebサイトやアプリに潜む、ちょっとした「解釈のズレ」を突く面白い攻撃、「HTTPパラメータ汚染(HPP)」についてお話しします。
専門用語を聞くと身構えてしまうかもしれませんが、実はこれ、皆さんの家の「鍵」に例えると非常に分かりやすいんです。一歩ずつ、一緒に学んでいきましょう!
—
1. 泥棒は「解釈の差」を突いてくる
皆さんの家に、2種類の鍵がかかっていると想像してください。1つは最新の「指紋認証キー」、もう1つは昔ながらの「物理的な鍵」です。
泥棒はこう考えます。「指紋認証は厳しいけれど、物理的な鍵なら誰かが複製を持っているかもしれない」。もし、指紋認証のシステムと物理的な鍵の管理者が「どっちの判断を優先するか」で意見が食い違っていたらどうでしょう?
- 指紋認証担当: 「指紋が合わないから入れさせない!」
- 物理鍵担当: 「いや、物理鍵が正しいから開けてやるよ」
結果、泥棒は「物理的な鍵」さえあれば家に入れてしまいますよね。これが、Webの世界で起きる「HTTPパラメータ汚染(HPP)」です。
HTTPパラメータ汚染(HPP)とは?
Webブラウザからサーバーにデータを送るとき、同じ名前のパラメータを2回送ることがあります。
例えば、?user=admin&user=guest というように送ったとき、「Webサーバー(WAFなど)」は最初の方(admin)を見て、その後ろの「プログラム(バックエンド)」は後ろの方(guest)を採用する、といった「解釈のズレ」を悪用する攻撃手法です。
—
2. 実際に起きている「すり抜け」の例
例えば、送金システムのプログラムを考えてみましょう。あなたは「自分の口座から、指定した相手に送金する」機能を作りました。
// PHPの例: 受け取ったパラメータを処理する部分
$target_user = $_GET['user']; // 送金先を指定
$amount = $_GET['amount']; // 送金額を指定
// 本来ならここで「送金してよいか」を厳密にチェックする
// しかし、途中のチェックプログラムが「最初の一つ目」しか見ていなかったら?
攻撃者は、次のようなURLを送りつけます。
transfer.php?user=victim&user=attacker&amount=1000
- セキュリティチェック用プログラム: 「おっ、userは
victimだな。よし、許可しよう」 - 実際の送金プログラム: 「おっ、userは
attackerだな。じゃあattackerに送金しよう」
結果、あなたは許可していない相手に送金してしまう……これがHPPの恐ろしさです。
—
3. どうやって防げばいいの?
この攻撃を防ぐには、「解釈のズレ」をなくすことが一番の近道です。以下の対策を覚えておきましょう。
対策1:パラメータは「一つ」と決めておく
開発段階で、「このパラメータには重複を許さない」という設計を徹底します。もし重複して送られてきたら、エラーを返すのが最も安全です。
// PHPでの対策例
$user_params = $_GET['user'];
// 配列になっていたら、それは「重複している」と判断して拒否する
if (is_array($user_params)) {
die("不正なアクセスです。パラメータは重複できません。");
}
対策2:WAF(Web Application Firewall)を賢く使う
WAFはWebサイトの門番です。最近のWAFは「同じパラメータが複数来たらブロックする」という設定が可能です。
- 設定のヒント: WAFの設定で「重複パラメータの拒否(Reject Duplicated Parameters)」を有効にしましょう。これは、泥棒の入る隙を物理的に塞ぐ、非常に強力な防犯カメラのような役割を果たします。
対策3:フレームワークの標準機能に頼る
多くの現代的なWebフレームワーク(LaravelやDjangoなど)は、パラメータが重複した際の挙動が定義されています。「配列として受け取るか」「最後の一つだけを強制的に採用するか」が明確なので、勝手に解釈が変わるリスクを低減できます。
—
まとめ:セキュリティは「思い込み」を捨てることから
HTTPパラメータ汚染は、一見すると「そんな単純なミスする?」と思うかもしれません。しかし、大規模なシステムになればなるほど、「WAF担当」「フロントエンド担当」「バックエンド担当」で解釈がズレることは日常茶飯事なのです。
1. 「全てのプログラムが同じようにデータを解釈している」という前提を疑う
2. 重複データは即座に拒否する設計にする
3. WAFで入り口をしっかり閉める
この3つを守るだけで、あなたのプログラムは格段に強固になります。セキュリティは難しく考える必要はありません。まずは「泥棒ならどうやって隙を突くかな?」と、少しだけ意地悪な視点で自分のコードを見つめ直してみてください。
それでは、また次回の記事でお会いしましょう!安全な開発ライフを!
コメント