【実務・中級編】HTTPヘッダインジェクション:レスポンス分割攻撃 – アプリケーションセキュリティ & 安全な開発防御ガイド

HTTPヘッダインジェクション:その「改行」がシステムを崩壊させる

現場でインシデント対応をしていると、意外なほど見落とされているのが「HTTPヘッダインジェクション」だ。最近はフレームワークの進化で自動的にサニタイズされるケースも増えたが、独自実装のプロキシや、古いレガシーな管理画面、あるいはAPIのレスポンス構築で、今なお致命的な穴を見かけることがある。

今日は、教科書的な説明は抜きにして、なぜこれが怖いのか、そしてどうコードで封じ込めるかを徹底的に解説しよう。

—

1. なぜ「改行」一つが致命的なのか

HTTPレスポンスは、Key: Value\r\n という形式でヘッダが並び、最後に \r\n\r\n が来てボディが始まるという厳格なプロトコルルールがある。

もし、攻撃者が入力値として「改行コード(\r\n)」を送り込み、それがそのままレスポンスヘッダに反映されたらどうなるか?

攻撃者は、本来存在しないヘッダ(Set-Cookieなど)を捏造したり、最悪の場合、HTTPレスポンス分割(HTTP Response Splitting)によって、偽のコンテンツをブラウザにレンダリングさせることが可能になる。

攻撃のイメージ:
ユーザー入力値: value\r\nSet-Cookie: session_id=evil_id\r\n\r\n...攻撃用スクリプト...

これをサーバーがそのまま出力すれば、ブラウザは「2つのレスポンスが届いた」と誤認し、偽のページを正規のドメイン上で表示してしまう。クロスサイトスクリプティング(XSS)の踏み台にされるリスクを想像してほしい。

—

2. セキュアな実装:コードで防ぐ(防御の鉄則)

根本的な対策は、「外部からの入力値を、改行コードを含んだままヘッダに出力しない」ことだ。多くの言語で、ヘッダセット時に改行が含まれているかをチェックする設計が必要になる。

PHPでの実装例

PHPの場合、header() 関数自体が改行混入を防ぐよう進化しているが、古いコードベースやライブラリをラップする場合は明示的な排除が不可欠だ。

  • セキュアにヘッダを設定するラッパー関数
  • /
    function safe_header($name, $value) {
    // 改行コード(CR: \r, LF: \n)を削除・置換する
    // そもそも改行が含まれる入力は拒絶するのが最も安全
    $clean_value = str_replace([“\r”, “\n”], ”, $value);

    // ヘッダを送信
    header(“{$name}: {$clean_value}”);
    }

    // 利用例:ユーザー入力をそのままヘッダにしない
    $user_input = $_GET[‘redirect_url’];
    safe_header(‘Location’, $user_input);

    Python (Flask) での実装例

    Flaskなどのフレームワークでは make_response を使い、ヘッダを辞書型で渡すのが定石だ。ここでも入力値のバリデーションを挟む。

    from flask import Flask, make_response, request
    import re

    app = Flask(__name__)

    @app.route(‘/redirect’)
    def redirect_user():
    url = request.args.get(‘url’, ‘/’)

    # 改行コードが含まれていたらエラーとする(ホワイトリスト形式が望ましい)
    if re.search(r'[\r\n]’, url):
    return “Invalid Header Value”, 400

    response = make_response(“Redirecting…”, 302)
    response.headers[‘Location’] = url
    return response

    —

    3. インフラ側で叩き潰す(多層防御)

    アプリ側がどうしても改行を許容せざるを得ないレガシーな仕様だったとしても、WebサーバーやWAFでトラフィックをフィルタリングするという最後の砦がある。

    Nginxによるブロック設定

    Nginxの ngx_http_headers_module を使っている場合、改行を含むリクエストを拒否するように設定できる。

    nginx.conf の http または server ブロック内に記述
    ヘッダに改行コードが含まれるリクエストを不正として弾く
    (基本的にはWAFで行うべきだが、エッジで止めるための防壁)
    if ($http_user_agent ~ “[\r\n]”) {
    return 400;
    }

    AWS WAF (Managed Rules) の活用

    AWS WAFを利用しているなら、「Core rule set」に含まれる「HTTP Header Injection」系のシグネチャを有効にするだけで、多くの攻撃パターンを自動的にブロックできる。これを使わない手はない。

    —

    まとめ:セキュリティの「勘所」

    いいか、現場で最も危険なのは「これくらいなら大丈夫だろう」という慢心だ。

    1. 入力値はすべて疑え: ヘッダ値として受け取るデータに、改行や制御文字が混じっていないか?
    2. サニタイズより拒絶: 改行が含まれていたら「不正なリクエスト」としてエラーを返すのが一番の防御だ。
    3. WAFは最後の砦: アプリのコードはいつか古くなる。インフラ側で共通の脅威を遮断する多層防御を忘れるな。

    セキュリティとは、完璧な製品を買うことではなく、「どう壊されるか」を想像し、その壊れ方を未然に塞ぎ続ける日々の積み重ねだ。今日のコードをコミットする前に、もう一度「もしここに改行が入ったら?」と考えてみてほしい。それだけで、君たちのシステムは格段に堅牢になるはずだ。

    コメント

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