本記事は学習用です。作成には ChatGPT と GitHub Copilot を使用しています。
1. 概要と目的
HTTPヘッダインジェクションは、アプリケーションがユーザー入力を検証せずに HTTP レスポンスのヘッダ値へ直接組み込むときに発生する脆弱性の総称です。攻撃者は改行(CRLF、\r\n)や特殊文字を注入してレスポンス構造を分断し、新しいヘッダを作成したり、レスポンス本文を書き換えたりできます(HTTP Response Splitting / CRLF Injection)。これにより、クロスサイトスクリプティング(XSS)、キャッシュポイズニング、セッション固定、悪意あるリダイレクトなど多様な攻撃につながります。基礎知識を整理し、検出法と現場で使える対策を示すことを目的とします(参考: OWASP Foundation)。
2. 定義・背景(用語定義を含む)
- HTTPヘッダ: サーバとクライアントがメッセージに付加する「名前: 値」のペア。HTTP/1.x はヘッダ行を CRLF で区切ります(参考: MDN Web Docs)。
- CRLF(Carriage Return + Line Feed):
\r\n(16進では 0x0D 0x0A)。HTTP ではヘッダ行の区切り・ヘッダと本文の区切りに使われ、CRLF を不正に挿入されるとレスポンスを分割可能(参考: Wikipedia)。 - HTTP Response Splitting: アプリが未検証入力をヘッダに入れ、攻撃者が CRLF を使って「複数レスポンス」や「改ざんレスポンス」を生成する攻撃(参考: OWASP)。
- Host ヘッダインジェクション(Host Header Injection): リクエストの
HostやX-Forwarded-Host等を悪用し、サーバの処理や URL 生成に影響を与える手法。逆プロキシやメール本文生成に影響(参考: OWASP WSTG)。
なぜ問題か(背景)
ヘッダはレスポンスの動作(リダイレクト、Cookie 設定、キャッシュ制御など)を左右します。この経路を制御されるとクライアント挙動の改変、情報漏えい、セッション乗っ取り、キャッシュを悪用した攻撃につながり得ます。実際に古いライブラリや誤った実装で多数の CVE や CWE が報告されています(参考: CWE-113)。
3. 攻撃手法(具体例と手順)
ここでは実際にどのように攻撃が成立するか、短いコード例とともに示します。
3.1 基本的な脆弱コード(PHP の例)
<?php
// 脆弱なリダイレクト
$url = $_GET['url']; // 想定: https://example.com/page
header("Location: $url");
exit;
?>
この $url に %0d%0aSet-Cookie: session=attacker のようなエンコード済み CRLF が入ると、サーバがそれをそのままヘッダに挿入し、新たなヘッダや空行で本文を制御される可能性があります(挙動は環境とランタイム次第)。実際のペイロードは http://victim.com/%0d%0aSet-Cookie:%20session=attacker のように送ります(URL エンコードで %0d%0a、参考: PortSwigger)。
3.2 Node.js / Express の注意点(示唆)
多くのランタイムやフレームワークは既知の CRLF 注入を防ぐ保護を入れており、ヘッダ値に改行が含まれると例外で拒否する実装もあります。ただし、アプリ側で独自にヘッダを組み立てたり、未エスケープの値を res.setHeader() 等に渡すと危険です。各ランタイムのバージョンと既知の脆弱性情報を確認してください(参考: OWASP WSTG)。
3.3 手順(攻撃者側)
- ユーザー入力がレスポンスヘッダに入る箇所を探す(リダイレクト、Set-Cookie、Location、Content-Disposition など、参考: PortSwigger)。
- 入力に生の改行(
\r\n)または URL エンコード(%0d%0a)を混ぜたペイロードを送る。 - ヘッダに改行が通る場合、新ヘッダの挿入やヘッダ/本文の分割が可能になり、目的に応じて XSS、Cookie 注入、キャッシュ汚染、メールヘッダ注入が実行できる(参考: Imperva)。
4. 影響(具体的な攻撃例と根拠)
下表は代表的な影響と簡単な説明です。
| 影響 | 仕組み | 実害例 |
|---|---|---|
| XSS(反射型) | 悪意の HTML をレスポンス本文に挿入できる | フォームを改ざんしスクリプトを実行 |
| Cookie 注入/セッション固定 | Set-Cookie を挿入してセッションを固定 | 被害者が攻撃者管理のセッション ID でログイン |
| キャッシュポイズニング | キャッシュされるレスポンスを攻撃者が制御 | 他ユーザに改ざんコンテンツが配信される |
| オープンリダイレクト/フィッシング | Location を書き換え外部へ誘導 | 正規サイトからの信頼を利用した詐欺 |
| メールヘッダ注入(SMTP) | 類似の CRLF 注入でメールヘッダ操作 | スパム送信やメール改ざん |
これらは OWASP や PortSwigger の解説で確認されている典型的被害です(参考: OWASP)。
実際の事例(CWE/CVE 等)
過去の CVE や CWE-113(CRLF シーケンスを正しく無害化しないこと)に多数の事例があり、古いライブラリや自前のヘッダ生成ロジックが原因になっているものがあります(参考: CWE-113)。
5. 検出とテスト手法(現場で使う手順)
5.1 手動テスト(簡易)
- 影響しそうなパラメータ(
url,filename,redirect,lang等)を列挙。 - ペイロード例を順に試す(生の改行は送れない場合があるため URL エンコードを併用)。例:
%0d%0aX-Injected: injected\r\nContent-Length: 0\r\n\r\n<h1>INJECTED</h1>(環境により拒否/無害化の可能性)
- レスポンスのヘッダと本文を観察し、新しいヘッダ/意図しない本文が現れるか確認(参考: PortSwigger)。
5.2 自動診断ツール
Burp Suite(Intruder/Scanner)、OWASP ZAP、各種 SAST/DAST ツールは CRLF/ヘッダ注入の検出ルールを持ちます。CI に組み込み定期スキャンを行うとよいです。Mozilla Observatory 等でヘッダ設定の健全性もチェックできます(参考: Mozilla Observatory)。
5.3 検出の注意点
- プロキシ、ロードバランサ、CDN などが前段にあると挙動が変わる(ヘッダが正規化・無害化される場合あり)。検査は実運用に近い経路で実施(参考: OWASP WSTG)。
攻撃フロー(Mermaid で概念図)
6. 防御と対策(実務で使う具体手順)
対策は受け入れる入力を厳しく限定(ホワイトリスト)し、ヘッダに使用する値は常に「無害化(制御文字の拒否など)」することが基本です。以下、実践的対策を列挙します。
6.1 原則(優先順位)
- ホワイトリスト化: 想定値(ドメイン、パス、数値、トークン等)だけ受け入れる。
- 改行(CR/LF)の拒否: ヘッダに入る可能性のある入力から
\rと\nを必ず拒否(置換ではなくエラー)。 - エンコード/安全 API の利用: URL を埋め込む場合は適切なエンコード関数(言語/フレームワーク標準)を用いる。ヘッダ値は制御文字を拒否し、フレームワークの安全な API を使用(独自文字列連結は避ける)。
- フレームワーク機能活用: 安全なリダイレクト・ヘッダ設定関数を提供している機能を用いる。
6.2 実装パターン(コード例)
PHP: 安全なリダイレクト例(ホストをホワイトリスト)
<?php
$allowed_hosts = ['example.com', 'www.example.com'];
$raw = $_GET['url'] ?? '';
$parsed = parse_url($raw);
if ($parsed !== false
&& isset($parsed['scheme'], $parsed['host'])
&& in_array(strtolower($parsed['host']), $allowed_hosts, true)
&& in_array(strtolower($parsed['scheme']), ['https', 'http'], true)) {
// ヘッダ値に使う前に CR/LF を拒否(検出で 400)
if (strpos($raw, "\r") !== false || strpos($raw, "\n") !== false) {
http_response_code(400);
echo 'Invalid redirect';
exit;
}
// 妥当な URL のみ許可(必要に応じてパス/クエリの正規化を追加)
$safeUrl = filter_var($raw, FILTER_VALIDATE_URL);
if ($safeUrl !== false) {
header('Location: ' . $safeUrl);
exit;
}
}
http_response_code(400);
echo 'Invalid redirect';
?>
ポイント: ホストのホワイトリスト + CR/LF の拒否 + FILTER_VALIDATE_URL による妥当性検証を組み合わせる(必要に応じて相対パス限定などにする)。
一般的な無害化(擬似コード)
function safeHeaderValue(value):
// 制御文字の拒否(SP=0x20〜~=0x7E の可視 ASCII のみ許可する例)
if not matches(value, '^[\x20-\x7E]*$'):
reject() // 明示的に拒否(ログに記録)
return value
6.3 サーバ/プロキシ側の防御
- フロントのロードバランサや WAF で不正ヘッダ(CRLF)をフィルタリング。
- 不要なヘッダ(
X-Powered-By等)を削除して攻撃面を減らす。 - セキュリティヘッダ(CSP、HSTS 等)を適切に設定し、万一の影響を抑える(参考: OWASP Cheat Sheet)。
6.4 開発プロセスに組み込むこと
- ライブラリ/フレームワークの脆弱性情報を継続的に追跡し、ランタイムのセキュリティ修正を適用(古いランタイムは既知の脆弱性を含む場合あり)。
- 自動スキャン(SAST/DAST)と手動レビューを組み合わせる。入力検証ルールをユニットテスト化。
7. よくある誤りと注意点
- エスケープだけで安心しない: 単純な文字置換(
\nを空文字に)では抜け漏れが残る場合がある。可能な限りホワイトリストで拒否(参考: CWE-113)。 - 前段のプロキシで“正規化”される場合の見落とし: 検査環境と実運用経路が異なると検出漏れを起こす。必ずプロダクションに近い経路で検査(参考: OWASP WSTG)。
- 既存ライブラリの実装依存: ランタイム/フレームワークの「自動無害化」に頼る場合、バージョン差で動作が変わるため、該当バージョンの挙動を確認。
8. まとめ(実務チェックリスト)
- ヘッダに入るユーザー入力は原則ホワイトリスト化する。
- ヘッダ値から
\rと\nを拒否し、必要なら安全な API を使う。 - リダイレクトやファイル名生成など「ヘッダを生成する箇所」は設計レビューで明示する。
- ランタイム/フレームワークのセキュリティアップデートを適用する。
- 自動・手動の双方で検査し、CI に脆弱性スキャンを組み込む(参考: OWASP Cheat Sheet)。
A. 参考サイト(検証済み・読みやすい順)
- OWASP — HTTP Response Splitting / CRLF Injection(概説と対策)(OWASP Foundation)
- MDN Web Docs — HTTP headers(仕様・ヘッダの書式)(MDN Web Docs)
- PortSwigger — HTTP response header injection(攻撃・検出の実例)(PortSwigger)
- OWASP Web Security Testing Guide — Testing for Host Header Injection(検査手順)(OWASP Foundation)
- MITRE — CWE-113: Improper Neutralization of CRLF Sequences(CWE の定義と事例)(cwe.mitre.org)
- OWASP HTTP Headers Cheat Sheet(推奨ヘッダ設定一覧)(cheatsheetseries.owasp.org)
- Mozilla Observatory — HTTP Header Security Test (Mozilla Observatory)

コメント