HTTP/2ダウングレードにおけるリクエストスムージング

Reading time: 9 minutes

tip

AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE) Azureハッキングを学び、実践する:HackTricks Training Azure Red Team Expert (AzRTE)

HackTricksをサポートする

HTTP/2は一般的に古典的なリクエストスムージングに対して免疫があると考えられていますが、フロントエンドプロキシがリクエストをHTTP/1.xに「ダウングレード」してバックエンドに転送する際、その保護は消えます。異なる2つのパーサー(HTTP/2フロントエンドとHTTP/1バックエンド)が、1つのリクエストが終了し次のリクエストが始まる場所について合意しようとすると、古いデシンクトリックがすべて戻ってきます - さらにいくつかの新しいものも。


ダウングレードが発生する理由

  1. ブラウザはすでにHTTP/2を話しますが、古いオリジンインフラストラクチャはまだHTTP/1.1しか理解していません。
  2. リバースプロキシ(CDN、WAF、ロードバランサー)は、したがって、エッジでTLS + HTTP/2を終了し、すべてのリクエストをHTTP/1.1としてオリジンに書き換えます
  3. 翻訳ステップは、オリジンがボディの長さを決定できるようにするために、両方の Content-Length および/または Transfer-Encoding: chunked ヘッダーを作成する必要があります。

フロントエンドがHTTP/2フレームの長さを信頼しているが、バックエンドがCLまたはTEを信頼している場合、攻撃者はそれらが不一致になるように強制できます。


2つの主要なプリミティブクラス

バリアントフロントエンドの長さバックエンドの長さ一般的なペイロード
H2.TEHTTP/2フレームTransfer-Encoding: chunked最終的な 0\r\n\r\n送信されない追加のチャンクメッセージボディを埋め込むことで、バックエンドは攻撃者が提供した「次の」リクエストを待ちます。
H2.CLHTTP/2フレームContent-Length実際のボディよりも小さいCLを送信することで、バックエンドは境界を越えて次のリクエストを読み取ります。

これらは、古典的なTE.CL / CL.TEと精神的に同じであり、単にHTTP/2がパーサーの1つを置き換えています。


ダウングレードチェーンの特定

  1. TLSハンドシェイクでALPNを使用する(openssl s_client -alpn h2 -connect host:443)またはcurl:
bash
curl -v --http2 https://target

* Using HTTP2が表示される場合、エッジはH2を話します。 2. 意図的に不正なCL/TEリクエストをHTTP/2経由で送信します(Burp RepeaterにはHTTP/2を強制するためのドロップダウンがあります)。応答が400 Bad chunkのようなHTTP/1.1エラーである場合、エッジが下流のHTTP/1パーサー用にトラフィックを変換した証拠があります。


攻撃ワークフロー(H2.TEの例)

http
:method: POST
:path: /login
:scheme: https
:authority: example.com
content-length: 13      # ignored by the edge
transfer-encoding: chunked

5;ext=1\r\nHELLO\r\n
0\r\n\r\nGET /admin HTTP/1.1\r\nHost: internal\r\nX: X
  1. フロントエンドは正確に13バイト(HELLO\r\n0\r\n\r\nGE)を読み取り、リクエストが終了したと考え、その分をオリジンに転送します。
  2. バックエンドはTEヘッダーを信頼し、2番目0\r\n\r\nを見るまで読み続け、攻撃者の2番目のリクエストのプレフィックス(GET /admin …)を消費します。
  3. 残り(GET /admin …)は被害者の後ろにキューイングされた新しいリクエストとして扱われます。

密輸されたリクエストを次のように置き換えます:

  • POST /api/logout セッション固定を強制するため
  • GET /users/1234 被害者特有のリソースを盗むため

h2cスムグリング(クリアテキストアップグレード)

2023年の研究では、フロントエンドがクリアテキストHTTP/2をサポートするバックエンドにHTTP/1.1 Upgrade: h2cヘッダーを渡すと、攻撃者がのHTTP/2フレームをHTTP/1.1のみを検証したエッジを通してトンネルできることが示されました。これにより、ヘッダーの正規化、WAFルール、さらにはTLS終端を回避します。

主な要件:

  • エッジは両方Connection: UpgradeUpgrade: h2cを変更せずに転送します。
  • オリジンはHTTP/2に増分し、リクエストキューイングを可能にする接続再利用のセマンティクスを保持します。

緩和策は簡単です – WebSocketを除いて、エッジでUpgradeヘッダーを削除またはハードコーディングします。


注目すべき実世界のCVE(2022-2025)

  • CVE-2023-25690 – Apache HTTP Serverのmod_proxyリライトルールは、リクエスト分割とスムグリングのために連鎖させることができました。(2.4.56で修正)
  • CVE-2023-25950 – HAProxy 2.7/2.6は、HTXパーサーがパイプライン化されたリクエストを誤って処理した場合にリクエスト/レスポンスのスムグリングが発生しました。
  • CVE-2022-41721 – GoのMaxBytesHandlerは、残りのボディバイトをHTTP/2フレームとして解析し、クロスプロトコルスムグリングを可能にしました。

ツール

  • Burp Request Smuggler – v1.26以降、H2.TE/H2.CLおよび隠れたALPNサポートを自動的にテストします。拡張オプションで「HTTP/2プロービング」を有効にします。
  • h2cSmuggler – Bishop Foxによるクリアテキストアップグレード攻撃を自動化するPython PoC:
bash
python3 h2csmuggler.py -u https://target -x 'GET /admin HTTP/1.1\r\nHost: target\r\n\r\n'
  • curl/hyper – 手動ペイロードの作成:curl --http2-prior-knowledge -X POST --data-binary @payload.raw https://target

防御策

  1. エンドツーエンドHTTP/2 – ダウングレード翻訳を完全に排除します。
  2. 長さの真実の単一ソース – ダウングレード時には、常に有効なContent-Lengthを生成し、ユーザー提供のContent-Length/Transfer-Encodingヘッダーを削除**します。
  3. ルート前の正規化 – ルーティング/リライトロジックの前にヘッダーのサニタイズを適用します。
  4. 接続の隔離 – ユーザー間でバックエンドTCP接続を再利用しないでください。「1接続あたり1リクエスト」はキューに基づく攻撃を無効にします。
  5. WebSocketでない限りUpgradeを削除 – h2cトンネリングを防ぎます。

参考文献

tip

AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE) Azureハッキングを学び、実践する:HackTricks Training Azure Red Team Expert (AzRTE)

HackTricksをサポートする