每日一题

2024/4/30

HTTP请求走私

现在网络架构多数采用反代+多台后端服务器的形式实现, 用户将请求发送到反代服务器,然后该服务器将请求转发到一台或多台后端服务器。当前端服务器将 HTTP 请求转发到后端服务器时,它通常会通过同一后端网络连接发送多个请求, HTTP 请求被一个接一个地发送,接收服务器必须确定一个请求在哪里结束以及下一个请求从哪里开始:

那假如我们发送不明确的请求,而前端和后端系统以不同的方式解释该请求,就可能会导致导致其前端请求的一部分被后端服务器解释为下一个请求的开始,也就是我们的请求的一部分被插入到了另一个请求的开头,实现攻击。

那具体什么是不明确的请求呢?是因为在HTTP/1中,提供了两种不同的方式来指定请求的结束位置:Content-Length标头和Transfer-Encoding标头。

Content-Length头很简单:它指定消息正文的长度(以字节为单位)。例如:

POST /search HTTP/1.1 
Host: normal-website.com 
Content-Type: application/x-www-form-urlencoded 
Content-Length: 11 

q=smuggling

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

POST /search HTTP/1.1 
Host: normal-website.com 
Content-Type: application/x-www-form-urlencoded 
Transfer-Encoding: chunked 

b 
q=smuggling 
0

那为什么我们平时很少看到这种格式的请求呢?主要是因为浏览器段很少会用这种分块编码,通常是服务器的响应中看到,而一般来说浏览器为了可读性会将这种分块请求自动转化为正常格式的请求

因为存在两种表示长度的方式,就有可能产生冲突,一旦我们的反代服务器和实际的后端采用的判断长度的方式不一样就有可能产生上述攻击

为了利用这一点,我们可以充分利用HTTP1给我们提供的` Transfer-Encoding` (TE)头和`Content-Lenth`(CC)头。假如反代服务器使用CL判断长度而后端服务器使用TE,或者反代服务器使用TE而后段使用CL,都能造成歧义。或者利用相同的请求头进行一些修改从而造成歧义,使前后端服务器对此解释不同,也能达到攻击的效果。

下面,我们将举例三种方式对应的payload。

1.CL-TE漏洞
这里,前端服务器使用标 Content-Length 头,后端服务器使用 Transfer-Encoding 标头。我们可以执行简单的HTTP 请求走私攻击,如下所示:

POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 13
Transfer-Encoding: chunked

0

SMUGGLED

前端服务器处理 Content-Length header,确定请求体长度为13字节(两个换行符贡献了四个字节),直到 SMUGGLED .该请求被转发到后端服务器。 后端服务器处理 标头,因此将消息正文视为使用分块编码。它处理第一个块,该块被声明为零长度,因此被视为终止请求。以下字节未处理,后端服务器会将这些字节视为序列中下一个请求的开始。

2.TE-CL漏洞
这里,前端服务器使用标 Transfer-Encoding 头,后端服务器使用 Content-Length 标头。我们可以执行简单的 HTTP 请求走私攻击,如下所示:

POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 3
Transfer-Encoding: chunked

8
SMUGGLED
0

前端服务器处理标头,因此将消息正文视为使用分块编码。它处理第一个块,该块的长度为 8 个字节,直到后面的行的开头。它处理第二个块,该块被声明为零长度,因此被视为终止请求。该请求被转发到后端服务器。
后端服务器处理 Content-Length header 并确定请求正文的长度为3 个字节,直到后面的行的开头 8 。以下字节(以开头SMUGGLED )未处理,后端服务器会将这些字节视为序列中下一个请求的开始。

3.TE.TE行为:混淆TE头

由于Content-Length一般不会导致歧义,混淆一般存在于前后端服务器都使用Tranfer-Encoding的情况。这里,前端和后端服务器都支持 Transfer-Encoding 标头,但是可以通过某种方式混淆标头来诱导其中一台服务器不处
理它。
混淆标头的方法可能有无数种 。例如:

Transfer-Encoding: xchunked

Transfer-Encoding : chunked

Transfer-Encoding: chunked
Transfer-Encoding: x

Transfer-Encoding:[tab]chunked

[space]Transfer-Encoding: chunked

X: X[\n]Transfer-Encoding: chunked

Transfer-Encoding
: chunked

这些技术中的每一种都与 HTTP 规范存在微妙的偏差。实现协议规范的现实代码很少能够绝对精确地遵守它,并且不同的实 现通常会容忍与规范的不同变化。要发现 TE.TE 漏洞,需要找到 Transfer-Encoding 标头的某些变体,以便只有前端或后端服务器之一处理它,而另一台服务器忽略它。
根据是否可以诱导前端服务器或后端服务器不处理混淆 Transfer-Encoding 标头,攻击的其余部分将采用与已经描述的 CL.TE 或 TE.CL 漏洞相同的形式。

如何防止HTTP请求走私

省流:换HTTP/2

本文参考了https://portswigger.net/web-security/request-smuggling#top

国赛在即,每日更新一个知识点;)