目录导航
识别和利用 70 多个缓存中毒漏洞

尽管 Web Cache Poisoning 已经存在多年,但技术堆栈中日益复杂的技术不断引入意想不到的行为,这些行为可以被滥用来实现新的缓存中毒攻击。在本文中,我将介绍我用来向各种 Bug Bounty 计划报告 70 多个缓存中毒漏洞的技术。如果您还不熟悉 Web Cache Poisoning 的基础知识,我强烈建议您阅读albinowax 的Practical Web Cache Poisoning。
背景故事
2020 年 12 月 19 日,我发表了一篇关于影响 Varnish 配置的特定边缘情况的简短文章,其中发送大写的主机头可能会污染缓存。不幸的是,由于这需要一个特定的自定义 Varnish 配置,因此扫描它并没有给我带来其他结果。令我惊讶的是,在发表这篇文章后不久,我意识到 Cloudflare 也容易受到相同的大写主机头攻击,但这一次,它不需要自定义配置。这意味着 cloudflare 在将主机标头引入缓存键之前将其小写,但始终按照客户端发送的方式转发。如果 Cloudflare 背后的任何后端在发送大写主机标头时会以不同的响应进行响应,则它将导致缓存中毒。您可以在我的以前的文章,但是 Fastly 和 Cloudflare 现在都修复了该行为。由于这种微妙的不一致影响了一个很好的漏洞赏金目标子集,我决定看看我可以识别和大规模利用的其他常见模式。
Apache Traffic Server 中的 URL 片段处理不正确 ( CVE-2021-27577 )
Apache Traffic Server (ATS) 是 Yahoo 和 Apple 广泛使用的缓存 HTTP 代理。当发送到 ATS 的请求包含 url 片段时,ATS 会转发它而不剥离该片段。根据RFC7230,ATS 转发的请求是无效的,因为 origin-form 应该只由绝对路径和查询组成。

此外,ATS 通过提取主机、路径和查询来生成缓存键,忽略 url 片段。因此,这意味着下面的两个请求将共享相同的缓存键:


ATS 在生成缓存密钥时忽略了 url 片段,但仍然转发它,这为缓存中毒攻击创造了巨大的机会。当 ATS 背后的代理配置为编码#
为 时%23
,攻击者可以在任何缓存键下缓存完全不同的路径。我能够使用这种技术来毒化静态文件,如下所示:

如果后端也正常化/../
,它将允许攻击者将用户重定向到任何路径,从而可以轻松升级 XSS 和 开放重定向。

GitHub CP-DoS
由于缓存中毒漏洞的很大一部分是由未键入的标头引起的,因此我编写了一个工具来蛮力未键入的标头并检测缓存中毒。这使我能够快速扫描大规模的漏洞赏金目标。
由于许多漏洞赏金计划在其范围列表中包含 Github 存储库,因此一些 repo url 进入了我的目标列表。在查看扫描结果时,我注意到当标头content-type
包含无效值时,所有 github 存储库都被标记为易受缓存中毒的影响。

尽管扫描将 Github Repos 标记为易受攻击并且攻击在 Burpsuite 中有效,但我无法在浏览器中进行复制。很快就发现 Github 将 Authentication cookie 包含在缓存键中。虽然不可能毒化经过身份验证的用户的存储库,但可以删除所有访问它们的未经身份验证的用户的存储库,因为他们都共享相同的缓存密钥。这获得了 7500 美元,是我获得最高报酬的缓存中毒报告。
GitLab CP-DoS
GitLab 使用 Google Cloud Platform 和 Fastly 在https://assets.gitlab-static.net/*
. Google Cloud Bucketsx-http-method-override
默认支持使用header,它允许覆盖 HTTP 方法。附加 header x-http-method-override: POST
,将返回一个 405 状态码,默认情况下 Fastly 不会缓存。但是,可以发送标头x-http-method-override: HEAD
并将缓存毒化为返回空响应正文。

此外,该PURGE
方法也被启用,大大降低了攻击的复杂性。这获得了 4,850 美元的顶级赏金。除了 GitLab,我还能够在许多其他赏金目标上使用相同的技术。
X-Forwarded-Scheme – Rack中间件
Ruby on Rails 应用程序通常与 Rack 中间件一起部署。下面的 Rack 代码获取 value 的x-forwarded-scheme
值并将其用作请求的方案。

发送x-forwarded-scheme: http
标头将导致 301 重定向到同一位置。如果响应被 CDN 缓存,它会导致重定向循环,本质上拒绝访问文件。这被利用在大量的赏金目标上,例如:
Hackerone.com 静态文件上的 CP-DoS
由于 Hackerone 的缓存配置设置为仅缓存静态文件,因此缓存中毒攻击仅限于静态文件。

尽管在报告 DoS 漏洞时超出了范围,但仍获得了 2500 美元的赏金。
www.shopify.com 的单一请求 DoS
同样的技术也影响了www.shopify.com
,但是 Shopify 的缓存配置增加了攻击的影响。由于服务器没有配置缓存 HTML 页面,而是默认缓存了 301 个请求,因此只需要一个不定时的请求就触发了 Cache Poisoning DoS。

这最初获得了 1300 美元,但在进一步调查后发现这也会影响其他本地子域和主机,例如apps.shopify.com
. 由于该漏洞影响了许多 Shopify 主机,并且只需要一个请求来毒化缓存,因此悬赏金额增加到 6300 美元。
在 21 个子域上存储 XSS
在测试私人程序时,我注意到在 Hackerone 上发现的相同漏洞影响了他们的所有子域。然而这一次,服务器也信任X-forwarded-host
301 重定向的标头,允许攻击者将 JS 文件重定向到攻击者控制的 Javascript。

由于这可能导致在目标的主网站和超过 21 个其他子域上存储 XSS,因此将其分类为关键并奖励最高 3000 美元的赏金。
Cloudflare 和存储桶
由于 Cloudflare 是使用最广泛的内容交付网络,S3 等存储桶往往落后于 cloudflare。不幸的是,默认情况下,此设置过去容易受到缓存中毒的影响。
直到 2021 年 8 月 3 日,即使没有Cache-control
指令,Cloudflare 也会缓存 403 状态代码。这使得污染托管在 S3 存储桶上并通过 Cloudflare 代理的任何文件成为可能。发送无效的授权标头会导致可缓存的 403 错误。
S3 存储桶:

Azure 存储
Exodus 使用子域downloads.exodus.com
来提供下载服务,例如 Exodus 钱包安装程序。由于文件存储在 Azure 存储 Blob 上,因此可能会导致带有精心设计的授权标头的可缓存 403 错误。Exodus 团队在收到报告几小时后解决了这个问题,并奖励了 2500 美元。

Cloudflare 还更改了它的默认配置,现在不再默认缓存 403 响应。
快速主机头注入
在向同一个漏洞赏金计划报告了多个缓存中毒漏洞后,他们同意将他们的 Varnish 配置文件发送给我,以便我可以更轻松地识别其他不一致之处。浏览文件后,我发现了一个类似于以下的片段:

该片段用于托管地图图像的子域。请求图像看起来像这样:

引入的规则使得当 url 路径与正则表达式匹配时,缓存键将只包含从 url 中提取的坐标,而忽略所有其他 url 组件。因此,上面请求的图像将具有以下缓存键:
/4/151/16
由于该规则仅在路径中包含提取的坐标,这意味着我可以将任何主机标头发送到后端,它仍然会匹配相同的缓存键。不幸的是,这行不通,因为 Fastly 拒绝任何未列入白名单的主机标头。

通过Fastly-host
在请求中附加标头,完全绕过了这种机制。如果fastly-host
标头包含列入白名单的值,则主机标头可以更改为任何内容:

虽然可以为 CP-DoS 使用主机头注入,但我希望得到更多,所以我决定深入挖掘。在查看同一程序上的其他 Fastly 主机时,我发现一个 html 文件redacted-cdn.com
易受 DOM XSS 攻击。由于这是在redacted-cdn.com
origin下,所以xss本身没有影响。
fastly-host
在发现主机头被转发后,我能够通过使用头来升级它,但是快速主机被用于生成缓存密钥。因此,以下请求将匹配缓存键:
https://assets.redacted.com/test.html

由于两台主机都在同一个负载均衡器后面,因此可以缓存托管在redacted-cdn.com
下的文件assets.redacted.com
,这本质上允许我将易受攻击的 html 文件移动到不同的域并在不同的源下实现 xss。
注入键控参数
很多时候,缓存被配置为仅在缓存键中包含特定的 GET 参数。这在托管图像的 CDN 中尤其常见,这些图像使用参数来修改图像大小或格式。
在使用 Fastly 缓存图像测试目标时,我注意到该size
参数包含在缓存键中,但所有其他参数都被忽略了。如果size
添加了两个参数,则两个参数都包含在缓存键中,但后端服务器使用最后一个参数的值。考虑到 Fastly (Varnish),在生成缓存密钥之前不做任何 url 规范化,我能够想出以下 DoS 方法:

URL 编码第二个size
参数导致它被缓存忽略,但被后端使用。将参数值设为 0 将导致可缓存的 400 错误请求。
用户代理规则
由于 FFUF 或 Nuclei 等大量流量工具会生成大量流量,一些开发人员决定阻止与其用户代理匹配的请求。具有讽刺意味的是,这些调整可能会引入不必要的缓存中毒 DoS 机会。

我发现这适用于多个目标,使用来自不同工具或扫描仪的用户代理。
非法headers字段
标头名称格式在RFC7230 中定义如下:

理论上,如果标头名称包含tchar 中列出的字符以外的字符,则应以 400 Bad 请求拒绝它。然而在实践中,服务器并不总是遵守 RFC。利用这种细微差别的最简单方法是针对 Akamai,它不会拒绝无效的标头,但只要缓存控制标头不存在,它就会转发它们并缓存任何 400 错误。

发送包含非法字符的标头\
会导致可缓存的 400 Bad Request 错误。这是整个测试过程中最常见的模式之一。
寻找新的headers
除了请求行的属性可用于毒化缓存的少数新案例外,检测到的大多数缓存毒化漏洞都是由未键入的标头引起的。
由于我想扩展我的标头列表,我使用 Google 的 BigQuery 来查询 HTTP 存档以获取Vary响应标头中使用的值。该因人而异头包含应由缓存服务器被键入头名。这使我能够找到一些额外的易受攻击的实例,否则这些实例不会被检测到。
这是与 Param-Miner 的标头列表合并的标头列表。
https://gist.github.com/iustin24/92a5ba76ee436c85716f003dda8eecc6 (2917L)
通用headers
下面的列表显示了用于利用 70 多个缓存服务器的所有标头。

转载请注明出处及链接