timing-attack-recon · git:20260518.7b5f854 · 2026-05-18 · sha256 a5f0b62e23d6378f

timing-attack-recon git:20260518.7b5f854B

Immutable. This exact content is served forever at /api/v1/blob/a5f0b62e23d6378f.

---
name: timing-attack-recon
description: Discover hidden parameters, headers, and scoped SSRFs via server-side timing differentials. Use when traditional fuzzing returns uniform responses but you suspect hidden backend logic or internal proxy routing.
---

# Timing Attack Recon

Measure response time deltas to find attack surface invisible in response bodies. Server-side operations (DNS lookup, DB query, log write, proxy routing) add 5-50ms. Isolate these from network jitter using single-packet synchronization.

## Why This Exists

Standard fuzzing keys on status codes, body diffs, content-length. When the app returns identical responses regardless of input, timing is the only remaining signal. This technique found hidden parameters and scoped SSRFs that content-based fuzzing missed entirely.

## Eliminate Network Jitter First

Server-side deltas are 1-50ms. Network jitter is 10-100ms+. You **must** eliminate jitter or you'll drown in noise.

**HTTP/2 single-packet**: Send N requests multiplexed in one TCP packet. All arrive within ~1ms. Compare response times — delta is pure server-side.

**HTTP/1.1 last-byte sync**: Open N connections, send all but final byte, release final bytes simultaneously. ~4ms spread.

Use Turbo Intruder's single-packet attack mode or `curl --parallel` over H2.

## Baseline

Before testing, establish what "normal" looks like:
1. Send 20 identical requests via single-packet
2. Record response times
3. Calculate mean and stddev
4. Anything >2 stddev above mean on a specific input = signal

## Hidden Parameter Discovery

Add candidate parameters one at a time. Parameters that trigger server-side logic add measurable delay.

**Why parameters cause delays:**
- DNS lookup on parameter value (app tries to resolve it)
- Log write for unexpected parameter name
- Validation/regex check on specific parameter names
- DB query triggered by parameter presence (feature flags, debug modes)

```bash
# Manual with curl timing
for param in debug admin internal test verbose trace; do
  time curl -s -o /dev/null -w "%{time_total}" "https://target.com/api?${param}=1"
done
```

**Better**: Use Param Miner (Burp) which automates this with statistical analysis, or Turbo Intruder with timing comparison.

Consistent 5ms+ delta on a specific parameter = that parameter triggers backend logic. Investigate further even if the response body is unchanged.

## Hidden Header Discovery

Same principle. Add candidate headers, measure timing.

Priority headers to test:
- `X-Forwarded-For`, `X-Real-IP`, `X-Original-URL`, `X-Rewrite-URL`
- `X-Debug`, `X-Debug-Token`, `X-Admin`, `X-Internal`
- `X-Forwarded-Host`, `X-Forwarded-Proto`, `X-Forwarded-Scheme`

## Scoped SSRF Detection via Timing

This is the highest-value technique. Detect proxy endpoints that route to internal services — even when responses are identical.

**How it works**: A proxy that allows certain domains routes requests internally (fast). Blocked domains either timeout or get rejected (different timing). Even if both return `200 OK` with identical bodies, the timing differs.

```
?url=https://google.com        → 200ms (external, blocked or slow)
?url=https://internal.corp.com  → 45ms  (internal, routed directly)
?url=https://10.0.0.1           → 48ms  (internal, routed directly)
```

### Enumerate Internal Targets
Once you've identified a scoped proxy via timing:
1. Feed it your subdomain list — timing reveals which resolve internally
2. Test RFC1918 ranges on common ports (80, 443, 8080, 8443)
3. Use `surf -l hosts.txt` to pre-filter candidates that are internal-only

### Front-End Impersonation
If the proxy respects `X-Forwarded-For`:
```
Request without header:             150ms
Request with X-Forwarded-For: 10.0.0.1:  45ms (internal routing!)
```
The header convinced the proxy you're internal. Now access internal-only endpoints.

## Decision Logic

```
Target returns uniform responses to all inputs
  ├── Establish timing baseline (20 identical requests, single-packet)
  ├── Fuzz parameters → any with >2 stddev delay?
  │     └── Yes → investigate that parameter (feature flag? debug? SSRF?)
  ├── Fuzz headers → any with timing delta?
  │     └── Yes → test X-Forwarded-For/Host impersonation
  ├── Suspect proxy/SSRF endpoint?
  │     ├── Compare timing: external domain vs internal IP vs internal subdomain
  │     └── Fast response on internal = scoped SSRF → enumerate internal services
  └── All uniform → timing vector exhausted, try other approaches
```

## Chain With
- blind-ssrf-chains (exploit the scoped SSRF you discovered)
- 403-bypass (hidden headers may bypass ACLs)
- race-condition-single-packet (same single-packet technique, different goal)

## Reference
- https://portswigger.net/research/listen-to-the-whispers-web-timing-attacks-that-actually-work (James Kettle, 2023)