点击蓝字
关注我们
始于理论,源于实践,终于实战
老付话安全,每天一点点
激情永无限,进步看得见
严正声明
本号所写文章方法和工具只用于学习和交流,严禁使用文章所述内容中的方法未经许可的情况下对生产系统进行方法验证实施,发生一切问题由相关个人承担法律责任,其与本号无关。
特此声明!!!
什么是 HTTP 请求走私
HTTP请求走私允许攻击者在HTTP请求中插入恶意数据,从而干扰服务器对请求的处理。通常是通过操纵HTTP请求头中的Content-Length或Transfer-Encoding字段来实现的。前端服务器会使用Content-Length字段来确定请求的结束位置,而后端服务器会使用Transfer-Encoding字段来处理请求,或者前端服务器会使用Transfer-Encoding字段来处理请求,而后端服务器会使用Content-Length字段来确定请求的结束位置。亦或者在HTTP请求头中指定了两个Transfer-Encoding字段,通过以某种方式混淆 Headers 来诱导服务器不处理它;这都可能导致前端和后端服务器对请求的理解不一致。
用户将请求发送到应用服务器前会经过很多前端服务器(反向代理服务器、负载平衡器等),当前端服务器将 HTTP 请求转发到后端服务器时,它通常会通过同一后端网络发送多个请求,因为这样效率和性能都要高得多。协议非常简单,HTTP 请求一个接一个地发送,并且 接收服务器必须确定一个请求的结束位置和下一个请求的开始位置。前端和后端系统必须就请求之间的边界达成一致,否则,将 攻击者可能能够发送一个不明确的请求,该请求被前端和后端系统以不同的方式解释,如果后端服务器将其前端请求的一部分解释为下一个请求的开始,可能会干扰应用程序处理该请求的方式。这就是一个请求走私攻击。
大多数 HTTP 请求走私漏洞的出现是因为 HTTP/1 规范提供了两种不同的方法来指定请求的结束位置:Content-Length 标头和 Transfer-Encoding 标头。Content-Length 标头非常简单:它指定消息正文的长度(以字节为单位)。如:
POST /search HTTP/1.1
Host: example.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 11
q=smuggling
Transfer-Encoding 标头可用于指定消息正文使用分块编码。这 表示消息正文包含一个或多个数据块。每个块都包含以字节为单位的块大小(以 hexadecimal),后跟换行符,后跟块内容。消息以大小为 0 的块终止。例如:
POST /search HTTP/1.1
Host: example.com
Content-Type: application/x-www-form-urlencoded
Transfer-Encoding: chunked
b
q=smuggling
0
Content-Length 标头和 Transfer-Encoding 标头可能会同时出现在一个HTTP消息中,这可能会导致它们相互冲突。例如,如果一个消息同时指定了Content-Length和Transfer-Encoding头字段,那么接收方应该如何确定消息正文的长度呢?是根据Content-Length头字段的值,还是根据Transfer-Encoding头字段的值?
为了避免这种情况的发生,HTTP/1规范规定,如果Content-Length和Transfer-Encoding头字段都存在,则应忽略Content-Length头字段。这意味着,如果一个消息同时指定了Content-Length和Transfer-Encoding头字段,那么接收方应该根据Transfer-Encoding头字段的值来确定消息正文的长度。
然而,这个规定可能并不总是足够。在某些情况下,例如当两个或多个服务器链接在一起时,可能会出现两个服务器都尝试使用不同的方法来确定消息正文的长度的情况。这可能会导致消息正文的长度被错误地解释,从而导致数据损坏或安全漏洞。
如何进行 HTTP 请求走私攻击
CL-TE 漏洞攻击
注:CL-TE (Content-Length 标头和 Transfer-Encoding 标头的缩写)
当前端服务器使用 Content-Length 标头,后端服务器使用 Transfer-Encoding 标头。我们可以执行一个简单的 HTTP 请求走私攻击,如:
POST / HTTP/1.1
Host: example.com
Content-Length: 13
Transfer-Encoding: chunked
0
SMUGGLED
前端服务器处理 Content-Length 标头,并确定请求正文的长度为 13 字节,直到 SMUGGLED 的末尾。此请求将转发到后端服务器。后端服务器处理 Transfer-Encoding 标头,因此将消息正文视为使用分块编码。它处理第一个块,该块被声明为零长度,因此被视为终止请求(根据HTTP/1规范,当服务器接收到一个空块时,它应该认为这是消息正文的结束,因此它会停止处理当前请求。)。以下字节 SMUGGLED 未被处理,后端服务器会将这些字节视为序列中下一个请求的开始(由于后端服务器只处理Transfer-Encoding标头,而忽略了Content-Length标头,所以它会将接下来的字节视为下一个请求的开始。)。
TE.CL 漏洞攻击
当前端服务器使用 Transfer-Encoding 标头,后端服务器使用 Content-Length 标头。我们可以执行一个简单的 HTTP 请求走私攻击,如:
POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 3
Transfer-Encoding: chunked
8
SMUGGLED
0
前端服务器处理 Transfer-Encoding 标头,因此将消息正文视为使用分块编码。它处理第一个块,该块的长度为 8 字节,直到 SMUGGLED 后面的行的开头。它处理第二个块,该块被声明为零长度,因此被视为终止 请求。此请求将转发到后端服务器。后端服务器处理 Content-Length 标头,并确定请求正文的长度为 3 字节,直到 8 后面的行的开头|(因为8后面存在rn,即8rn三个字节)。以下字节(以 SMUGGLED 开头)未被处理,后端服务器会将这些字节视为下一个字节的开头 请求。
注:Transfer-Encoding: chunked分块编码,报文中的实体需要改为用一系列分块来传输。每个分块包含十六进制的长度值和数据,长度值独占一行,长度不包括它结尾的 CRLF(rn),也不包括分块数据结尾的 CRLF。
最后一个分块长度值必须为 0,对应的分块数据没有内容,表示实体结束。例如:
POST / HTTP/1.1
Host: example.com
Content-Type: text/plain
Transfer-Encoding: chunked
25rn
This is the data in the first chunkrn
1Crn
andthis is the second onern
3rn
conrn
8rn
sequencern
0rn
rn
Content-Encoding 和 Transfer-Encoding 二者经常会结合来用,其实就是针对 Transfer-Encoding 的分块再进行 Content-Encoding压缩。
混淆 TE 标头
前端和后端服务器都支持 Transfer-Encoding 标头,但其中一个服务器可以通过以某种方式混淆 Headers 来诱导不处理它。混淆 Transfer-Encoding 标头的方法有很多,如下:
Transfer-Encoding: xchunked #无效的格式
Transfer-Encoding : chunked #有效的格式,尽管在Transfer-Encoding和:之间有一个额外的空格。
Transfer-Encoding: chunked
Transfer-Encoding: x #多个Transfer-Encoding标头,服务器可能会拒绝请求或响应
Transfer-Encoding:[tab]chunked #有效的格式,尽管在Transfer-Encoding和:之间有一个制表符(tab)。
[space]Transfer-Encoding: chunked #有效的格式,尽管在行首有一个空格。
X: X[n]Transfer-Encoding: chunked #无效的格式,因为X: X不是标准的HTTP标头,且在多行标头中,每行应该只有一个标头。
Transfer-Encoding
: chunked #有效的格式,尽管在Transfer-Encoding和:之间换行。
END
老付
欢迎扫码
关注我们
网络安全
原文始发于微信公众号(老付话安全):详解HTTP 请求走私原理
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论