什么是请求走私
HTTP 请求走私是一种干扰网站处理从一个或多个用户接收的 HTTP 请求序列的方式的技术。请求走私漏洞本质上通常很严重,它允许攻击者绕过安全控制,获得对敏感数据的未经授权的访问,并直接危害其他应用程序用户。
请求走私主要与 HTTP/1 请求相关。但是,支持 HTTP/2 的网站可能容易受到攻击,具体取决于其后端架构。
HTTP请求走私攻击会发生什么
当今的 Web 应用程序经常在用户和最终应用程序逻辑之间使用 HTTP 服务器链。用户将请求发送到前端服务器(有时称为负载均衡器或反向代理),然后该服务器将请求转发到一台或多台后端服务器。这种类型的架构在现代基于云的应用程序中越来越常见,并且在某些情况下是不可避免的。
当前端服务器将 HTTP 请求转发到后端服务器时,它通常会通过同一后端网络连接发送多个请求,因为这样的效率和性能要高得多。协议非常简单; HTTP 请求被一个接一个地发送,接收服务器必须确定一个请求在哪里结束以及下一个请求从哪里开始
在这种情况下,前端和后端系统就请求之间的边界达成一致至关重要。否则,攻击者可能能够发送不明确的请求,前端和后端系统会以不同的方式解释该请求:
在这里,攻击者导致其前端请求的一部分被后端服务器解释为下一个请求的开始。它有效地添加到下一个请求之前,因此可能会干扰应用程序处理该请求的方式。这是请求走私攻击,可能会造成灾难性的后果。
如何造成HTTP请求走私漏洞
大多数 HTTP 请求走私漏洞的出现是因为 HTTP/1 规范提供了两种不同的方式来指定请求的结束位置:
Content-Length
头Transfer-Encoding
头
Content-Length
头很简单:它指定消息正文的长度,类似于下述的http请求报文,其中Content-Length
则为q=smuggling
的长度
POST /search HTTP/1.1
Host: normal-website.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 11
q=smuggling
Transfer-Encoding
头可用于指定消息正文使用分块编码。这意味着消息正文包含一个或多个数据块。
每个块由块大小(以十六进制表示)组成,后跟换行符,然后是块内容。消息以大小为零的块终止。例如下述http请求报文,指定请求体使用了分块编码的方式,第一个字母b
表示11的十六进制数,后接换行符之后为消息内容q=smuggling
,该内容长度为11,后接换行符后通过0表明结束块:
POST /search HTTP/1.1
Host: normal-website.com
Content-Type: application/x-www-form-urlencoded
Transfer-Encoding: chunked
b
q=smuggling
0
由于HTTP/1规范提供了两种不同的方法来指定HTTP消息的长度,因此单个消息有可能同时使用这两种方法,从而导致它们相互冲突。该规范试图通过规定如果Content-Length
和Transfer-Encoding
标头都存在,则应忽略Content-Length
标头来防止此问题。当只有一台服务器在运行时,这可能足以避免歧义,但当两个或多个服务器链接在一起时,就无法避免歧义了。在这种情况下,出现问题的原因有两个:
某些服务器不支持请求中的
Transfer-Encoding
标头如果标头以某种方式混淆,某些支持
Transfer-Encoding
标头的服务器可能会被诱导不处理它。
如果前端和后端服务器对于(可能是混淆的)Transfer-Encoding
标头的行为不同,那么它们可能对连续请求之间的边界存在分歧,从而导致请求走私漏洞。
如何进行HTTP请求走私攻击
经典的请求走私攻击涉及将Content-Length
标头和Transfer-Encoding
标头放入单个 HTTP/1 请求中并对其进行操作,以便前端和后端服务器以不同的方式处理请求。完成此操作的确切方式取决于两个服务器的行为:
CL.TE
:前端服务器使用Content-Length
标头,后端服务器使用Transfer-Encoding
标头TE.CL
:前端服务器使用Transfer-Encoding
标头,后端服务器使用Content-Length
标头TE.TE
:前端和后端服务器都支持Transfer-Encoding
标头,但可以通过某种方式混淆标头来诱导其中一台服务器不处理它
这些技术只能使用 HTTP/1 请求来实现。浏览器和其他客户端(包括 Burp)默认使用 HTTP/2 与在 TLS 握手期间明确通告支持的服务器进行通信。 因此,在测试支持 HTTP/2 的站点时,需要在 Burp Repeater 中手动切换协议。您可以从检查器面板的请求属性部分执行此操作。
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
标头并确定请求正文长度为 13 个字节(其中\r\n
代表两个字节)
直到SMUGGLED
末尾。该请求被转发到后端服务器。 后端服务器处理Transfer-Encoding
标头,因此将消息正文视为使用分块编码。它处理第一个块,该块被声明为零长度,因此被视为终止请求。以下字节SMUGGLED
未处理,后端服务器会将这些字节视为序列中下一个请求的开始。
类似的,若SMUGGLED中的内容为一个新的http请求,将会造成发送一个请求,在后端服务器解析两个请求的情况
CL.TE靶场
靶场地址:https://portswigger.net/web-security/request-smuggling/lab-basic-cl-te
由靶场描述可知,前端服务器不支持chunked encoding
,解决这个靶场的目标是通过GPOST
方法请求后端服务器,其中前端服务器不支持除了GET / POST
的请求方式
发送以下特制的http请求包:
POST / HTTP/1.1
Host: 0aef007b048d628b80de1cfb002e00d7.web-security-academy.net
Content-Type: application/x-www-form-urlencoded
Content-Length: 6
Transfer-Encoding: chunked
0
G