Desync Attacks: Request Smugglingの邪悪な双子 🔗

HTTPパースの脆弱性の闇の側面を理解する
HTTPのデシンク攻撃は、近年発見された最も高度で危険なWebアプリケーションの脆弱性の一つです。従来のrequest smugglingは2000年代初頭から知られていましたが、現代のデシンク攻撃はより複雑で危険な脅威へと進化し、HTTPプロトコルの曖昧さを突いてセキュリティ制御を回避し、ユーザーセッションを乗っ取り、Webキャッシュを汚染します。
HTTPデシンク攻撃とは?
HTTPデシンク、一般的にはHTTP request smugglingと呼ばれるものは、フロントエンドとバックエンドのサーバーがHTTPリクエストの終了位置について意見が一致しない場合に発生します。この基本的なパーサーの不一致は、攻撃者が悪意のあるリクエストを接続ストリームに注入し、不正なコマンドをセキュリティメカニズムをすり抜けて「密輸」できる重大な脆弱性を生み出します。
HTTPデシンクの根本原因はパーサーの不一致であり、これは異なるシステムがHTTPリクエストを解釈する方法の違いに起因します。攻撃者が曖昧な境界マーカーを含むリクエストを送信すると、プロキシチェーン内の異なるサーバーがそれを異なる方法で処理し、request smugglingの機会を生み出します。
従来のrequest smugglingは特別に作成された悪意のあるリクエストを必要としましたが、現代のデシンク攻撃はブラウザを利用した技術も含み、完全に正当なHTTP/1.1リクエストを使用します。これにより、サーバー側のrequest smuggling攻撃やクライアント側のデシンク攻撃の新たな脅威クラスが生まれています。
HTTP/1.1の致命的な欠陥の解剖
HTTP/1.1の仕様には、デシンク攻撃を可能にする根本的な弱点があります。それは、メッセージ境界を指定するための2つの異なる方法を提供している点です。
Content-LengthとTransfer-Encoding
この脆弱性は、2つの競合するヘッダー機構に由来します:
Content-Lengthヘッダー:メッセージ本文の正確なサイズをバイト単位で指定します。このヘッダーが存在する場合、サーバーは正確にそのバイト数を読み取り、リクエストを完了とみなします。
Transfer-Encoding: chunked:メッセージ本文を複数のチャンクに分けて送信でき、各チャンクは16進数のサイズで前置きされます。最後はゼロ長のチャンクで終了します。
HTTP request smugglingの脆弱性は、フロントエンドとバックエンドのサーバーがリクエストの境界を決定するために異なるメカニズムを使用している場合に発生します。両方のヘッダーが1つのリクエストに存在すると、サーバーの実装によって優先されるヘッダーが異なり、不整合を生じさせます。
主要な攻撃ベクトル3つ
1. CL.TE (Content-Length / Transfer-Encoding)
この攻撃バリアントでは、フロントエンドサーバーはContent-Lengthヘッダーを処理し、バックエンドはTransfer-Encodingヘッダーを使用します。攻撃者は次のようなリクエストを作成します:
- フロントエンドはContent-Lengthに基づき特定のバイト数を読み取る
- バックエンドは同じデータをchunkedエンコーディングとして解釈
- 残りのバイトは新しいリクエストの開始とみなす
POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 13
Transfer-Encoding: chunked
0
SMUGGLED
バックエンドはTransfer-encodingヘッダーを処理し、メッセージ本文をchunkedとみなして最初のチャンク(ゼロ長とされる)を処理します。”SMUGGLED”のバイトは未処理のままで、新たなリクエストとして扱われます。
2. TE.CL (Transfer-Encoding / Content-Length)
このバリアントは処理順序を逆にします:
- フロントエンドはTransfer-Encodingを使用しチャンクを処理
- バックエンドはContent-Lengthを使用し固定バイト数を読み取る
- 攻撃者は”残り”のチャンクデータに追加リクエストを密輸できる
POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 3
Transfer-Encoding: chunked
8
SMUGGLED
0
フロントエンドは両方のチャンクを完全に処理しますが、バックエンドはContent-lengthヘッダーを見てリクエスト本文が3バイトであると判断し、その後のバイトは未処理のまま次のリクエストの開始と解釈されます。
3. TE.TE (Transfer-Encodingの難読化)
このタイプのHTTP request smugglingでは、フロントエンドとバックエンドの両方がTransfer-Encodingヘッダーを使用しますが、そのヘッダーが難読化されている場合、一方のサーバーは無視し、もう一方は処理します。
攻撃者はヘッダーの微妙なバリエーションを利用します:
Transfer-Encoding: xchunked
Transfer-Encoding : chunked
Transfer-Encoding: chunked
Transfer-Encoding: x
Transfer-Encoding:[tab]chunked
これらのバリエーションは、HTTP仕様の厳格な準拠からわずかに逸脱しており、サーバーの実装によって一貫性が異なります。
Chunkedエンコーディングの悪用技術
Chunk Extensionの乱用
最近発見された新しいHTTP request smuggling技術では、攻撃者はフロントエンドのプロキシサーバーとバックエンドのアプリケーションサーバー間のパースの不一致を突いて、曖昧なリクエストフォーマットを利用します。
HTTP/1.1では、チャンクサイズの後にオプションの拡張子を付けることが可能です。これらの拡張は実務ではほとんど使われず、多くの実装が緩やかまたは誤って処理します。攻撃者は次のように仕掛けます:
- セミコロンで終わるチャンクサイズ行を送信(拡張子名なし)
- フロントエンドのパーサーは不正な拡張子を無視
- バックエンドのパーサーはセミコロンの後の改行をチャンクヘッダーの終わりと解釈
- 攻撃者はゼロ長チャンクの後に2つ目のHTTPリクエストを埋め込む
POST / HTTP/1.1
Host: vulnerable-website.com
Transfer-Encoding: chunked
0;
GET /admin HTTP/1.1
Host: localhost
フロントエンドは全体を1つのリクエストとみなしますが、バックエンドはGET /adminを別の有効なリクエストと処理します。
ファンキーなチャンクとTE.0の脆弱性
最新の研究では、誤ったチャンクエンコーディングを利用した高度な技術も明らかになっています。2024年にはTE.0やファンキーなチャンクの脆弱性に対する耐性が重要視され、2025年にはExpect-basedや0.CL攻撃に対する免疫が確認され、報酬も$350,000超となっています。
これらの攻撃は、サーバーが次のような場合にエッジケースを突きます: - 不正なフォーマットのチャンクを受け入れる - チャンク拡張を誤処理 - チャンク終端子を不整合に扱う
クライアントサイドのデシンク:ブラウザを利用した攻撃
最近のデシンク攻撃の重要な進展の一つは、クライアントサイドのデシンク(CSD)攻撃の発見です。クライアントサイドのデシンクは、被害者のWebブラウザを騙して、その接続をデシンクさせる攻撃であり、通常のrequest smugglingとは異なり、フロントエンドとバックエンドのサーバー間の接続をずらすものです。
クライアントサイドデシンクの仕組み
クライアントサイドのデシンクは、WebサーバーがPOSTやPUTリクエストに対して即座に応答し、本文の内容を事前に確認しない設定や誤設定時に発生します。脆弱性の流れは次の通りです:
- 攻撃者が悪意のJavaScriptを自ドメインにホスト
- 被害者が攻撃者のページを訪れる
- JavaScriptが被害者のブラウザに特別に作成されたリクエストを送信させる
- サーバーが本文を読まずに即座に応答
- ブラウザが次のリクエストに同じ接続を再利用
- 最初のリクエストの残留データが次のリクエストを汚染
この攻撃は特に危険です: - 単一サーバーアーキテクチャに対して有効(フロントエンド/バックエンド分離不要) - 完全にブラウザ互換のHTTP/1.1リクエストを使用 - same-originポリシーを回避可能 - クロスサイトリクエストフォージェリを完全にキャプチャ可能
一時停止ベースのデシンク攻撃
特定のサーバーが部分的なリクエストを処理し、完全に受信される前に中断した場合、15秒間何もデータが届かないとタイムアウトしますが、接続は閉じずに再利用されます。
攻撃者は次のように仕掛けます: 1. ボディを伴うリクエストヘッダーを送信 2. タイムアウトまで待つ 3. タイムアウト後にボディを送信 4. サーバーはこのボディを新しいリクエストとみなす
この技術は、Varnishのようなキャッシュサーバーに対して特に効果的です。
Keep-Alive接続の悪用
HTTPのkeep-alive接続は、パフォーマンス向上のためにTCP接続を再利用しますが、デシンクの攻撃面も増やします。HTTPサーバーとプロキシ間でのkeep-aliveの使用は少ないですが、使用時にはRequest Smugglingの問題が潜在します。
Keep-Aliveによる接続乗っ取り
keep-aliveが有効な場合: - 複数のリクエストが同じTCP接続を共有 - 接続状態がリクエスト間で維持される - パーサーのデシンクがその接続上のすべてのリクエストに影響
攻撃者は次のように仕掛けます:
- リクエストインジェクション:悪意のリクエストを密輸し、次のユーザーのリクエストのコンテキストで実行させる
- レスポンスキューの毒化:レスポンスキューをずらし、意図しないユーザーにレスポンスを返す
- 認証情報の窃取:次の正規リクエストの認証トークンを奪取
このトリックは、ストリームに部分的なクエリを注入し、通常のユーザークエリと同じバックエンド接続で待つことで成立します。
セッション乗っ取り:接続再利用による攻撃
2回目のクエリで使われる資格情報は、密輸されたクエリに奪われたり乗っ取られたりします。これにより、攻撃者はユーザーに不正なPOST操作をさせることも可能です。
攻撃の流れ: 1. 攻撃者が不完全なリクエストと密輸プレフィックスを送信 2. 被害者の正規リクエストが同じ接続に到達 3. 被害者のヘッダー(クッキーや認証トークン含む)が攻撃者の密輸リクエストに付加される 4. 攻撃者は被害者の認証済みセッションにアクセス
HTTP/2ダウングレード攻撃
現代のWebインフラは、クライアントとサーバー間でHTTP/2を使用しつつ、バックエンドではHTTP/1.1にダウングレードすることが一般的です。chunked transfer encodingはHTTP/2と互換性がなく、仕様では、挿入されたtransfer-encoding: chunkedヘッダーは削除またはリクエスト全体をブロックすべきと推奨しています。
H2.CLとH2.TE攻撃
フロントエンドサーバーがHTTP/2からHTTP/1.1への変換時にヘッダーの適切な除去や検証を行わない場合、攻撃者は:
- 禁止されたヘッダーを挿入し、プロトコルダウングレード後も残す
- HTTP/2のバイナリフォーマットを利用したCRLFインジェクション
- 疑似ヘッダーの操作によるリクエストの密輸
HTTP/2のメッセージはバイナリ形式のため、各ヘッダーの境界は明示的なオフセットに基づき、デリミタ文字は使用されません。これにより、CRLFは値の中に含めることができ、ヘッダーの分割を引き起こさずに済みます。ダウングレード後、これらのCRLFシーケンスはヘッダーの区切りとして解釈され、ヘッダーインジェクションやrequest smugglingを可能にします。
実世界の影響とケーススタディ
重大な脆弱性の公開
最新のセキュリティ研究により、主要なCDNやWebインフラの提供者に深刻な脆弱性が明らかになっています:
Black Hatで公開された新しい攻撃クラスは、HTTP/1.1の致命的な境界の弱点と複数の長さ指定方法を突いて、数千万のWebサイトを危険にさらしました。
これらの攻撃は次のことを可能にします: - サイト乗っ取り:Webアプリケーションの完全な乗っ取り - 認証情報の窃取:トークンやセッションCookieの盗難 - キャッシュ汚染:悪意のあるコンテンツの永続的なキャッシュ挿入
PayPalの事例
ある研究者は、Transfer-EncodingヘッダーがAkamaiのCDNに見えなくなる行折り込みヘッダーを利用し、PayPalのログインページを制御し、$20,000の報酬を獲得しました。
攻撃は次のように行われました:
Transfer-Encoding:
chunked
行折り込みによりAkamaiはヘッダーを無効とみなし無視しますが、バックエンドはこれを受け入れ、CL.TEのデシンクを引き起こしました。
Apache HTTP Serverの脆弱性
Apache HTTP Serverのバージョン2.4.63までには、TLSアップグレード中にHTTPデシンク攻撃やセッション乗っ取りを可能にする脆弱性が含まれていました。CVE-2025-49812は、TLSアップグレード機能を悪用してデシンク攻撃を行うもので、暗号化された接続も脆弱であることを示しています。
高度なエクスプロイト技術
レスポンスキューの毒化
最も深刻なデシンク攻撃の結果の一つはレスポンスキューの毒化です。デシンクが発生すると:
- 密輸リクエストがレスポンスを生成
- このレスポンスがキューに入り、誤ったクライアントに配信される
- 以降のレスポンスもずれていく
- その接続上のすべてのユーザーに誤ったレスポンスが返される
これにより: - 機密ユーザーデータの漏洩 - ユーザー間のセッション汚染 - 接続が閉じられるまで持続的な侵害
Webキャッシュ汚染
Responseの連結を利用し、Content-LengthとCache-Controlヘッダーを含むレスポンスを選択し、キャッシュに保存させることが可能です。
攻撃者は次の操作を行います: 1. HEADリクエストを密輸し、レスポンスヘッダーのみを生成 2. Content-Lengthヘッダーが完全なGETレスポンスのサイズを示す 3. プロキシが次のレスポンス(別ユーザーのリクエストに対する)を連結 4. 連結されたレスポンスが攻撃者の注入コンテンツとともにキャッシュされる 5. 以降のユーザーは汚染されたキャッシュレスポンスを受け取る
TRACEメソッドの悪用
TRACEメソッドはサーバーにTRACEリクエストに応答させる必要があります。これは通常デバッグ目的でのみ使用されるべきですが、request smugglingを利用してファイアウォールルールを回避し、直接バックエンドにTRACEメッセージを送ることも可能です。
この攻撃は反射型XSSを引き起こすこともあります:
POST / HTTP/1.1
Host: vulnerable.com
Content-Length: 6
Transfer-Encoding: chunked
0
TRACE / HTTP/1.1
Host: vulnerable.com
SomeHeader: scriptalert(1)/script
このレスポンスは注入されたスクリプトを反射し、次のユーザーに配信されます。
検出と識別
手動検出技術
クライアントサイドのデシンクを調べる最も簡単な方法は、Content-Lengthが実際の本文より長いリクエストを送ることです。リクエストがハングしたりタイムアウトした場合、サーバーは残りのバイトを待っています。即時応答が返る場合、CSDの可能性があります。
検出の流れ: 1. 再利用可能な接続を特定:HTTP keep-aliveをサポートするサーバーを探す 2. 境界のパースをテスト:矛盾するヘッダーを含むリクエストを送信 3. タイミング差を観察:遅延応答はデシンクの可能性を示す 4. リクエストの連結を確認:一つのリクエストの一部が別のリクエストに現れるか監視
自動ツールとスキャン
以下のツールはデシンクの脆弱性を検出するのに役立ちます:
- Burp Suite HTTP Request Smuggler Extension:CL.TE、TE.CL、TE.TEの脆弱性の自動検出
- smuggler.py:大量スキャン用CLIツール
- Burp Scanner:内蔵のデシンク検出機能
Burp ScannerとHTTP Request Smugglerは検出を自動化しますが、手動でも理解を深めるために重要です。
ブラウザベースのテスト
クライアントサイドのデシンクテストには:
Burp Suiteを経由しないブラウザを使用し、Chromeの開発者ツールのPreserve logやConnection ID列を有効にして、各リクエストに使用される接続を追跡します。
Fetch APIを使ったテスト例:
fetch('https://vulnerable-site.com', {
method: 'POST',
body: 'POST /internal HTTP/1.1\r\nHost: vulnerable-site.com\r\n\r\n',
headers: {
'Content-Length': '200'
}
});
防御戦略と緩和策
アーキテクチャ的解決策
1. HTTP/2のエンドツーエンド運用
HTTP request smugglingを防ぐために、HTTP/2をエンドツーエンドで使用し、可能ならダウングレードを無効にします。HTTP/2はリクエストの長さを決定する堅牢な仕組みを持ち、脆弱性に対して自然に保護されます。
HTTP/2は次の点でデシンクを排除します: - バイナリフレーミングを使用し、テキストパースを排除 - メッセージ境界の曖昧さを排除 - Content-LengthやTransfer-Encodingヘッダーを排除 - 厳格な多重化ルールを適用
2. 統一されたパースアーキテクチャ
Fastlyは、スタック全体で単一のパーサー実装を採用し、ミスマッチやエッジケースを排除してHTTPデシンクを防止しています。
重要な原則: - 一つのHTTPパーサーを全体で使用 - 異なるサーバーソフトウェアのバージョンを混在させない - 各層で厳格なリクエスト検証を行う - 曖昧なリクエストは即座に拒否
設定のベストプラクティス
接続再利用を無効化
バックエンド側: - フロントエンドとバックエンド間での接続再利用を避ける - 各リクエストごとに新しい接続を確立 - 応答後すぐに接続を閉じる
ヘッダーの厳格な検証
- Content-LengthとTransfer-Encodingの両方を含むリクエストを拒否
- RFC準拠を厳守
- 難読化されたヘッダーをブロック
- リクエストを正規化して転送
サーバーの堅牢化
Apache設定例:
# 曖昧なリクエストを拒否
RequestReadTimeout header=20-40,MinRate=500 body=20,MinRate=500
# keep-alive制限
MaxKeepAliveRequests 100
KeepAliveTimeout 5
# 厳格なプロトコル適用
HttpProtocolOptions Strict
Nginx設定例:
# request smugglingのベクトルを無効化
ignore_invalid_headers on;
client_body_buffer_size 1k;
client_header_buffer_size 1k;
client_max_body_size 1k;
Webアプリケーションファイアウォールルール
WAFルールを実装し: - 重複ヘッダーを検出・ブロック - chunkedエンコーディングの異常を監視 - 疑わしいヘッダーパターンを検知 - 不審なリクエストサイズにアラート
責任ある情報公開の後、全システムにセキュリティパッチが適用され、最新のソフトウェアを維持する組織はHTTP request smugglingの脆弱性から完全に保護されています。
監視と検出
次の点を監視: - 異常な接続パターン - 矛盾した長さ指定のリクエスト - 不審なchunkedエンコーディングシーケンス - レスポンスキューのずれ - キャッシュの挙動異常
デシンク攻撃の未来
新たな攻撃ベクトル
研究は新しいデシンク技術を継続的に発見しています:
- 0.CL攻撃:ゼロ長Content-Lengthヘッダーの悪用
- Expectヘッダー操作:100-Continueメカニズムの利用
- プロトコルチェーン:HTTP/2、HTTP/1.1、WebSocketアップグレードの組み合わせ
この分野はまだ研究途上であり、今後数年間にわたり新たなデシンク技術やエクスプロイトの発見が期待されています。
業界の対応
主要インフラ提供者は次の対策を進めています:
- より厳格なパースロジックの実装
- 統一パーサーアーキテクチャの展開
- 自動脆弱性スキャンの強化
- デシンク発見のバグバウンティ報酬増加
一部のロードバランサーは未修正のままですが、業界標準の厳格な規範により、攻撃クラス全体が排除されています。
結論
HTTPデシンク攻撃は、HTTP/1.1の仕様の根本的な曖昧さを突く高度な進化形です。chunkedエンコーディングの操作やkeep-aliveの悪用、ブラウザを利用したクライアントサイド技術を通じて、攻撃者はセキュリティ制御を回避し、セッションを乗っ取り、Webアプリケーションを大規模に侵害します。
これらの攻撃は特に危険です: - インフラ層を標的にし、アプリケーションロジックを直接攻撃しない - 伝統的なセキュリティメカニズムを回避 - キャッシュ汚染を通じて持続的な侵害を可能に - セキュアなアプリケーションにも効果的
組織は、アーキテクチャの変更(HTTP/2の採用)、厳格なパースの強制、接続の分離、継続的な監視を組み合わせたディープインフラ防御を採用すべきです。今後もWebインフラの進化に伴い、最新のデシンク研究に関する情報を常に把握し、適切にシステムを更新・設定することが、アプリケーションの安全性維持に不可欠です。研究コミュニティは新たな攻撃変種の発見を続けており、継続的な警戒と積極的な防御が必要です。
Related InstaTunnel pages
Continue from this article into the most relevant product guides and workflows.
Related Topics
Keep building with InstaTunnel
Read the docs for implementation details or compare plans before you ship.