【テクニカル・上級編】HTTPヘッダーインジェクションの脆弱性と対策 – アプリケーションセキュリティ & 安全な開発防御ガイド

HTTPヘッダーインジェクション:プロトコル解釈の「隙間」を突く攻撃の解剖学

現代のWebアーキテクチャにおいて、SQLインジェクションやXSSは「過去の遺物」として対策が自動化されつつある。しかし、HTTPヘッダーインジェクション(CRLFインジェクション)は、プロトコル層の曖昧さと、アプリケーション層の楽観的な入力検証の狭間に潜む、極めて根深い脆弱性だ。

本稿では、単なる「入力値チェックをしましょう」という教科書的な教説を超え、HTTP/1.1の構造的脆弱性がどのようにしてキャッシュ汚染やセッションハイジャックへと昇華されるのか、その低レイヤのメカニズムを紐解く。

—

1. プロトコル仕様の境界線:CRLFの魔力

HTTPレスポンスヘッダーは、行末を示す \r\n (CRLF) によって区切られる。もし、アプリケーションが外部からの入力を適切にサニタイズせず、レスポンスヘッダーの一部に組み込んでしまった場合、攻撃者は \r\n を挿入することで、サーバ側のヘッダー終了を偽装し、その後に任意のヘッダーやレスポンスボディを自由に記述できる。

攻撃シナリオ:レスポンス分割(Response Splitting)

サーバーが以下のようなレスポンスを生成すると仮定しよう。

Set-Cookie: user_id=[入力値]

攻撃者が \r\nContent-Length: 0\r\n\r\nHTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n を注入すると、ブラウザおよび中間プロキシは、本来のレスポンスとは別に、攻撃者が構築した「偽のレスポンス」を受け取ることになる。これがWebキャッシュサーバー(VarnishやCloudFront等)を通過すると、キャッシュが汚染され、全ユーザーが攻撃者の送り込んだ悪意あるペイロードを閲覧する事態に陥る。

—

2. なぜ「ガードレイル」はすり抜けるのか

モダンなフレームワーク(Spring Boot, Express.js, Django等)は、すでにヘッダーへのCRLF挿入を防止するバリデーションを組み込んでいる。しかし、アーキテクトが陥る罠は「後段のプロキシ」にある。

盲点:透過型プロキシとリクエスト・スマグリング

現代の防御において最も恐ろしいのは、フロントエンドのWAF/プロキシと、バックエンドのアプリケーションサーバー間での「ヘッダーの解釈の差異(Desync)」だ。
WAFが「安全」と判断したヘッダーが、バックエンドで特定のプロトコル拡張(HTTP/2の疑似ヘッダーやチャンク転送の悪用)により、意図しない挙動を引き起こす。これは、単なる入力値チェックでは防げない。

推奨される防御アーキテクチャ

単純な文字列置換ではなく、信頼境界の厳格化が必要だ。

// Go言語における安全なヘッダー設定の例
func SetUserHeader(w http.ResponseWriter, cookieValue string) {
// 1. CRLFを徹底的に除去する正規化処理
// 単なる拒否ではなく、プロトコル構造を破壊する文字をホワイトリストベースで削除する
sanitizedValue := strings.ReplaceAll(cookieValue, “\r”, “”)
sanitizedValue = strings.ReplaceAll(sanitizedValue, “\n”, “”)

// 2. 認可済みの文字セットのみを許可する(正規表現によるバリデーション)
// 制御文字が含まれていないかをチェック
if !isValidHeaderValue(sanitizedValue) {
http.Error(w, “Invalid Header Value”, http.StatusBadRequest)
return
}

w.Header().Set(“Set-Cookie”, “user_id=”+sanitizedValue)
}

—

3. 生成AI時代の新たな脅威:プロンプトインジェクションとの交差点

現在、我々が直面しているのは、生成AIがWebアプリケーションのバックエンドとして組み込まれるケースだ。AIエージェントが生成した出力が、そのままHTTPヘッダーにセットされる場合、プロンプトインジェクションによってヘッダーが改ざんされるリスクがある。

監査の観点:

  • AIの出力は「外部入力」とみなせ: LLMの出力結果を、信頼できるデータソースとして扱ってはいけない。必ず「ヘッダー生成専用のサニタイズ層」を通すこと。
  • ヘッダーの型定義: OpenAPI定義等で、ヘッダー値に厳格な型(Regexパターン)を強制し、それを超える構造をパイプラインで遮断する「型ベースのガードレイル」の実装が不可欠だ。

—

4. 結び:防御は「観測」から始まる

HTTPヘッダーインジェクションの脆弱性を探す際、私は常に curl -v でのパケットダンプだけでなく、中間のプロキシがどの程度「寛容(Loose)」にパケットを解釈しているかを計測する。

セキュリティアーキテクトとして最も重要なのは、「自分のコードがどう動くか」ではなく、「プロトコルがどう解釈されるか」を疑うことだ。耐量子暗号(PQC)への移行期において、通信のセキュアなハンドシェイクが注目されているが、レイヤ7のHTTPヘッダーのような「古典的な脆弱性」は、システムの基盤が複雑化するほど、より見つけにくく、かつ致命的な影響を及ぼす。

脆弱性を根絶する唯一の道は、スタックの各層において「入出力の正規化」を徹底し、境界条件を過剰なまでに厳しく設定することにある。それが、我々エンジニアが守るべきプロフェッショナリズムの根幹である。

コメント

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