「鍵をかけたはずなのに…」 HTTPパラメータ汚染(HPP)という見えない侵入者
こんにちは。セキュリティの世界に足を踏み入れたばかりの皆さん、ようこそ。
今日は、一見完璧に見える防犯システムが、なぜか「解釈のズレ」だけで破られてしまうという、ちょっと意地悪で、でも非常に面白い攻撃手法についてお話しします。その名も「HTTPパラメータ汚染(HTTP Parameter Pollution: HPP)」です。
セキュリティ用語ってどうしても難しく聞こえますよね。でも大丈夫。「家」を例にして、一緒に紐解いていきましょう。
—
1. HPPって何?:二人の「番人」の解釈が違う時
想像してみてください。あなたは自分の家の玄関に、とても厳重な「警備員(WAF:Webアプリケーションファイアウォール)」を立たせました。
あなたの家には「訪問者のID(パラメータ)」をチェックするルールがあります。ルールは「IDは一つしか受け取らない」です。
ところが、もしあなたが同じパラメータを2回送ったらどうなるでしょう?
- 警備員(WAF):「おっと、IDが2つあるな。最初のIDだけ見て、後は無視しよう(最初の値を採用)」
- 家の中の家族(バックエンドサーバー):「おっ、IDが2つある!最後の方が最新の情報だろうから、こっちを使おう(最後の値を採用)」
この「警備員」と「家族」の意見の食い違いこそが、HPPの正体です。攻撃者は、警備員には「安全なID」を見せつつ、家の中の家族には「悪意あるコマンド」をこっそり届けようとするのです。
2. なぜこれが危険なの?:SQLインジェクションとの合わせ技
例えば、ユーザーのIDを検索するプログラムがあるとします。
- 正常なリクエスト:
?id=123 - 攻撃者のリクエスト:
?id=123&id=SELECT FROM users--
WAFは「123」を見て「よし、これは数字のIDだな、安全だ!」と判断します。しかし、バックエンド側が後ろの id=SELECT... を採用してしまったらどうなるでしょう?
データベースに対して「ユーザーID 123を検索しつつ、全ユーザー情報を抜き出せ」という命令が実行されてしまうのです。これが、インジェクション攻撃への「裏口」を作ってしまう仕組みです。
—
3. どうやって防げばいいの?:「共通言語」を持つこと
この攻撃を防ぐための鍵は、「誰がどう解釈するか」を統一することです。
① WAFの「正規化」を正しく設定する
WAFが「パラメータが重複していたら、どう処理するか」を明確に設定しましょう。多くのWAFには、重複したパラメータを拒否したり、最初や最後の値を強制的に固定したりする機能があります。
設定のポイント(例:Nginx等のプロキシ設定)
重複したパラメータをブロックする設定のイメージ
悪意ある重複を許さず、エラーを返すのが一番の近道です
if ($query_string ~ “id=.&id=”) {
return 403; # 許可されていない形式なので門前払い!
}
② アプリケーション側で「リスト」として受け取る
開発者として一番確実なのは、サーバー側で「重複している」という事実を検知することです。
悪い例(PHPのイメージ)
// 単一の値として受け取ると、言語の仕様で「最後」が優先され、攻撃を許す
$id = $_GET[‘id’];
良い例(対策済み)
// パラメータが配列かどうかを確認し、想定外なら処理を止める
if (is_array($_GET[‘id’])) {
// ログに記録して警告!
die(“不正なリクエストです。”);
}
$id = $_GET[‘id’];
—
4. 現場からのアドバイス:完璧を求めすぎない勇気
新人の皆さんが現場でまずやるべきことは、「自分のアプリケーションが、重複したパラメータをどう解釈しているか」をテストしてみることです。
- Python (Flask/Django) はどう動く?
- Java (Spring) はどう動く?
- PHP は?
言語やフレームワークによって「最初の値を取る派」と「最後を取る派」が分かれます。この違いを知っているだけで、あなたが見るコードの「危なっかしさ」にすぐに気づけるようになります。
最後に:セキュリティは「疑うこと」から始まる
HPPのような攻撃は、システムが複雑になればなるほど見えなくなります。でも、「ここの値、もし2回送られてきたら誰がどう判断するんだろう?」と一歩立ち止まって考えるだけで、あなたはもう立派なエンジニアです。
セキュリティは、一度の完璧な設定で終わるものではありません。日々の小さな「なぜ?」を積み重ねて、強固な城を築いていきましょう!
何か分からないことがあれば、いつでも聞いてくださいね。一緒に学んでいきましょう!
コメント