【実務・中級編】 HTTPヘッダーインジェクションの仕組みとレスポンス分割攻撃 – オフェンシブセキュリティ & リバースエンジニアリング防御ガイド

HTTPヘッダーインジェクション:改行コードが生む「レスポンス分割」という悪夢

現場でコードをレビューしていると、いまだに「ユーザーの入力値をそのままレスポンスヘッダーに突っ込む」という背筋が凍るような実装に出くわすことがある。

Webアプリの脆弱性というと、どうしても XSS や SQLインジェクション に目が向きがちだが、HTTPヘッダーインジェクションは「システムの根幹」を揺るがすポテンシャルを秘めている。今日は、この一見地味だが破壊力抜群な脆弱性について、攻撃者の視点からその裏側を解説する。

—

1. 攻撃の仕組み:CRLFが境界線を崩す

HTTPヘッダーは、各行が CRLF(\r\n)で区切られている。もし攻撃者が入力値にこの CRLF を忍び込ませることができれば、Webサーバーやブラウザを騙し、サーバーが意図しない「偽のヘッダー」や「偽のレスポンスボディ」を挿入させることが可能になる。

具体的な攻撃イメージ

例えば、リダイレクト先のURLをユーザー入力から生成している場合を考えよう。

Location: /redirect?url=ユーザー入力値

ここで攻撃者が url パラメータに以下のような値を仕込んだらどうなるか。

http://example.com/search?q=test%0d%0aSet-Cookie:session_id=attacker_controlled_value

サーバーがこれをそのままレスポンスヘッダーに流し込むと、ブラウザは次のように解釈する。

HTTP/1.1 302 Found
Location: /redirect?url=test
Set-Cookie: session_id=attacker_controlled_value
...

これが「HTTPレスポンス分割(HTTP Response Splitting)」の基本だ。セッションIDを固定してユーザーを乗っ取ったり、キャッシュサーバーを汚染して偽コンテンツを世界中に配信させることも容易になる。

—

2. 実践:絶対にやってはいけない実装(PHP例)

まずは「なぜ脆弱なのか」を理解するために、典型的なNGコードを見てほしい。

<?php
// ユーザーからの入力を受け取る
$target_url = $_GET['url'];

// 危険!入力値のバリデーションを行わず、そのままヘッダーに含めている
header("Location: " . $target_url);
?>

このコードは、改行コードの有無を全くチェックしていない。PHPの header() 関数は、渡された文字列に改行が含まれていても、それをそのままHTTPストリームに流し込んでしまう性質がある。

—

3. 防御の鉄則:実装レベルでの対策

この脆弱性を防ぐための黄金律はただ一つ。「外部入力をヘッダーに直接含めない」ことだ。どうしても必要な場合は、徹底的なサニタイズを行う必要がある。

PHPでの安全な実装例

PHP 5.1.2以降であれば、header() 関数自体が改行を含むヘッダーの送信をブロックするようになったが、依存しすぎるのは危険だ。自前でチェックを入れよう。

<?php
$target_url = $_GET['url'];

// 1. 改行コード(CR, LF)が含まれていないか厳密にチェックする
if (preg_match("/[\r\n]/", $target_url)) {
    // 不正な入力とみなし、エラーを返すかリダイレクトを中止する
    http_response_code(400);
    die("不正なリクエストです。");
}

// 2. 許可されたURLのみにリダイレクトさせる(ホワイトリスト方式)
$allowed_hosts = ['example.com', 'myapp.internal'];
$parsed = parse_url($target_url);

if (!isset($parsed['host']) || !in_array($parsed['host'], $allowed_hosts)) {
    die("許可されていないホストへのリダイレクトです。");
}

header("Location: " . $target_url);
?>

—

4. インフラ・ミドルウェア層での防御

開発段階のミスをカバーするため、WebサーバーやWAFの設定で多層防御を敷くことが重要だ。

Nginxによる改行コードのブロック

Nginxはデフォルトで改行を含むヘッダーを拒否するように設計されているが、設定で明示的に防御を強化できる。

# nginx.conf
# HTTPレスポンスヘッダーに含まれる制御文字をフィルタリングする設定
# 基本的に最新のNginxはCRLFインジェクションに対して強いが、設定を確認すること
ignore_invalid_headers on;

WAF(AWS WAF等)でのルール設定

AWS WAFを利用している場合、HTTP Request Header に対する検査ルールを追加し、改行コード(%0d, %0a)が含まれるリクエストをブロックするルールを構成すべきだ。

  • ルール条件: String match を利用
  • 対象: Header(必要に応じて全てのヘッダーを検査)
  • マッチングパターン: \r, \n, %0d, %0a を含むリクエストを拒否

—

最後に:セキュリティは「疑うこと」から始まる

HTTPヘッダーインジェクションは、単なるバグではなく「HTTPプロトコルの解釈の隙間」を突く、極めてロジカルな攻撃だ。

現場のエンジニア諸君に伝えたいのは、「APIやフレームワークがよしなにやってくれるだろう」という楽観的な期待こそが、最大のリスクであるということだ。ユーザーから受け取るデータは、たとえURLの一部であっても「敵の武器になり得る」という前提でコードを書いてほしい。

もし、今運用しているシステムで心当たりがあるなら、すぐにログを確認し、入力値のバリデーションを見直してほしい。それが明日、あなたのサービスが乗っ取られるのを防ぐ唯一の道だ。

コメント

タイトルとURLをコピーしました