hacktricks/src/pentesting-web/http-request-smuggling/request-smuggling-in-http-2-downgrades.md

101 lines
5.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# HTTP/2降级中的请求走私
{{#include ../../banners/hacktricks-training.md}}
HTTP/2通常被认为对经典请求走私免疫因为每个DATA帧的长度是明确的。**这种保护在前端代理将请求“降级”到HTTP/1.x并转发到后端时消失**。当两个不同的解析器HTTP/2前端和HTTP/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时攻击者可以迫使它们不一致。
---
## 两种主要原始类
| 变体 | 前端长度 | 后端长度 | 典型有效负载 |
|---------|-----------------|-----------------|-----------------|
| **H2.TE** | HTTP/2帧 | `Transfer-Encoding: chunked` | 嵌入一个额外的分块消息主体,其最终的`0\r\n\r\n`*未*发送,因此后端等待攻击者提供的“下一个”请求。 |
| **H2.CL** | HTTP/2帧 | `Content-Length` | 发送一个*较小*的CL而不是实际主体因此后端读取超出边界的下一个请求。 |
> 这些在精神上与经典的TE.CL / CL.TE相同只是用HTTP/2替换了其中一个解析器。
---
## 识别降级链
1. 在TLS握手中使用**ALPN**`openssl s_client -alpn h2 -connect host:443`)或**curl**
```bash
curl -v --http2 https://target
```
如果出现`* Using HTTP2`则边缘支持H2。
2. 通过HTTP/2发送故意格式错误的CL/TE请求Burp Repeater现在有一个下拉菜单可以强制使用HTTP/2。如果响应是HTTP/1.1错误,例如`400 Bad chunk`则证明边缘将流量转换为下游的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 头,继续读取直到看到 *第二个* `0\r\n\r\n`,从而消耗了攻击者第二个请求的前缀(`GET /admin …`)。
3. 剩余部分(`GET /admin …`)被视为排队在受害者后面的 *新* 请求。
用以下内容替换走私请求:
* `POST /api/logout` 以强制会话固定
* `GET /users/1234` 以窃取特定于受害者的资源
---
## h2c 走私(明文升级)
2023 年的一项研究表明,如果前端将 HTTP/1.1 的 `Upgrade: h2c` 头传递给支持明文 HTTP/2 的后端,攻击者可以通过仅验证 HTTP/1.1 的边缘隧道 *原始* HTTP/2 帧。这绕过了头部规范化、WAF 规则甚至 TLS 终止。
关键要求:
* 边缘不变地转发 **两个** `Connection: Upgrade``Upgrade: h2c`
* 源升级到 HTTP/2并保持允许请求排队的连接重用语义。
缓解措施很简单——在边缘剥离或硬编码 `Upgrade`WebSockets 除外。
---
## notable real-world CVEs (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 连接;“每个连接一个请求”可以抵御基于队列的攻击。
5. **剥离 `Upgrade` 除非是 WebSocket** 防止 h2c 隧道。
---
## 参考文献
* PortSwigger Research “HTTP/2: The Sequel is Always Worse” <https://portswigger.net/research/http2>
* Bishop Fox “h2c Smuggling: request smuggling via HTTP/2 clear-text” <https://bishopfox.com/blog/h2c-smuggling-request>
{{#include ../../banners/hacktricks-training.md}}