| name | Cache Poisoning |
| description | This skill should be used when the user asks about "cache poisoning", "web cache deception", "CDN cache", "proxy cache", "nginx cache", "varnish", "cache key manipulation", "response caching", or needs to find cache-related vulnerabilities during whitebox security review. |
| version | 1.0.0 |
Cache Poisoning & Web Cache Deception
Purpose
Provide detection patterns for HTTP cache poisoning and web cache deception vulnerabilities, including proxy cache misconfigurations, cache key manipulation, and authenticated response caching.
OWASP Top 10 Mapping
Category: Related to A01 (Broken Access Control), A05 (Security Misconfiguration)
CWEs:
- CWE-524: Use of Cache Containing Sensitive Information
- CWE-525: Use of Web Browser Cache Containing Sensitive Information
- CWE-444: Inconsistent Interpretation of HTTP Requests
- CWE-436: Interpretation Conflict
When to Use
Activate this skill when:
- Reviewing proxy/CDN configurations (Nginx, Varnish, Cloudflare, etc.)
- Analyzing SSRF vulnerabilities for exfiltration vectors
- Auditing applications with static file caching
- Looking for authenticated content exposure
- Checking cache key construction for manipulation
Web Cache Deception
Overview
Web cache deception occurs when:
- Proxy caches responses based on file extension (e.g.,
.png, .css)
- Application serves dynamic content regardless of path extension
- Attacker tricks victim into visiting
/profile.png
- Proxy caches authenticated response
- Attacker retrieves cached sensitive data
Detection Patterns
Nginx Cache Configuration
grep -rniE "proxy_cache|proxy_cache_valid|proxy_cache_key" --include="*.conf" --include="nginx.conf"
grep -rniE "location.*\.(css|js|png|jpg|jpeg|gif|ico|svg|woff)" -A10 --include="*.conf" | grep -iE "proxy_cache|cache"
grep -rniE "proxy_cache_key" --include="*.conf"
grep -rniE "proxy_cache_valid\s+200" --include="*.conf"
Varnish Cache Configuration
grep -rniE "vcl_recv|vcl_hash|vcl_backend_response" --include="*.vcl"
grep -rniE "req\.url.*\.(css|js|png|jpg|jpeg|gif|ico)" --include="*.vcl"
grep -rniE "set beresp\.ttl|beresp\.grace" --include="*.vcl"
Apache/mod_cache
grep -rniE "CacheEnable|CacheRoot|CacheMaxExpire" --include="*.conf" --include=".htaccess"
grep -rniE "CacheEnable.*disk" --include="*.conf"
CDN/Cloud Configurations
grep -rniE "cache.*control|edge.*cache|cdn.*cache|cloudfront|cloudflare" --include="*.json" --include="*.yaml" --include="*.yml"
grep -rniE "Cache-Control|max-age|s-maxage|public|private" --include="*.go" --include="*.py" --include="*.java" --include="*.ts" --include="*.php"
Cache Key Manipulation
Detection Patterns
grep -rniE "Host.*header|getHeader.*Host|X-Forwarded-Host|X-Original-Host" --include="*.go" --include="*.py" --include="*.java" --include="*.ts" --include="*.php"
grep -rniE "query.*param|request\.query|getQueryString" --include="*.go" --include="*.py" --include="*.java" --include="*.ts" --include="*.php"
grep -rniE "proxy_cache_key.*query|CacheKeyQueryString" --include="*.conf" --include="*.vcl"
Cache Key Injection via Headers
grep -rniE "X-Forwarded-Host|X-Forwarded-Scheme|X-Forwarded-Proto" --include="*.conf" --include="*.go" --include="*.py"
grep -rniE "X-Original-URL|X-Rewrite-URL" --include="*.conf" --include="*.go" --include="*.py"
SSRF + Cache Poisoning Chain
Overview
When SSRF response is not directly returned to attacker:
- Make SSRF request to
/sensitive-endpoint.png
- Proxy caches the response (thinks it's static)
- Attacker requests same path
- Gets cached sensitive data
Detection Patterns
grep -rniE "requests\.get|http\.Get|fetch\(|axios\.|urllib" --include="*.py" --include="*.go" --include="*.js" --include="*.ts"
grep -rniE "url.*=.*request|uri.*=.*request|callback.*=.*request" --include="*.py" --include="*.go" --include="*.js" --include="*.ts"
grep -rniE "proxy_cache|cache_valid" -B5 -A5 --include="*.conf"
Verification Checklist for SSRF + Cache
Path Extension Abuse
Overview
Many caches use file extension to determine cacheability:
/api/user/profile - NOT cached (dynamic)
/api/user/profile.png - CACHED (static file)
If the application ignores the extension and serves the same content, this enables cache deception.
Detection Patterns
grep -rniE "route.*<path:|path:subpath|<.*:.*>" --include="*.py"
grep -rniE "app\.get\('\*'|router\.get\('\*'|\.use\('\/'," --include="*.js" --include="*.ts"
grep -rniE "location\s+/|location\s+~" -A10 --include="*.conf" | grep -iE "proxy_pass"
grep -rniE "\.split\('\.\'\)|path\.extname|endswith|path.*extension" --include="*.py" --include="*.go" --include="*.js" --include="*.ts"
Response Caching of Authenticated Content
Detection Patterns
grep -rniE "Vary.*header|add_header.*Vary" --include="*.conf" --include="*.go" --include="*.py"
grep -rniE "@login_required|@jwt_required|isAuthenticated|requireAuth" -A20 --include="*.py" --include="*.go" --include="*.js" --include="*.ts" | grep -iE "cache|response"
grep -rniE "Set-Cookie.*Cache|Cache-Control.*Set-Cookie" --include="*.conf" --include="*.py" --include="*.go"
Proper Cache Headers for Authenticated Content
Cache-Control: private, no-store, must-revalidate
Vary: Authorization, Cookie
CDN-Specific Patterns
Cloudflare
grep -rniE "page.*rules|cache.*level|cache.*everything" --include="*.json" --include="*.tf"
grep -rniE "bypass.*cache|cache\.bypass" --include="*.json"
AWS CloudFront
grep -rniE "CacheBehavior|DefaultCacheBehavior|CachePolicyId" --include="*.json" --include="*.yaml" --include="*.tf"
grep -rniE "OriginRequestPolicy|ForwardedValues" --include="*.json" --include="*.yaml"
Fastly/Akamai
grep -rniE "snippet|vcl_recv|vcl_hash" --include="*.vcl" --include="*.json"
grep -rniE "edge.*cache|surrogate.*key" --include="*.json" --include="*.yaml"
Framework-Specific Checks
Django
grep -rniE "django\.core\.cache|@cache_page|CACHES\s*=" --include="*.py"
grep -rniE "@vary_on_headers|@vary_on_cookie" --include="*.py"
Express/Node.js
grep -rniE "express\.static|serve-static|maxAge" --include="*.js" --include="*.ts"
grep -rniE "res\.set.*Cache|setHeader.*Cache" --include="*.js" --include="*.ts"
Spring Boot
grep -rniE "@Cacheable|@CacheEvict|@CachePut" --include="*.java"
grep -rniE "spring\.cache|CacheManager|EhCache|Redis" --include="*.properties" --include="*.yaml"
Go
grep -rniE "httpcache|groupcache|bigcache" --include="*.go"
grep -rniE "Cache-Control|w\.Header\(\)\.Set" --include="*.go"
Cross-Layer Analysis
Verification Steps
When analyzing cache vulnerabilities, check all layers:
-
Application Layer
- Does app handle path extensions?
- What data is in authenticated responses?
- Are Cache-Control headers set?
-
Proxy Layer (Nginx/HAProxy)
- What paths are cached?
- How is cache key constructed?
- What's the cache TTL?
-
CDN Layer (Cloudflare/CloudFront)
- Page rules / cache behaviors
- Origin cache settings
- Cache key configuration
Command to Check Full Stack
find . -name "*.conf" -o -name "*.vcl" -o -name "nginx*" -o -name "*cloudfront*" -o -name "*cdn*" 2>/dev/null | head -20
grep -rniE "cache|proxy_cache|vcl_|CDN|cloudfront|cloudflare" --include="*.conf" --include="*.vcl" --include="*.json" --include="*.yaml" --include="*.tf"
Exploitation Checklist
When cache vulnerabilities are found:
Example Attack Scenarios
Scenario 1: SSRF + Cache Deception (CDNio Pattern)
1. SSRF allows bot to visit internal URLs as admin
2. Nginx caches /*.png for 3 minutes
3. Make bot visit /profile.png (admin profile)
4. Request /profile.png → Get cached admin data
Scenario 2: Path Confusion
1. App serves /api/user regardless of extension
2. CDN caches /api/user.css (thinks it's static)
3. Attacker requests /api/user.css
4. Gets user profile from cache
Scenario 3: Host Header Poisoning
1. Cache key includes Host header
2. Inject X-Forwarded-Host: evil.com
3. Response contains evil.com URLs
4. Cache serves poisoned response to all users
Remediation
Nginx
# Don't cache authenticated responses
location ~* \.(css|js|png|jpg)$ {
proxy_cache cache;
proxy_cache_valid 200 3m;
# Add this to prevent caching authenticated responses
proxy_cache_bypass $http_authorization $cookie_session;
proxy_no_cache $http_authorization $cookie_session;
}
Application
@app.route('/profile')
@jwt_required
def profile():
response = make_response(jsonify(user_data))
response.headers['Cache-Control'] = 'private, no-store'
response.headers['Vary'] = 'Authorization'
return response
CDN
- Include Authorization/Cookie in cache key
- Use "Cache-Control: private" for authenticated content
- Set appropriate cache behaviors per path pattern
CWE References
| CWE | Name | Example |
|---|
| CWE-524 | Sensitive Info in Cache | Authenticated data cached |
| CWE-525 | Browser Cache Sensitive Info | Secrets in browser cache |
| CWE-444 | HTTP Request Smuggling | Cache poisoning via smuggling |
| CWE-436 | Interpretation Conflict | Path extension confusion |