What is HTTP Response Splitting?
HTTP Response Splitting (also known as CRLF Injection) is a vulnerability where an attacker can inject newline characters (\r\n or \n) into HTTP response headers. This can lead to:
- Cache poisoning attacks
- Cross-site scripting (XSS)
- Session fixation
- Response manipulation
Why This is Critical
HTTP Response Splitting can allow attackers to:
- Inject malicious headers into responses
- Create fake responses that get cached by proxies
- Inject arbitrary HTML/JavaScript into responses
- Bypass security controls and redirect users
How It Works in NGINX
The attack occurs when user-controlled input is used in directives that set HTTP headers or URLs. If the input contains newline characters, the attacker can terminate the current header and inject additional headers or even a complete response body.
Vulnerable NGINX Directives
These NGINX directives are susceptible to HTTP splitting when they contain user-controlled variables:
rewrite— URL rewriting with redirectsreturn— Returning redirects or custom responsesadd_header— Adding custom response headersproxy_set_header— Setting headers for upstream requestsproxy_pass— Proxying to dynamic backends
Dangerous Variables
These NGINX variables can contain newline characters when controlled by attackers:
$uri— The normalized request URI (can be manipulated via rewrites)$document_uri— Same as $uri$request_uri— The original request URI including query string$arg_*— Query string parameters$http_*— Any HTTP request header- Regex capture groups (
$1,$2, etc.) without proper anchoring
Vulnerable Patterns
Pattern 1: Redirect with User Input
# User can inject headers via $uri
rewrite ^ http://$host$uri permanent;
# Attack: GET /page%0d%0aSet-Cookie:evil=value HTTP/1.1
Pattern 2: Return with Query Parameter
# Attacker controls the redirect URL
location /redirect {
return 301 $arg_url;
}
# Attack: /redirect?url=http://evil%0d%0aX-Injected:true
Pattern 3: Custom Header from User Input
# User-controlled header value
add_header X-Original-URI $uri;
# If $uri is manipulated, attacker can inject headers
Pattern 4: Proxy Header with User Data
# User controls the forwarded URI
proxy_set_header X-Original-Uri $document_uri;
proxy_pass http://backend;
# Injection point for header manipulation
Pattern 5: Regex Capture Groups
# Unanchored regex allows injection
location ~ /proxy/(.*) {
set $path $1;
proxy_pass http://backend/$path;
}
# Attack: GET /proxy/page%0d%0aX-Injected:value HTTP/1.1
Secure Patterns
Use Hardcoded Values
# Redirect to a fixed location
return 301 https://example.com/;
# No user input in the redirect target
Validate and Sanitize
# Use map to whitelist allowed redirects
map $arg_page $redirect_url {
default "";
"home" "/";
"about" "/about";
"contact" "/contact";
}
location /redirect {
if ($redirect_url = "") {
return 400;
}
return 301 $redirect_url;
}
Use Safe Variables
# $host is safer than $http_host for redirects
# But still validate the destination domain
return 301 https://$host$request_uri;
Anchor Regex Patterns
# Properly anchored regex limits what can be captured
location ~ ^/api/v[12]/([a-zA-Z0-9_]+)$ {
# $1 can only contain alphanumeric and underscore
proxy_pass http://backend/$1;
}
Detecting with Gixy
Gixy automatically detects HTTP Response Splitting vulnerabilities in your NGINX configuration:
$ gixy /etc/nginx/nginx.conf
==================== Results ====================
[http_splitting] Possible HTTP-Splitting vulnerability.
Severity: HIGH
Description: Using variables that can contain "\n" or "\r"
may lead to http injection.
Reason: At least variable "$uri" can contain "\n"
Pseudo config:
server {
location / {
rewrite ^ http://$host$uri;
}
}
File: /etc/nginx/conf.d/site.conf
Line: 12
==================== Summary ====================
Total issues: 1 (High: 1)
gixy as part of your deployment process to catch HTTP splitting vulnerabilities before they reach production.
Real-World Impact
HTTP Response Splitting has been used in real attacks to:
- Deface websites — By injecting HTML content into cached responses
- Steal sessions — By injecting Set-Cookie headers
- Phish users — By redirecting to malicious sites via cache poisoning
- Bypass WAFs — By splitting requests to evade detection
Prevention Checklist
- Never use
$uri,$document_uri, or$request_uriin redirects - Never use
$arg_*variables directly in headers or URLs - Never use
$http_*variables without validation - Always anchor regex patterns with
^and$ - Restrict capture groups to safe character classes like
[a-zA-Z0-9_-] - Use
mapdirectives to whitelist allowed values - Run Gixy in your CI/CD pipeline to catch issues automatically