Web缓存投毒
在本节中,我们将讨论什么是Web缓存投毒,以及哪些行为可能导致Web缓存投毒漏洞。我们还将介绍一些利用这些漏洞的方法,并建议你如何降低暴露在它们面前的风险。
什么是Web缓存投毒?
Web缓存投毒是一种高级技术,攻击者利用Web服务器和缓存的行为,使得其他用户接收到有害的HTTP响应。
从根本上说,Web缓存投毒包括两个阶段。首先,攻击者必须想办法从后端服务器中获得一个不经意间包含某种危险payload的响应。一旦成功,他们需要确保他们的响应被缓存,并随后提供给预期的受害者。
一个被投毒的Web缓存可能成为分发许多不同攻击的破坏性手段,利用诸如XSS、JavaScript注入、打开重定向等漏洞。
Labs
如果你已经熟悉Web缓存投毒背后的基本概念,只想在一些现实的、故意易受攻击的目标上练习利用它们,你可以从下面的链接访问本主题的所有实验。
Web缓存投毒研究
这项技术最早是由我们2018年的研究论文《实用Web缓存投毒》普及的,并在2020年进一步发展为第二篇研究论文《Web缓存纠缠:投毒新途径》。如果你对我们是如何在野外发现和利用这些漏洞的详细描述感兴趣,完整的论文可在我们的研究页面上找到。
Research
Web缓存的工作原理
要了解Web缓存投毒漏洞是如何产生的,首先必须要对Web缓存的工作原理有一个基本的了解。
如果一个服务器必须为每个HTTP请求单独发送一个新的响应,那么这可能会使服务器超载,从而导致延迟问题和糟糕的用户体验,尤其是在高峰时期。缓存主要是为了减少这些问题。
缓存位于服务器和用户之间,它保存(缓存)对特定请求的响应,通常有固定的时间。如果另一个用户发送了一个相同的请求,缓存就会直接向用户提供缓存的响应副本,而无需后端进行任何交互。这大大减轻了服务器的负担,降低了它必须处理的重复请求的数量。
缓存键
当缓存接收到一个HTTP请求时,首先需要确定是否有一个可以直接提供给用户的缓存响应,或者是否需要将请求转发给后端服务器处理。缓存通过比较预定义的请求组件子集(统称为“缓存键”)来识别等效的请求。通常这包括请求行和Host
标头。不包含在缓存键中的请求组件被认为是“unkeyed”[1]的。
如果传入请求的缓存键与之前请求的键相匹配,那么缓存会认为它们是等效的。因此,它将提供一个为原始请求生成的缓存响应的副本。这适用于所有具有匹配缓存键的后续请求,直到缓存响应过期。
最重要的是,请求的其他组件完全被缓存完全忽略了。稍后我们将更详细地探讨这种行为的影响。
Web缓存投毒攻击的影响是什么?
Web缓存投毒的影响主要取决于两个关键因素:
攻击者到底可以成功地缓存什么
由于被投毒的缓存更像是一种分发手段,而不是一个独立的攻击,Web缓存投毒的影响与注入的payload的危害程度密切相关。与大多数类型的攻击一样,Web缓存投毒也可以与其他攻击结合使用,进一步提高潜在影响。
受影响页面的流量
只有在缓存被投毒时,访问受影响页面的用户才会收到投毒的响应。因此,影响范围可能从不存在到巨大,取决于该页面是否受欢迎。例如,如果攻击者在一个主站的主页上投毒一个缓存响应,那么攻击可能会影响到成千上万的用户,而无需攻击者进一步互动。
请注意,缓存条目的持续时间并不一定会影响Web缓存投毒的影响。攻击通常可以通过脚本的方式,使其无限期地重新毒害缓存。
构造一个Web缓存投毒攻击
通常来说,构造一个基本的Web缓存投毒攻击包括以下步骤:
识别和评估未键控的输入
从后端服务器获取一个有害响应
获取缓存的响应
识别和评估未键控的输入
任何Web缓存投毒攻击都依赖于对未键控输入(如HTTP标头)的操作。Web缓存在决定是否将缓存响应提供给用户时会忽略未键控的输入。这种行为意味着你可以使用它们来注入payload,并引发一个“被毒害”的响应,如果被缓存,它将被提供给所有请求有匹配缓存键的用户。因此,构建Web缓存投毒攻击的第一步是确定服务器所支持的未键控输入。
你可以通过向请求中添加随机输入并观察它们是否对响应产生影响来手动识别未键控的输入。这可能很明显,比如在响应中直接反映出输入,或者触发一个完全不同的响应。然而,有时候效果更微妙,需要做一些侦查工作才能弄清楚。可以使用像Burp Comparer这样的工具来比较有无注入输入的响应,但这仍然涉及大量的手动操作。
Param Miner
幸运的是,可以通过从BApp store为Burp添加Param Miner扩展来自动识别未键控的输入。要使用Param Miner,只需右击要调查的请求,然后单击“Guess headers”。接着,Param Miner在后台运行,发送包含其广泛内置HTTP标头列表的不同输入的请求。
如果某个包含其注入输入的请求对响应产生影响,Param Miner会在Burp中记录此信息,如果你使用的是Burp Suite Professional,则为“Issues”窗格,如果你使用的是Burp Suite Community Edition,则为扩展程序的“Output”选项卡(“Extensions”>“Installed”>“Param Miner”>“Output”)。
例如,在下面的截图中,Param Miner在网站的主页上发现了一个未键控的X-Forwarded-Host
标头:
从后端服务器获取一个有害响应
一旦你识别了一个未键控的输入,下一步就是评估网站如何处理它。了解这一点对于成功引发有害响应至关重要。如果一个输入在没有正确过滤的情况下就反映在服务器的响应中,或者用于动态生成其他数据,那么这就是Web缓存投毒的一个潜在切入点。
获取缓存的响应
操作输入以引发有害的响应是成功的一半,但除非你能使响应被缓存,否则不会有太大成效,有时这可能很棘手。
响应是否被缓存可能取决于各种因素,如文件扩展名、内容类型、路由、状态码和响应标头。你可能需要花一些时间在不同页面上尝试请求并研究缓存的行为。一旦弄清楚如何获取包含恶意输入的缓存响应,你就可以将漏洞传递给潜在的受害者。
利用Web缓存投毒漏洞
这个基本过程可以用来发现和利用各种不同类型的Web缓存投毒漏洞。
在某些情况下,Web缓存投毒漏洞是由于缓存设计的普遍缺陷而产生的。而其他时候,特定网站如何实现缓存可能会引入意想不到的特性,这些特性可以被利用。
在接下来的章节中,我们将概述这两种情况的一些最常见示例。我们还提供了许多交互式实验,以便你可以亲眼目睹这些漏洞并练习利用它们。
阅读更多
如何防止Web缓存投毒漏洞
防止Web缓存投毒的确切方法是完全禁用缓存。尽管对许多网站来说,这可能不是一个现实的选择,但在其他情况下,这可能是可行的。例如,如果你使用缓存仅仅是因为在采用CDN时默认启用了它,那么你可能需要评估默认缓存选项是否确实符合你的需求。
即使你确实需要使用缓存,将其限制为纯静态响应也是有效的,只要你对“静态”的分类保持足够的警惕。例如,确保攻击者不能欺骗后端服务器检索其恶意版本的静态资源,而不是真正的资源。
这也涉及到Web安全更广泛的问题。现在大多数网站在开发过程和日常操作中都采用了各种第三方技术。无论你的内部安全状况有多强大,一旦将第三方技术纳入你的环境,你就依赖于其开发者也和你一样具有安全意识。基于你的安全取决于你最薄弱的点的原则,确保在整合任何第三方技术之前,充分了解其安全影响是至关重要的。
具体到Web缓存投毒,这不仅意味着要决定是否默认启用缓存,还包括查看你的CDN支持哪些标头等。上面讨论的几个Web缓存投毒漏洞之所以被暴露,是因为攻击者能够操纵一系列不太为人知的请求标头,而这其中许多标头对网站的功能来说是完全没有必要的。再次强调,你可能在不知情的情况下将自己暴露于这类攻击中,仅仅是因为你实施了某种默认支持这些未键控输入的技术。如果某个标头对网站的运行并无必要,则应将其禁用。
在实施缓存时,你还应采取以下预防措施:
如果你考虑将某些内容从缓存键中排除以提高性能,请重写请求。
不要接受fat
GET
请求[2]。请注意,某些第三方技术可能默认允许此类请求。即使客户端漏洞看似无法利用,也要修补。由于缓存行为的不可预测特性,这些漏洞可能实际上是可以利用的。迟早有人找到一个漏洞,无论是基于缓存的还是其他类型的,这个漏洞就有可能被利用。
译者注:
[1] unkeyed:不属于缓存键的输入被称为未键控的输入。
[2] Fat GET请求表示非标准的带有body的GET请求。
Last updated