curl · Report #3153971
Stack Buffer Overflow in curl's OpenSSL Provider Handling
How it was found
Summary
Hello curl Team,
I found a stack buffer overflow in curl's OpenSSL provider handling code. The bug is in ossl_set_provider() function located in lib/vtls/openssl.c. When a provider name longer than MAX_PROVIDER_LEN is passed, the function copies it to a fixed-size buffer without proper length checking, causing stack overflow
Vulnerability Location
The buffer overflow happens in lib/vtls/openssl.c at line 2003-2004:
memcpy(name, curlx_str(&prov), curlx_strlen(&prov));
name[curlx_strlen(&prov)] = 0;
Code Analysis
I was looking at curl's SSL engine handling and noticed something strange in the provider setup. Here is what happens:
- The
ossl_set_provider()function defines a fixed buffer:
char name[MAX_PROVIDER_LEN + 1]; // line 1986
where MAX_PROVIDER_LEN is defined as 128 (line 1974 in the same file)
- Later in the function (line 2003-2004), it copies data from the provider string:
memcpy(name, curlx_str(&prov), curlx_strlen(&prov));
name[curlx_strlen(&prov)] = 0;
The problem is there's no check if curlx_strlen(&prov) is less than or equal to MAX_PROVIDER_LEN. This lets us overflow the stack-based buffer if we provide a string longer than 128 bytes
Also notice name[curlx_strlen(&prov)] = 0; this writes a null byte past the end of the buffer when overflow happens
Reproducing the Bug
I tried to find ways to trigger this issue. The code path is:
ossl_set_engine()inlib/vtls/openssl.ccallsossl_set_provider()ossl_set_engine()is called byCurl_ssl_set_engine()Curl_ssl_set_engine()is triggered byCURLOPT_SSLENGINEoption
I couldn't trigger a crash directly with curl command line because it stops with **"SSL Engine not found"**error before hitting the vulnerable code
Proof of Concept
I created a minimal PoC that reproduces the exact vulnerable code pattern:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// Same as in curl code
#define MAX_PROVIDER_LEN 128
typedef struct {
char *data;
size_t len;
} Curl_str;
// Mimicking curl's functions
char *curlx_str(Curl_str *s) {
return s->data;
}
size_t curlx_strlen(Curl_str *s) {
return s->len;
}
// Recreating the vulnerable function
void simulate_curl_provider_vulnerability(const char *iname) {
char name[MAX_PROVIDER_LEN + 1]; // Same buffer size as curl
Curl_str prov;
printf("[+] Input: %s\n", iname);
// Set up provider string
prov.data = (char *)iname;
prov.len = strlen(iname);
printf("[+] Provider length: %zu\n", prov.len);
printf("[+] Buffer size: %zu\n", sizeof(name));
// VULNERABLE PART - exactly as in curl source
memcpy(name, curlx_str(&prov), curlx_strlen(&prov));
name[curlx_strlen(&prov)] = 0;
printf("[+] Done\n");
}
int main(void) {
char *overflow_string = malloc(300);
// Creating long provider name to trigger overflow
strcpy(overflow_string, "pkcs11:");
for(int i = 0; i < 200; i++) {
strcat(overflow_string, "A");
}
// Call the vulnerable function
simulate_curl_provider_vulnerability(overflow_string);
free(overflow_string);
return 0;
}
When compiled with AddressSanitizer and run:
gcc -g -fsanitize=address -o poc poc.c
./poc
It clearly shows stack buffer overflow:
{F4365560}
Additional Notes
-
I tried to trigger this vulnerability directly using the curl command line tool but wasn't successful as curl returns an "SSL Engine not found" error before reaching the vulnerable code. However, the vulnerable code is clearly present in the curl source and confirmed with my PoC
-
I can provide more detailed analysis with GDB if needed
Impact
This bug allows overwriting stack memory with controlled content. In specific contexts, it could cause to:
- Remote code execution
- Denial of service
- Information disclosure
The severity depends on how this code is used in applications. It is most dangerous if an attacker can control provider name input
Thank you for reviewing also I can provide more detailed analysis with GDB if needed I didnt want to make the report very long