在本文中,我将分享缓存中毒漏洞的多种技术,这些技术让我在Bug Bounty上实现了财富自由。
故事背景
在2020年12月19日,我发布了一篇关于影响 Varnish 配置的特定边缘案例的文章,其中提到在请求包中将 HOST 头改为大写可能导致缓存中毒。然而这需要特定的自定义 Varnish 配置。
在发布文章后不久,我发现在 Cloudflare 也存在相同的大写 HOST 头缓存攻击漏洞,并且并不需要自定义配置。这意味着 Cloudflare 在将 HOST 头引入缓存键之前会将其转换为小写,但始终按客户端发送的形式转发。如果任何位于 Cloudflare 后的后端在收到大写 HOST 头时返回不同的响应,这将导致缓存被污染。
这一细微的不一致性使得一部分常见的漏洞赏金目标受到影响,因此我决定进一步探索其他方法,在更大范围内识别和利用这些漏洞。
下面我对一些漏洞做分享。
Apache Traffic Server
Apache Traffic Server 中对 URL 片段的不当处理,导致了缓存污染,而这也使得我获得了 CVE-2021-27577。
Apache Traffic Server(ATS)是一种广泛应用于 Yahoo 和 Apple 的缓存 HTTP 代理。当发送到 ATS 的请求包含 URL 片段时,ATS 会在不剥离片段的情况下转发请求。
根据 RFC7230,ATS 转发的请求是无效的,因为原始形式应该仅由绝对路径和查询组成:
此外,ATS 在生成缓存键时通过提取主机、路径和查询来忽略URL片段。这意味着以下两个请求将共享相同的缓存键:
由于 ATS 在生成缓存键时忽略 URL 片段,但仍然转发它,因此这为缓存中毒攻击提供了机会。当 ATS 后面的代理配置为将 # 编码为 %23 时,攻击者可以在任何缓存键下缓存完全不同的路径。我能够使用这种技术来污染静态文件,如下所示:
如果后端也对 /../ 进行了规范化,攻击者将能够将用户重定向到任何路径,从而实现XSS和开放重定向的升级:
GitHub
由于许多缓存中毒漏洞是由未加密的头部引起的,我编写了一个工具,可以对未加密的头部进行暴力破解并检测缓存中毒。这使我能够快速大规模扫描漏洞赏金目标。
由于许多漏洞赏金计划将GitHub仓库包括在其范围列表中,因此一些仓库 URL 也进入了我的目标列表。在查看扫描结果时,我注意到所有 GitHub 仓库在头部内容类型包含无效值时都被标记为易受缓存中毒攻击。
尽管扫描标记了 GitHub 仓库为易受攻击,且攻击在 Burp Suite 中有效,但我在浏览器中无法重现。很快,我意识到 GitHub 在缓存键中包含了身份验证 cookie。虽然无法对已认证用户的仓库进行缓存中毒,但对于所有访问仓库的未认证用户来说,由于他们共享相同的缓存键,我能够使这些仓库无法访问。这一发现使我获得了7500美元的奖励。
GitLab
GitLab 使用 Google Cloud Platform 和 Fastly 来托管静态文件,地址为https://assets.gitlab-static.net/*。
默认情况下,Google Cloud 存储桶支持使用 x-http-method-override 头,这允许HTTP方法被覆盖。
添加头部 x-http-method-override: POST 会返回405状态码实现缓存中毒。而 Fastly 默认不会缓存此响应。
然而,发送头部 x-http-method-override: HEAD 则可以实现缓存中毒,返回空响应体。
此外,PURGE 方法也被启用,这大大降低了攻击的复杂性。这一发现使我获得了4850美元奖励。除了 GitLab,我还能够在多个其他漏洞赏金目标上使用相同的技术。
X-Forwarded-Scheme - Rack 中间件
Ruby on Rails 应用程序通常与 Rack 中间件一起部署。下面的 Rack 代码获取 x-forwarded-scheme 的值,并将其用作请求的方案。
发送 x-forwarded-scheme: http 会导致301重定向到相同的位置。如果响应被CDN缓存,这将造成重定向循环,从而阻止用户访问文件。这一漏洞在多个漏洞赏金目标中被证明有效,例如下面这个案例。
Hackerone静态文件
由于 Hackerone 的缓存配置仅缓存静态文件,因此缓存中毒攻击仅限于静态文件。
尽管在报告时,拒绝服务漏洞不在范围内,这一发现仍然获得了2500美元的奖励。
单一请求实现shopify DoS
同样的技术也影响了 www.shopify.com,但 Shopify 的缓存配置加大了攻击的影响力。由于服务器未配置为缓存HTML页面,而301请求默认被缓存,因此只需一次简单的请求即可触发缓存中毒导致的拒绝服务。
最初,这一发现获得了1300美元的奖励,但经过进一步调查,发现该漏洞也影响了其他本地化的子域和主机,如 apps.shopify.com。由于该漏洞影响了多个 Shopify 主机,并且只需一次请求即可导致缓存中毒,奖励金额增加到6300美元。
同时在21个子域实现储存型XSS
在测试一个私有程序时,我注意到在 Hackerone 发现的相同漏洞也能影响该私有程序的所有子域。不过,这次服务器还信任请求包中 X-Forwarded-Host 的值,这将允许攻击者将JS文件重定向到攻击者控制的 JavaScript。
由于这可能导致在目标主网站及其21个其他子域上产生存储型XSS,因此这一漏洞被评估为严重,并获得了3000美元奖励。
Cloudflare 及 Azure
作为最广泛使用的内容分发网络,Cloudflare 位于用户请求和实际存储服务(如 Amazon S3 存储桶)之间,充当一个中间层或代理。不幸的是,这种配置默认情况下容易受到缓存中毒攻击。
直到2021年8月3日之前,Cloudflare都会缓存403状态码,即使没有 Cache-Control 指令。因此发送无效的 Authorization 头即可使得攻击者能够毒化通过 Cloudflare 代理的任何托管在 S3 存储桶上的文件。
此外,Exodus 使用子域 downloads.exodus.com 提供下载,如 Exodus 钱包安装程序。由于这些文件存储在 Azure Storage Blob 上,通过特制的Authorization 头可以导致可缓存的403错误。
Exodus团队在收到报告后几个小时内修复了这个问题,并奖励了2500美元的奖金。
Fastly HOST 头注入
在向同一个漏洞赏金计划报告多次缓存中毒漏洞后,他们同意将他们的 Varnish 配置文件发送给我,在浏览该文件时,我发现了一个类似下面的代码片段:
该片段用于托管地图图像的子域。请求图像的格式如下:
引入的规则使得当URL路径与正则表达式匹配时,从URL提取的坐标将被作为缓存键。因此,以上请求的图像将具有以下缓存键:
/4/151/16
我发现,如果请求包中存在 Fastly-Host 头,且其包含白名单中的值,即可实现 DoS。
例如:
GET /maps/1.0.5/map/4/151/16.png
Host: maps.redacted.com
Fastly-Host: redacted.com
此时用户访问maps.redacted.com/maps/1.0.5/map/4/151/16.png时,
实际上是访问redacted.com/maps/1.0.5/map/4/151/16.png,导致DoS。
我决定深入挖掘。在查看该程序上其他Fastly主机时,我发现 redacted-cdn.com 上的一个 HTML 文件存在 DOM XSS 漏洞。
因此我是这样做的:
由于两个主机位于同一个负载均衡器后,因此可以将托管在 redacted-cdn.com 上的文件缓存到 assets.redacted.com 上,从而使我能够将易受攻击的 HTML 文件移动到不同的域名,并在不同的源下实现 XSS。
注入键控参数
缓存通常被配置为仅在缓存键中包含特定的 GET 参数。这在托管图像的 CDN 中特别常见,通常使用参数来修改图像的大小或格式。
在测试一个使用 Fastly 缓存图像的目标时,我注意到 size 参数被包含在缓存键中,但所有其他参数都被忽略。如果添加两个 size 参数,两个都会包含在缓存键中,但后端服务器使用的是最后一个参数的值。
考虑到Fastly(Varnish)在生成缓存键之前并不进行任何 URL 规范化(URL解码),我能够实现以下DoS:
对第二个 size 参数进行URL编码导致它被缓存忽略,但后端仍会使用它。将该参数的值设为 0 会导致返回可缓存的 400 Bad Request。
用户代理规则
由于像 FFUF 或 Nuclei 这样的工具会生成高流量,一些开发者决定阻止与其用户代理匹配的请求。然而,这些调整可能会引入不必要的缓存中毒拒绝服务机会。
我发现这在多个目标上有效,尤其是来自不同工具或扫描器的用户代理。
非法标头字段
根据RFC7230,请求包的头部名称格式定义如下:
理论上,如果头部名称包含除列出的 tchar 之外的字符,应返回 400 Bad Request 错误。然而,在实际中,服务器并不总是遵循RFC。
最简单的利用这一细微差别的方法是针对 Akamai,它不会拒绝无效头部,而是转发它们,并缓存任何 400 错误,只要没有Cache-Control头。
如图:
发送一个包含非法字符的头部会导致可缓存的400 Bad Request错误。
通用标头
下面的列表显示了我进行此类漏洞挖掘的绝大部分标头:
最后
将测试限制在暴力破解范围内往往会错过隐藏在服务器堆栈复杂性中的攻击技术。自定义缓存配置、URL 解析差异或未记录的报头会引入意外行为,从而导致缓存的任意重定向、DoS 甚至 JS 文件覆盖。
原文出处:
https://youst.in/posts/cache-poisoning-at-scale/
原文始发于微信公众号(玲珑安全):一个漏洞让我年入数百万
- 左青龙
- 微信扫一扫
- 右白虎
- 微信扫一扫
评论