# Cache and Host Header Security

> Cache key poisoning, Host/X-Forwarded-* header poisoning, CDN/reverse proxy bypass

## High-Risk Attack Surfaces
- Cache key does not include Host/protocol/authentication information → shared cache poisoning
- Trusting client Host/X-Forwarded-Host/X-Forwarded-Proto/X-Forwarded-Port
- Inconsistent proxy/gateway rewriting causes origin and edge cache key mismatch
- Path normalization differences (`//`, `/./`, `/../`, `;`) causing same resource to have different cache keys
- Hop-by-hop headers incorrectly cached (`Connection: keep-alive`, `Proxy-Authorization`)
- CDN custom headers (e.g., `X-True-Client-IP`) being forged

## Detection Checklist
- [ ] Does the application directly use `Host`/`X-Forwarded-*` to construct absolute URLs, redirects, or signed URLs?
- [ ] Does the cache key include Host + Path + Query + Protocol (to prevent cross-origin poisoning)?
- [ ] Does the proxy/gateway sanitize client Host/XFH/XFP/XFF?
- [ ] Is the Vary header correct (`Vary: Host, Authorization, Cookie, Origin, Accept-Encoding`, etc.)?
- [ ] Are responses with authentication context being cached (Cookie/Authorization/Bearer/Session)?
- [ ] Is normalization behavior consistent: do the gateway and application use the same rules (encoding, case, trailing slashes, semicolons)?
- [ ] Do CDN edge and origin share cache across different protocols/ports?
- [ ] Are internal management/authentication interfaces cached with `Cache-Control: private, no-store`?

## Dangerous Patterns
```nginx
# Trusting client Host, vulnerable to cache poisoning
proxy_set_header Host $http_host;   # Client-controlled
proxy_set_header X-Forwarded-Host $http_host;

# Not sanitizing XFH/XFP, used by backend for redirects
set $redirect_host $http_x_forwarded_host;
return 302 https://$redirect_host/login;
```

```js
// Node.js/Express - Using Host to construct redirects
const redirectUrl = `${req.protocol}://${req.get('host')}/login`; // Host can be poisoned
res.redirect(redirectUrl); // Open redirect + cache key poisoning
```

```conf
# CDN/proxy not setting Vary
Cache-Control: public, max-age=300
# Missing: Vary: Authorization, Cookie, Accept-Encoding
```

## Detection Commands
```bash
# Find usage of Host/X-Forwarded-*
rg -n "Host|X-Forwarded-(Host|Proto|Port|For)" --glob "*.{js,ts,java,go,py,rb,php,cs}"

# Nginx/Envoy/Traefik configuration
rg -n "proxy_set_header Host|X-Forwarded-Host|X-Forwarded-Proto|X-Forwarded-Port" --glob "*.{conf,yml,yaml}"
rg -n "set_real_ip_from|real_ip_header|trustProxy" --glob "*.{conf,yml,yaml}"

# Cache control/Vary
rg -n "Cache-Control|Vary" --glob "*.{conf,nginx,js,ts,go,py,java,cs,rb,php}"
```

## Security Baseline
- Gateway/proxy enforce rewriting: Set `Host` to a fixed upstream domain; sanitize client XFH/XFP/XFF
- Application uses trusted headers: Inject `X-Forwarded-Host-Safe` at the gateway, backend only reads this header
- Set correct Vary: `Vary: Host, Authorization, Cookie, Origin, Accept-Encoding`
- Authentication pages/user-specific responses: `Cache-Control: private, no-store`
- Consistent normalization: Disable semicolon routing, merge double slashes; canonicalize paths uniformly
- CDN: Isolate cache keys for HTTP/HTTPS/ports, disable anonymous caching of admin paths
- Web Cache Deception: Separate static/dynamic paths, prohibit caching sensitive responses with static suffixes
- ESI/edge injection: Disable unnecessary ESI; filter Edge-Side-Includes at origin

## Validation Steps
- Construct requests with different Host/XFH to the same path, observe if content from other tenants/domains is returned
- Do requests with Cookie/Bearer hit public cache? If yes, this is high risk
- Test if `//path`, `/./path`, `/path;param` produce different cache keys from `/path`
- Inject external domain via CDN/XFH, check if redirects, absolute URLs, or signed URLs can be forged

## Minimal PoC Examples
```bash
# Host poisoning + observe response
curl -H "Host: attacker.com" https://victim/resource -i
curl -H "X-Forwarded-Host: attacker.com" https://victim/resource -i

# Cache key poisoning (with Cookie/Bearer)
curl -H "Authorization: Bearer TOKEN" https://victim/account --dump-header headers.txt
curl https://victim/account --dump-header headers2.txt

# Path normalization
curl -I "https://victim//admin"
curl -I "https://victim/admin;%2f"

# Web Cache Deception
curl -I "https://victim/profile.php/.css"
```
