利用TRACE方法简化HTTP异步攻击
你是否曾经发现一个HTTP异步漏洞,但由于复杂的约束条件而看似无法利用?在这篇博客中,我们将探索一种新的利用技术,可以使用TRACE方法完全攻陷一个Web应用程序——这是一种古老的HTTP方法,但其支持范围可能比你想象的要广泛得多。
最近,我在一个漏洞赏金项目中遇到了一个HTTP/2异步漏洞(也称为HTTP请求走私),该漏洞存在HTTP/2头部注入问题。具体来说,我可以在头部值中注入换行符,从而走私传输编码头部,最终在后端分割请求。
确认漏洞并提交给项目后,我收到了以下消息: “感谢您的提交。能够走私请求本身并不是漏洞。您如何利用这个走私请求?”
尽管在2024年说走私请求本身不是漏洞似乎是一个大胆的声明,但我有信心能够制作一个良好的概念验证来展示影响。
但在研究应用程序几个小时后,我开始担心,因为没有端点可以用来创建我的有效载荷。没有其他漏洞可以与请求走私结合利用,也没有反射参数可用于响应走私,更糟糕的是,前端和后端之间的连接似乎是隔离的,因此我无法直接攻击其他用户。我能够使用HEAD走私请求来分割响应队列中的消息,但除此之外,这个主机似乎无法被利用。
TRACE方法
那时我注意到了一些有趣的事情。后端服务器被配置为响应TRACE请求。
对于那些不熟悉此方法的人,HTTP RFC规定: “TRACE方法请求远程、应用级别的请求消息回环。请求的最终接收者应该反射接收到的消息…”
这意味着如果我们发送如下请求:
|
|
我们将获得一个响应,其中包含相同的请求体,并且内容类型为“message/http”:
|
|
尽管你可能认为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异步攻击的服务器的请求:
|
|
第一个响应将照常转发给攻击者。
但是,由于代理从未看到HEAD请求,它将像通常那样解析下一个响应的内容长度,将下一个响应用作主体的一部分。
|
|
使用这种技术,攻击者可以拼接响应,使用头部作为主体,并通过更改有效载荷的内容类型来修改消息的行为,如前面的示例所示。
利用TRACE进行异步攻击
回到HTTP/2异步漏洞,我没有端点在响应的头部或主体中反射有用的内容。但TRACE请求呢?
由于TRACE响应将反射后端接收到的任何头部,我们可以使用它生成恶意脚本并将其放置在HEAD响应的主体中:
|
|
产生以下响应:
|
|
响应将被转发到通过同一连接到达的下一个请求,从而通过恶意JavaScript控制浏览器!
这种技术虽然强大,但需要服务器响应TRACE请求,这在大多数生产环境中似乎不太可能。由于此方法仅应用于调试目的,代理通常使用某些防火墙规则阻止这些请求,返回禁止响应。
但是,由于走私可用于绕过防火墙规则,可以隐藏TRACE消息并将其直接传递到后端。因此,即使该方法被禁止,通过异步进行利用仍然是可能的。
到目前为止,我能够异步连接以在响应中反射任意有效载荷。然而,由于后端连接彼此隔离,恶意响应只会由发出它的用户接收。
即使用户之间不共享连接,也有两种技术可用于利用这种情况:Web缓存投毒和客户端异步。
在这种情况下,客户端异步不可行(需要HTTP/2注入),但应用程序在缓存中存储静态响应,这意味着Web缓存投毒是可能的。
使用响应拼接,可以选择包含内容长度和缓存控制头部的响应,强制响应存储在缓存中。
尽管我能够找到许多潜在的候选端点,但它们都没有值为text/html的内容类型头部。这意味着即使我能够使用这些响应之一存储我的有效载荷,浏览器也不会执行我的恶意JavaScript。
那时,我可以先发送异步攻击,然后通过同一HTTP/2连接请求静态资源如“/payload.css”,并为该端点存储响应。任何请求“/payload.css”的人都会从缓存中接收恶意有效载荷,并且JavaScript将被执行。
尽管这种攻击可能有效,但要影响用户,必须覆盖现有资源的缓存响应,并且根据页面的加载方式和响应的max-age,有效利用受害者浏览器可能相当困难。
从TRACE到响应分割
尽管如此,还有一个更好的选择。当我研究响应走私时,我理论化了一种情况,攻击者可以分割响应以创建将存储在缓存中的任意消息。
要实现这一点,应用程序必须允许某些内容反射包括换行符,以便攻击者可以编写响应头部以及有效载荷:
|
|
这将创建以下响应:
|
|
如前所述,最后一条消息将用于完成HEAD响应,但在这种情况下,只有前78个字节将被拼接。
如果剩余的字节不对应于有效的HTTP消息,代理将转发500错误消息或在转发先前的响应后关闭连接。
但是,在这种情况下,代理能够正确解析剩余的有效载荷作为有效的HTTP响应。因此,消息将被转发为下一个可用请求的响应。
通过这种方式,攻击者能够生成包括头部和主体的任意响应,该响应将存储在后续请求中指定的URL的缓存中。
找到一个允许我们反射主体中发送的任何字节的端点极为罕见,但如果允许TRACE请求,攻击是完全可行的。
请注意,根据配置,TRACE请求不能包含大于0的内容长度头部,因此无法在同一请求中添加JavaScript有效载荷。我们可以使用上述相同技术添加一个额外的响应来生成有效载荷的主体。
像Apache这样的一些服务器,如果存在“TraceEnabled extended”指令,将允许主体,这使得攻击更加简单。
如果不允许主体,可以使用走私的传输编码或额外的响应添加消息长度头部,该响应将附加在TRACE消息的最后一个头部之后:
|
|
这将生成以下响应:
|
|
如果TRACE实现使得无法在响应中附加消息长度头部,也可以创建将存储在缓存中的重定向响应。这可以重定向到存储的有效载荷(使用缓存欺骗/投毒技术),或重定向到攻击者的页面以发起其他攻击,如客户端异步或经典网络钓鱼。
结论
总之,这个案例展示了如何使用像TRACE这样的被遗忘的方法,结合现代技术如HTTP异步和缓存投毒,可能导致Web应用程序中的严重安全问题。尽管TRACE是一种古老的方法,但它对于知道如何创造性使用它的攻击者来说非常有效。
这提醒我们,我们永远不应低估旧技术,因为它们可以以新的方式使用,为网络安全带来重大挑战。