Performing Web Cache Poisoning Attack
实施Web缓存污染攻击
- During authorized penetration tests when the application uses CDN or reverse proxy caching (Cloudflare, Akamai, Varnish, Nginx)
- When assessing web applications for cache-based vulnerabilities that could affect all users
- For testing whether unkeyed HTTP headers are reflected in cached responses
- When evaluating cache key behavior and cache deception vulnerabilities
- During security assessments of applications with aggressive caching policies
- 在授权渗透测试中,当应用使用CDN或反向代理缓存(Cloudflare、Akamai、Varnish、Nginx)时
- 评估Web应用中可能影响所有用户的基于缓存的漏洞时
- 测试未加入缓存键的HTTP头是否会在缓存响应中被反射时
- 评估缓存键行为和缓存欺骗漏洞时
- 对采用激进缓存策略的应用进行安全评估时
- Authorization: Written penetration testing agreement explicitly covering cache poisoning testing
- Burp Suite Professional: With Param Miner extension for automated unkeyed header discovery
- curl: For manual cache testing with precise header control
- Target knowledge: Understanding of the caching layer (CDN provider, cache headers)
- Cache buster: Unique query parameter to isolate test requests from other users
- Caution: Cache poisoning affects all users; test with cache-busting parameters first
Legal Notice: This skill is for authorized security testing and educational purposes only. Unauthorized use against systems you do not own or have written permission to test is illegal and may violate computer fraud laws.
- 授权:明确涵盖缓存污染测试的书面渗透测试协议
- Burp Suite Professional:安装Param Miner扩展以自动发现未加入缓存键的请求头
- curl:用于手动缓存测试,实现精准的请求头控制
- 目标知识:了解缓存层(CDN供应商、缓存请求头)
- 缓存破坏参数:唯一的查询参数,用于将测试请求与其他用户的请求隔离开
- 注意事项:缓存污染会影响所有用户;测试时先使用缓存破坏参数
法律声明:本技能仅用于授权安全测试和教育目的。未经授权对不属于您或未获得书面测试许可的系统使用本技能属于违法行为,可能违反计算机欺诈相关法律。
Step 1: Identify the Caching Layer and Behavior
步骤1:识别缓存层及其行为
Determine what caching infrastructure is in use and how the cache key is constructed.
Check cache-related response headers
检查与缓存相关的响应头
Common cache indicators:
常见缓存标识:
X-Cache: HIT / MISS
X-Cache: HIT / MISS
CF-Cache-Status: HIT / MISS / DYNAMIC (Cloudflare)
CF-Cache-Status: HIT / MISS / DYNAMIC (Cloudflare)
Age: 120 (seconds since cached)
Age: 120(缓存已生成的秒数)
X-Varnish: 12345 67890 (Varnish)
X-Varnish: 12345 67890 (Varnish)
Via: 1.1 varnish (Varnish/CDN proxy)
Via: 1.1 varnish (Varnish/CDN代理)
Determine cache key by testing variations
通过测试变体确定缓存键
Cache key typically includes: Host + Path + Query string
缓存键通常包含:Host + 路径 + 查询字符串
Test 1: Same URL, two requests - check if second is cached
测试1:相同URL,发送两次请求 - 检查第二次是否命中缓存
First: MISS, Second: HIT = caching is active
第一次:MISS,第二次:HIT = 缓存已激活
Test 2: Vary header behavior
测试2:Vary请求头行为
Vary: Accept-Encoding means Accept-Encoding is part of cache key
Vary: Accept-Encoding 表示Accept-Encoding是缓存键的一部分
Step 2: Discover Unkeyed Inputs with Param Miner
步骤2:使用Param Miner发现未加入缓存键的输入
Use Burp's Param Miner to find headers and parameters not included in the cache key but reflected in responses.
借助Burp的Param Miner查找未被纳入缓存键但会在响应中被反射的请求头和参数。
In Burp Suite:
在Burp Suite中:
1. Install Param Miner from BApp Store
1. 从BApp Store安装Param Miner
2. Right-click target request > Extensions > Param Miner > Guess headers
2. 右键点击目标请求 > Extensions > Param Miner > Guess headers
3. Param Miner will test hundreds of HTTP headers
3. Param Miner会测试数百个HTTP请求头
4. Check results in Extender > Extensions > Param Miner > Output
4. 在Extender > Extensions > Param Miner > Output中查看结果
Common unkeyed headers to test manually:
可手动测试的常见未加入缓存键的请求头:
X-Forwarded-Host, X-Forwarded-Scheme, X-Forwarded-Proto
X-Forwarded-Host, X-Forwarded-Scheme, X-Forwarded-Proto
X-Original-URL, X-Rewrite-URL
X-Original-URL, X-Rewrite-URL
X-Host, X-Forwarded-Server
X-Host, X-Forwarded-Server
Origin, Referer
Origin, Referer
X-Forwarded-For, True-Client-IP
X-Forwarded-For, True-Client-IP
Manual testing for unkeyed header reflection
手动测试未加入缓存键的请求头反射
Add cache buster to isolate testing
添加缓存破坏参数以隔离测试
CB="cachebuster=$(date +%s)"
CB="cachebuster=$(date +%s)"
Test X-Forwarded-Host reflection
测试X-Forwarded-Host的反射
Test X-Forwarded-Scheme
测试X-Forwarded-Scheme
Test X-Original-URL (path override)
测试X-Original-URL(路径覆盖)
Test X-Forwarded-Proto
测试X-Forwarded-Proto
Step 3: Exploit Unkeyed Header for Cache Poisoning
步骤3:利用未加入缓存键的请求头实施缓存污染
Craft requests that poison cached responses with malicious content.
Scenario: X-Forwarded-Host reflected in resource URLs
场景:X-Forwarded-Host在资源URL中被反射
Normal response includes: <script src="https://target.example.com/app.js">
正常响应包含:<script src="https://target.example.com/app.js">
Poisoned: <script src="https://evil.example.com/app.js">
被污染后:<script src="https://evil.example.com/app.js">
Step 1: Confirm reflection with cache buster
步骤1:使用缓存破坏参数确认反射存在
Step 2: Poison the actual cached page (WITHOUT cache buster)
步骤2:污染实际缓存页面(不使用缓存破坏参数)
WARNING: This affects all users - only do with explicit authorization
警告:这会影响所有用户 - 仅在获得明确授权后执行
Step 3: Verify cache is poisoned
步骤3:验证缓存已被污染
If evil.example.com appears, the cache is poisoned
如果出现evil.example.com,则缓存已被污染
Attack with X-Forwarded-Proto for HTTP downgrade
利用X-Forwarded-Proto实施HTTP降级攻击
May cause cached response to include http:// links, enabling MitM
Attack with multiple headers
使用多个请求头发起攻击
Step 4: Test Web Cache Deception
步骤4:测试Web缓存欺骗
Trick the cache into storing authenticated responses for public URLs.
诱使缓存将经过身份验证的响应存储为公共URL的内容。
Web Cache Deception attack
Web缓存欺骗攻击
The cache caches based on file extension (.css, .js, .jpg)
缓存基于文件扩展名(.css, .js, .jpg)进行缓存
If the application ignores path suffixes:
如果应用忽略路径后缀:
Step 1: As victim (authenticated), visit:
步骤1:作为受害者(已认证),访问:
If the application returns the profile page (ignoring .css suffix)
如果应用返回个人资料页面(忽略.css后缀)
AND the cache stores it because of .css extension...
并且缓存因.css扩展名而存储该页面...
Test application path handling
测试应用路径处理逻辑
Step 2: As attacker (unauthenticated), request:
步骤2:作为攻击者(未认证),发起请求:
If victim's profile data is returned, cache deception is confirmed
如果返回受害者的个人资料数据,则确认存在缓存欺骗漏洞
Test various static extensions
测试各种静态文件扩展名
Test path confusion patterns
测试路径混淆模式
/account/settings%2f..%2fstatic/style.css
/account/settings%2f..%2fstatic/style.css
/account/settings/..;/static/style.css
/account/settings/..;/static/style.css
/account/settings;.css
/account/settings;.css
Step 5: Test Parameter-Based Cache Poisoning
步骤5:测试基于参数的缓存污染
Exploit unkeyed query parameters or parameter parsing differences.
利用未加入缓存键的查询参数或参数解析差异发起攻击。
Unkeyed parameter (parameter not in cache key but reflected)
未加入缓存键的参数(参数不在缓存键中但会被反射)
Using UTM parameters that are often excluded from cache keys
使用通常被排除在缓存键之外的UTM参数
Parameter cloaking via parsing differences
通过解析差异进行参数伪装
Backend sees: callback=evil, Cache key ignores: callback
后端看到:callback=evil,缓存键忽略:callback
Fat GET request (body in GET request)
Fat GET请求(GET请求中包含请求体)
Cache key normalization differences
缓存键规范化差异
Some caches normalize query string order, some don't
部分缓存会规范化查询字符串顺序,部分不会
Test port-based cache poisoning
测试基于端口的缓存污染
Step 6: Validate Impact and Clean Up
步骤6:验证影响并清理
Confirm the attack impact and ensure poisoned cache entries are cleared.
Verify poisoned cache serves to other users
验证被污染的缓存是否会分发给其他用户
Use a different IP/User-Agent/session to verify
使用不同的IP/用户代理/会话进行验证
Check cache TTL to understand exposure window
检查缓存TTL以了解暴露时长
max-age=3600 means poisoned for 1 hour
max-age=3600 表示缓存会被污染1小时
Clean up: Force cache refresh
清理:强制缓存刷新
Some CDNs allow purging via API
部分CDN允许通过API清除缓存
Cloudflare: API call to purge cache
Cloudflare:调用API清除缓存
Varnish: PURGE method
Varnish:使用PURGE方法
Or wait for TTL to expire
或等待TTL过期
Document the cache poisoning window
记录缓存污染窗口
Start time: when poison request was sent
开始时间:发送污染请求的时间
End time: start time + max-age
结束时间:开始时间 + max-age
Affected users: all users hitting the cached URL during the window
受影响用户:在缓存窗口内访问该缓存URL的所有用户
| Concept | Description |
|---|
| Cache Key | The set of request attributes (host, path, query) used to identify cached responses |
| Unkeyed Input | HTTP headers or parameters not included in the cache key but reflected in responses |
| Cache Poisoning | Injecting malicious content into cached responses that are served to other users |
| Cache Deception | Tricking the cache into storing authenticated/private responses as public content |
| Vary Header | HTTP header specifying which request headers should be included in the cache key |
| Cache Buster | A unique query parameter used to prevent affecting the real cache during testing |
| TTL (Time to Live) | Duration a cached response remains valid before being refreshed |
| 概念 | 描述 |
|---|
| Cache Key(缓存键) | 用于识别缓存响应的请求属性集合(主机、路径、查询参数) |
| Unkeyed Input(未加入缓存键的输入) | 未被纳入缓存键但会在响应中被反射的HTTP请求头或参数 |
| Cache Poisoning(缓存污染) | 向缓存响应中注入恶意内容,分发给其他用户 |
| Cache Deception(缓存欺骗) | 诱使缓存将已认证/私有响应存储为公共内容 |
| Vary Header(Vary请求头) | 指定哪些请求头应被纳入缓存键的HTTP请求头 |
| Cache Buster(缓存破坏参数) | 用于在测试期间避免影响真实缓存的唯一查询参数 |
| TTL (Time to Live) | 缓存响应在被刷新前保持有效的时长 |
| Tool | Purpose |
|---|
| Burp Suite Professional | Request interception and cache behavior analysis |
| Param Miner (Burp Extension) | Automated discovery of unkeyed HTTP headers and parameters |
| Web Cache Vulnerability Scanner | Automated cache poisoning detection tool |
| curl | Manual HTTP request crafting with precise header control |
| Varnishlog | Varnish cache debugging and log analysis |
| CDN-specific tools | Cloudflare Analytics, Akamai Pragma headers for cache diagnostics |
| 工具 | 用途 |
|---|
| Burp Suite Professional | 请求拦截与缓存行为分析 |
| Param Miner (Burp Extension) | 自动发现未加入缓存键的HTTP请求头和参数 |
| Web Cache Vulnerability Scanner | 自动检测缓存污染漏洞的工具 |
| curl | 手动构造HTTP请求,实现精准的请求头控制 |
| Varnishlog | Varnish缓存调试与日志分析 |
| CDN专属工具 | Cloudflare Analytics、Akamai Pragma请求头,用于缓存诊断 |
Scenario 1: X-Forwarded-Host Script Injection
场景1:X-Forwarded-Host脚本注入
The application reflects the
header in script src URLs. This header is not part of the cache key. Sending a request with
X-Forwarded-Host: evil.com
poisons the cache to load JavaScript from the attacker's server for all subsequent visitors.
应用会在脚本src URL中反射
请求头,而该请求头未被纳入缓存键。发送包含
X-Forwarded-Host: evil.com
的请求会污染缓存,使后续所有访问者从攻击者的服务器加载JavaScript。
Scenario 2: Web Cache Deception on Account Page
场景2:账户页面的Web缓存欺骗
A Cloudflare-cached application ignores unknown path segments. Requesting
/account/profile/logo.png
returns the account page while Cloudflare caches it as a static image. Any unauthenticated user can then access the cached account page.
使用Cloudflare缓存的应用会忽略未知路径段。请求
/account/profile/logo.png
会返回账户页面,同时Cloudflare将其作为静态图片缓存。任何未认证用户都可以访问该缓存的账户页面。
Scenario 3: Parameter-Based XSS via Cache
场景3:基于参数的缓存型XSS
UTM tracking parameters are excluded from the cache key but rendered in the page HTML. Injecting
tags via
parameter poisons the cache with stored XSS affecting all visitors.
UTM跟踪参数被排除在缓存键之外,但会在页面HTML中渲染。通过
参数注入
标签会污染缓存,导致存储型XSS影响所有访问者。
Scenario 4: CDN Cache Poisoning via Host Header
场景4:通过Host请求头实施CDN缓存污染
Multiple applications are behind the same CDN. Manipulating the Host header causes the CDN to cache a response from one application under another application's cache key.
多个应用位于同一CDN后方。操纵Host请求头会导致CDN将一个应用的响应缓存到另一个应用的缓存键下。
Web Cache Poisoning Finding
Web缓存污染漏洞发现
Vulnerability: Web Cache Poisoning via Unkeyed Header
Severity: High (CVSS 8.6)
Location: X-Forwarded-Host header on all pages
OWASP Category: A05:2021 - Security Misconfiguration
漏洞类型:基于未加入缓存键请求头的Web缓存污染
严重程度:高(CVSS 8.6)
位置:所有页面的X-Forwarded-Host请求头
OWASP分类:A05:2021 - 安全配置错误
| Property | Value |
|---|
| CDN/Cache | Cloudflare |
| Cache-Control | max-age=3600, public |
| Unkeyed Headers | X-Forwarded-Host, X-Forwarded-Proto |
| Affected Pages | All HTML pages (/*.html) |
| 属性 | 值 |
|---|
| CDN/缓存 | Cloudflare |
| Cache-Control | max-age=3600, public |
| 未加入缓存键的请求头 | X-Forwarded-Host, X-Forwarded-Proto |
| 受影响页面 | 所有HTML页面(/*.html) |
- Send request with X-Forwarded-Host: evil.example.com
- Response includes: <link href="https://evil.example.com/style.css">
- This response is cached by Cloudflare for 3600 seconds
- All subsequent visitors receive the poisoned response
- 发送包含X-Forwarded-Host: evil.example.com的请求
- 响应包含:<link href="https://evil.example.com/style.css">
- 该响应被Cloudflare缓存3600秒
- 后续所有访问者都会收到被污染的响应
- JavaScript execution in all users' browsers (via poisoned script src)
- Credential theft, session hijacking, defacement
- Affects estimated 50,000 daily visitors during 1-hour cache window
- Can be re-poisoned continuously for persistent attack
- 在所有用户的浏览器中执行JavaScript(通过被污染的脚本src)
- 凭据窃取、会话劫持、页面篡改
- 在1小时缓存窗口内影响约50,000日活用户
- 可持续重新污染缓存以发起持久化攻击
- Include X-Forwarded-Host and similar headers in the cache key via Vary header
- Do not reflect unkeyed headers in response content
- Configure the cache to strip unknown headers before forwarding to origin
- Use application-level hardcoded base URLs instead of deriving from headers
- Implement cache key normalization to prevent key manipulation
- 通过Vary请求头将X-Forwarded-Host及类似请求头纳入缓存键
- 不在响应内容中反射未加入缓存键的请求头
- 配置缓存,在转发到源服务器前剥离未知请求头
- 使用应用级硬编码基础URL,而非从请求头中推导
- 实现缓存键规范化,防止键被篡改