我将在本文介绍如何将受害者的 Web 浏览器变成一个异步的传播平台,通过暴露一个独立的服务器网站和内部网络来转移请求走私的边界。你将学习如何将跨域请求与服务器漏洞相结合,以攻击浏览器连接池、安装后门,并释放异步攻击。使用这些技术,我将攻击包括 Apache、Akamai、Varnish、Amazon 和多个 Web VPN 在内的目标。
接下来我将分享一种结合浏览器特点和自定义开源工具的方法。除此之外,我还将介绍一种黑盒分析策略,该策略解决了长期存在的异步障碍,并揭示了一种极其有效的新颖异步触发器。由此产生的后果将包括客户端、服务器端甚至 MITM 攻击。最后,我将介绍修改 HTTPS 以在 Apache 上触发 MITM 驱动的异步。
本文使用的术语“浏览器驱动的异步攻击”表示可以通过 Web 浏览器触发的所有异步攻击。这包括所有客户端异步攻击,以及一些服务器端攻击。
本文的示例都是取材于真实网站。本文中引用的所有漏洞均已报告给相关供应商,并已修补,除非另有说明。
如果你没有尝试请求走私攻击,很容易忘记 HTTP 连接重用并将 HTTP 请求视为独立对象。毕竟,HTTP 应该是无状态的。然而,下面的层(通常是 TLS)只是一个字节流,很容易找到实现不佳的 HTTP 服务器,假设通过单个连接发送的多个请求必须共享某些属性。
在野外看到的主要漏洞是服务器假设通过给定 TLS 连接发送的每个 HTTP/1.1 请求都必须具有相同的预期目标和 HTTP Host 标头。由于网络浏览器符合这个假设,所以在有人使用 Burp Suite 之前一切都会正常工作。
我发现了两个不同的场景,这个漏洞均造成了很大的安全后果。
反向代理通常使用 Host 标头来识别将每个请求路由到哪个后端服务器,并有一个允许人们访问的主机白名单:
但是,我发现一些代理只对通过给定连接发送的第一个请求应用此白名单。这意味着攻击者可以通过向允许的目的地发出一个请求来访问内部网站,然后通过相同的连接向内部网站发出一个请求:
幸运的是,这种漏洞非常罕见。
第一个请求路由是一个密切相关的漏洞,发生在前端使用第一个请求的 Host 标头来决定将请求路由到哪个后端,然后将来自同一客户端连接的所有后续请求路由到同一后端连接。
这本身不是一个漏洞,但它使攻击者能够使用任意 Host 标头攻击任何后端,因此它可以与 Host 标头攻击链接在一起,例如密码重置攻击、Web 缓存攻击以及获得对其他虚拟主机的访问权限。
在此示例中,我们希望使用“psres.net”的攻击主机标头攻击 example.com 的后端,以进行密码重置攻击,但前端不会路由我们的请求:
然而,通过对目标网站的有效请求开始我们的请求序列,我们可以成功到达后端:
希望能给受害者发一封带有钓鱼链接的邮件:
你可以使用 HTTP Request 走私中的“连接状态探测”选项扫描这两个漏洞。
大多数 HTTP 请求走私攻击可以描述如下:
发送一个长度不明确的 HTTP 请求,使前端服务器与后端对消息的结束位置产生分歧,从而将恶意前缀应用于下一个请求。此分歧通常是通过混淆的传输编码标头来实现的。
该漏洞是由以下HTTP/2请求触发的,该请求没有使用任何混淆或违反任何RFC。甚至对于长度没有任何歧义,因为 HTTP/2 在帧层中有一个内置的长度字段:
此请求触发了来自运行 AWS Application Load Balancer (ALB) 作为其前端的各种网站的非常可疑的间歇性 400 漏洞请求响应。调查显示,ALB在将请求降级为HTTP/1.1转发到后端时,添加了一个“Transfer-Encoding: chunked”标头,而没有对消息正文进行任何更改:
我只需要提供一个有效的被chunk对象:
这是一个发现漏洞的完美示例,它让你回溯实际发生的情况和原因。这个请求只有一个不寻常的地方,它没有 Content-Length (CL) 标头。由于前面提到的内置长度字段,在 HTTP/2 中省略 CL 是明确可接受的。然而,浏览器总是发送一个 CL,所以服务器显然不会期望没有CL的请求。
有了这两个经验教训,我决定解决我去年在HTTP/2 研究中强调的一个未解决的问题,连接锁定 HTTP/1.1 请求走私漏洞的通用检测。连接锁定是指前端为与客户端建立的每个连接创建一个到后端的新连接的常见行为。这使得直接的跨用户攻击几乎不可能,但仍然留下了其他攻击途径。
要识别此漏洞,你需要通过单个连接发送“攻击者”和“受害者”请求,但这会产生大量误报,因为服务器行为无法与称为HTTP管道的常见无害特性区别开来。例如,给定以下 CL.TE 攻击的请求/响应序列,你无法判断目标是否易受攻击:
HTTP 管道在 Burp Repeater 中也可见,它通常被误认为是真正的请求走私:
你可以通过将 requestsPerConnection 设置从 1 增加到自己在 Turbo Intruder 中的测试,这只是要做好误报的准备。
我浪费了很多时间试图调整请求来解决这个问题。但事实证明,上面的响应不能证明存在漏洞,并且解决方案立刻就出现了:
从上面的响应序列可以看出,由于随后的 404 响应,后端正在使用传输编码标头解析请求。但是,你无法判断前端是否使用请求的 Content-Length ,并因此易受攻击,或者是否安全地将其视为许多chunk,并假设橙色数据已通过管道传输。
要排除管道的可能性并证明目标确实易受攻击,你只需在使用 0\r\n\r\n 完成chunk处理请求后暂停并尝试提前读取。如果服务器在你的读取尝试期间做出响应,则表明前端认为该消息还是完整的,因此必须将其安全地分割成很多小块:
如果你的读取尝试被暂停,这表明前端正在等待消息完成,因此必须使用 Content-Length,从而使其易受攻击:
这种技术也可以很容易地适应 TE.CL 漏洞。将其集成到 HTTP Request 走私中很快发现了一个在Barracuda WAF 后面运行 IIS 的网站,该网站容易受到传输编码的影响。有趣的是,修复这个漏洞的更新已经出现了,但它是作为一种投机性的修复措施来实现的,所以它没有被标记为安全版本,攻击设备也没有安装它。
虽然原先将另一个网站标记为最初看起来像连接锁定的 TE.CL 漏洞。但是,服务器没有按预期响应我的手动探测和读取。当我尝试简化请求时,我发现传输编码标头实际上被前端和后端完全忽略了。这意味着我可以完全利用它,发起攻击:
前端使用的是 Content-Length,但后端显然完全忽略了它。结果,后端将正文作为第二个请求的方法的开始。忽略CL等同于将其视为值为0,因此这是一个CL.0异步,这是一种已知但较少探索的攻击类。
关于此漏洞的第二个也是更重要的一点是,它是由一个完全有效的、符合规范的 HTTP 请求触发的。这意味着前端防御它的机会为零,甚至可以由浏览器触发。
攻击是可能的,因为后端服务器根本不会接收到 POST 请求。
对 CL.0/H2.0 异步漏洞实施粗略扫描检查后发现,它们影响了包括 amazon.com 在内的众多网站,亚马逊网站忽略了发送到 /b/ 的请求的 CL:
我通过创建一个简单的概念证明 (PoC) 来确认此漏洞,该概念将随机实时用户的完整请求(包括身份验证令牌)存储在我的清单中:
在我向亚马逊报告此事后,我意识到我还是错过了一个危害更大的漏洞。攻击请求非常普通,我可以让任何人的网络浏览器使用 fetch() 发出它。通过在亚马逊上使用 HEAD 技术创建一个 XSS 小工具并在受害者的浏览器中执行 JavaScript,我可以让每个受攻击的受害者自己重新发起攻击,并将其传播给其他人。这样就会产生一个异步攻击,一种自我复制的攻击,利用受害者在没有用户交互的情况下发起的攻击,迅速利用亚马逊上的每个活跃用户。
我不建议在你的工作系统上尝试此操作,但在暂存环境中尝试可能会很有趣。
传统的异步攻击利用的是前端和后端服务器之间的连接,因此在不使用前端/后端架构的网站上是不可能的。从现在开始,我将把它称为服务器端异步。大多数服务器端异步只能由发出格式漏洞的请求的自定义 HTTP 客户端触发,但是,正如我们刚刚在 amazon.com 上看到的,有时可以创建由浏览器驱动的服务器端异步。
浏览器导致异步的能力会引发一类全新的威胁,我将其称为客户端异步 (client-side desync,CSD),其中异步发生在浏览器和前端服务器之间。这使得可以利用独立的服务器网站,这很有价值,因为它们通常在 HTTP 解析方面非常糟糕。
CSD 攻击始于受害者访问的感染网站,然后让他们的浏览器向易受攻击的网站发送两个跨域请求。第一个请求的目的是使浏览器的连接异步,并使第二个请求触发有害响应,通常使攻击者控制受害者的帐户:
在尝试检测和利用客户端异步漏洞时,你可以重用来自服务器端异步攻击的许多概念。主要区别在于,整个漏洞利用序列都发生在受害者的网络浏览器中,这个环境比专用黑客工具更加复杂和不受控制。这带来了一些新的挑战,这给我在研究这项技术时带来了很大的阻碍。为此,我开发了以下方法:
第一步是识别你的 CSD 矢量。这个基本原语是漏洞的核心,也是构建漏洞利用的平台。我们已经在 HTTP Request 走私和Burp Scanner 中实现了对这些的自动检测,但是了解如何手动进行检测仍然很有价值。
CSD 向量是具有两个关键属性的 HTTP 请求。
首先,服务器必须忽略请求的 Content-Length (CL)。这种情况通常会发生,因为请求要么触发了服务器错误,要么服务器根本不期望向所选端点发出POST请求。尝试针对静态文件和服务器级重定向,并通过超长 URL 和 /%2e%2e 等半格式错误触发漏洞。
其次,请求必须在web浏览器的跨域触发。浏览器严重限制了对跨域请求的控制,因此你对标头的控制有限,如果你的请求有正文,则需要使用 HTTP POST 方法。最终,你只控制URL,加上一些零星的结尾,如Referer 标头、正文和 Content-Type 的后半部分:
现在我们已经编写了攻击请求,我们需要检查服务器是否忽略了 CL。作为简单的第一步,使用超长的 CL 发出请求并查看服务器是否仍然回复:
这是有希望的,但不幸的是,一些安全服务器无需等待正文即可响应,因此你会遇到一些误报。其他服务器没有正确处理 CL,而是在响应后立即关闭每个连接,使它们无法被利用。要过滤掉这些,请在同一连接下发送两个请求,并查找第一个请求的正文影响对第二个的响应:
要在 Burp Suite 中对此进行测试,将两个请求放入Repeater中的一个标签组,然后使用单连接发送序列。你还可以在 Turbo Intruder 中通过禁用管道并将 concurrentConnections 和 requestsPerConnection 分别设置为 1 和 100 来实现此目的。
如果可行,请尝试更改正文并确认第二个响应按预期更改。这个简单的步骤旨在确认你对正在发生的事情的心理模型与现实相符。我个人在运行 Citrix Web VPN 的系统上浪费了很多时间,只是意识到它只是为发送到某个端点的每个请求发出两个 HTTP 响应。
最后,重要的是要注意目标网站是否支持 HTTP/2。CSD 攻击通常利用 HTTP/1.1 连接重用,并且 Web 浏览器更喜欢尽可能使用 HTTP/2,因此如果目标网站支持 HTTP/2,你的攻击不太可能起作用。有一个例外;一些转发代理不支持 HTTP/2,因此你可以利用任何使用它们的人。这包括公司代理、某些VPN 甚至一些安全工具。
现在我们已经找到了 CSD 向量,我们需要通过在真实浏览器中复制行为来排除任何潜在的漏洞。我推荐使用 Chrome,因为它拥有创造CSD漏洞的最佳开发工具。
首先,选择一个网站来发起攻击。此网站必须通过 HTTPS 访问,并且位于与目标不同的域中。
接下来,确保你没有配置代理,然后浏览到你的攻击网站。打开开发人员工具并切换到网络选项卡。为了帮助调试以后可能出现的问题,我建议进行以下调整:
选择“保留日志”复选框。
右键点击列标题并启用“连接 ID”列。
切换到开发人员控制台并使用fetch()执行JavaScript来复制攻击序列。如下所示:
我已将获取模式设置为“no-cors”以确保 Chrome 在“网络”选项卡中显示连接 ID。我还设置了凭据:“包含”,因为 Chrome 有两个独立的连接池,一个用于带有 cookie 的请求,一个用于不带 cookie 的请求。你通常会想要利用导航,并且那些使用“with-cookies”池。
执行此操作时,你应该在 Network 选项卡中看到两个具有相同连接 ID 的请求,第二个应该触发 404:
如果这如预期的那样工作,那么恭喜你,你已经发现自己的客户端不同步了!
现在我们已经确认了客户端异步,下一步就是找到一个小工具来利用它。在Network选项卡中意外触发404可能会给一些人留下深刻印象,但它不太可能产生任何用户密码或奖励。
至此,我们已经确定我们可以攻击受害者浏览器的连接池,并对我们选择的 HTTP 请求应用任意前缀。这是一个非常强大的原语,它提供了三种广泛的攻击途径。
一种选择是识别目标网站上允许你存储文本数据的功能,并编写前缀,以便受害者的 cookie、身份验证标头或密码最终存储在你可以检索它们的位置。这种攻击流程的工作原理与服务器端请求走私几乎相同,所以我不会详述。
下一个选项是全新的,由受害者浏览器中的新攻击平台提供。
在正常情况下,很多类型的服务器端攻击只能由直接访问目标网站的攻击者发起,因为它们依赖于浏览器拒绝发送的 HTTP 请求。这几乎包括了所有涉及篡改HTTP报头的攻击——Web 缓存攻击、大多数服务器端请求走私、主机标头攻击、基于用户代理的 SQLi 以及许多其他攻击。
例如,不可能让其他人的浏览器在 User-Agent 标头中使用 log4shell 有效负载发出以下请求:
CSD 漏洞为这些针对网站的攻击打开了大门,这些网站由于位于受信任的内部网或隐藏在基于 IP 的限制之后而受到保护。例如,如果 intranet.example.com 易受 CSD 攻击,你可以使用以下请求达到相同的效果,可以在浏览器中使用 fetch() 触发该请求:
浏览器正在努力缓解对内网网站的攻击,无法想象有多少物联网设备容易受到CSD攻击。
你还可以利用诸如会话 cookie 之类的环境权限,在 CSRF 风格的攻击中攻击身份验证后的攻击面,由于不可伪造的标头(例如 JSON Content-Type),这通常是不可能的。总体而言,CSD 漏洞非常适合与客户端和服务器端漏洞进行链接,并且可以在适当的情况下启用多步pivot。
最后一种选择是使用恶意前缀从服务器引发有害响应,其目标通常是在易受攻击的网站上执行任意 JavaScript,并劫持用户的会话或密码。
我发现成功攻击的最简单途径来自通常用于服务器端异步攻击的两种关键技术:通过Host-header重定向的JavaScript资源攻击,以及使用 HEAD 方法将响应与被感染的 HTML 拼接在一起。这两种技术都需要进行调整,以克服与在受害者浏览器中操作相关的一些新挑战。在下一篇文章中,我将使用一些案例研究来探索这些障碍并展示如何处理它们。
参考及来源:https://portswigger.net/research/browser-powered-desync-attacks