摘要
Web缓存投毒一直是一个难以捉摸的漏洞,是一种“理论上”存在,可吓唬开发人员去乖乖修补,但任何人无法实际利用的问题。
在本文中,我将向您展示,如何通过使用深奥的网络功能将其缓存转换为漏洞并利用传送系统来破坏网站,受众是任何能在请求访问其主页过程中制造错误的人。
我将通过漏洞来说明和开发这种技术。这些漏洞使我能够控制众多流行的网站和框架,从简单的单一请求攻击发展到劫持JavaScript,跨越缓存层,颠覆社交媒体和误导云服务的复杂漏洞利用链。我将讨论防御缓存投毒的问题,并发布推动该研究开源的Burp Suite社区扩展。
核心概念
缓存101
要掌握缓存投毒,我们需要快速了解缓存的基本原理。Web缓存位于用户和应用程序服务器之间,用于保存和提供某些响应的副本。在下图中,我们可以看到三个用户接连获取相同的资源:
缓存旨在通过减少延迟来加速页面加载,还可以减少应用程序服务器上的负载。一些公司使用类似Varnish的软件来托管他们的缓存,而其他公司选择依赖Cloudflare这样的内容交付网络(CDN),将缓存分散在各个地理位置。此外,一些流行的Web应用程序和框架(如Drupal)具有内置缓存功能。
还有其他类型的缓存,例如客户端浏览器缓存和DNS缓存,但它们不是本文的研究重点。
缓存键
缓存的概念可能听起来简洁明了,但它隐藏了一些风险。每当缓存收到对资源的请求时,它需要确定它是否已经保存了这个确切资源的副本,并且可以使用该副本进行回复,或者是否需要将请求转发给应用程序服务器。
确定两个请求是否正在尝试加载相同的资源可能很棘手; 通过请求逐字节匹配的方法是完全无效的,因为HTTP请求充满了无关紧要的数据,例如浏览器发出的请求:
缓存使用缓存键来标识一个资源,缓存键一般由请求中的一部分内容组成。在上面的请求中,缓存键中包含的值用橙色突出显示,这个缓存键是非常常用的。
这意味着缓存认为以下两个请求是等效的,并使用从第一个请求缓存的响应来响应第二个请求:
因此,该页面将错误的语言格式提供给第二位访问者。这暗示了一个问题 ——任何非缓存键内容的差异,都可能被存储并提供给其他用户。理论上,站点可以使用“Vary”响应头来指定请求头中哪些部分应该作为缓存键。在实际中,Vary协议头很少使用,像Cloudflare这样的CDN甚至完全忽略它,人们甚至没有意识到他们的应用程序支持基于任何协议头的输入。
这会导致许多意想不到的破坏,特别是当有人故意开始利用它时,它的危害才会真正开始体现
缓存投毒
Web缓存投毒的目的是发送导致有危害响应的请求,该响应将保存在缓存中并提供给其他用户。
在本文中,我们将使用非缓存键部分的输入(如HTTP请求)来使缓存中毒。当然,这不是缓存投毒的唯一方法 (您也可以使用HTTP响应拆分和请求走私 的方法),但我自认为自己的方法最好。请注意,不要混淆Web缓存投毒与Web 缓存欺骗,它们是不同类型的攻击。
方法
我们将使用以下方法查找缓存投毒漏洞:
第一步:识别非缓存键部分的输入。手动执行此操作非常繁琐,因此我开发了一个名为Param Miner的开源Burp Suite扩展,通过猜测header/cookie的名称来自动执行这些步骤,并观察它们是否对应用程序的响应产生影响。
找到非缓存键部分的输入后,接下来的步骤是评估您可以对它做多少破坏,然后尝试将其存储在缓存中。如果失败,则您需要更好地了解缓存的工作方式,并且在重试之前,搜索可缓存的目标页面。然而页面是否被高速缓存基于多种因素,包括文件扩展名,内容类型,路由,状态代码和响应头。
缓存的响应可能会忽略你的输入,因此如果您尝试手动检测非缓存键部分,则“破坏缓存”是很重要的。如果加载了Param Miner,就可以通过向查询字符串添加值为$ randomplz的参数,确保每个请求都具有唯一的缓存键。
检测实时网站时,因为缓存响应而意外的使其他访问者中毒是一种永久性危害。Param Miner通过向来自Burp的所有出站请求添加“破坏缓存”来缓解这种情况。此缓存共享器具有固定值,因此您可以自己观察缓存行为,而不会影响其他用户。
实例探究
让我们来看看该方法应用于真实网站时会发生什么。像往常一样,我只针对对研究人员具有友好安全策略的网站。这里讨论的所有漏洞都已被报告和修补,但由于“私人”需要,我被迫编写了一些漏洞利用程序。
其中许多案例研究在非缓存键部分的输入中利用了XSS等辅助漏洞,重要的是要记住,如果没有缓存投毒,这些漏洞是无用的,因为没有可靠的方法强制其他用户在跨域请求上发送自定义协议头。它们因此容易被找到。
英文原文:https://portswigger.net/blog/practical-web-cache-poisoning
译者:盈韬
未完,接本日推送第二篇
领取专属 10元无门槛券
私享最新 技术干货