Stack use-after-scope in HTTP/3 POST request processing via CURLOPT_POSTFIELDS
High
C
curl
Submitted None
Actions:
Reported by
geeknik
Vulnerability Details
Technical details and impact analysis
## Summary
A stack use-after-scope vulnerability exists in libcurl's HTTP/3 request processing when using `CURLOPT_POSTFIELDS` with stack-allocated buffers. libcurl retains a pointer to user-provided POST data but accesses it after the original stack frame has been destroyed, leading to memory corruption and potential denial of service.
The vulnerability occurs in `Curl_pretransfer()` at `transfer.c:569` when libcurl calls `strlen()` on the previously stored POST data pointer that now points to invalid stack memory.
## Steps to Reproduce / Proof of Concept
### Environment
- libcurl version: 8.16.0-DEV (master branch)
- Compiler: Clang 20.1.8 with AddressSanitizer
- Platform: macOS (ARM64)
- Configuration: HTTP/3 enabled with ngtcp2/nghttp3
### Reproduction Steps
1. Build libcurl with ASAN:
```bash
export CC=clang
export CFLAGS="-O1 -g -fsanitize=address,undefined"
./configure --with-openssl --with-nghttp2 --with-nghttp3 --with-ngtcp2
make
```
2. Compile the reproducer:
```
// http3_crash_poc.c
#include <curl/curl.h>
#include <string.h>
int main() {
CURL *curl = curl_easy_init();
// Stack-allocated buffer that goes out of scope
{
char body_data[257];
memset(body_data, 'A', 256);
body_data[256] = '\0';
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_3);
curl_easy_setopt(curl, CURLOPT_POST, 1L);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body_data); // Vulnerable call
curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, 50L);
} // body_data goes out of scope here
// libcurl accesses invalid memory during transfer
curl_easy_perform(curl);
curl_easy_cleanup(curl);
return 0;
}
```
3. Compile and run:
```bash
clang -fsanitize=address http3_crash_poc.c -lcurl -o poc
./poc
```
### Crash Output
```
==3720==ERROR: AddressSanitizer: stack-use-after-scope on address 0x00016fa21470
READ of size 45 at 0x00016fa21470 thread T0
#0 strlen
#1 Curl_pretransfer transfer.c:569
#2 multi_runsingle multi.c:2376
#3 curl_multi_perform multi.c:2756
#4 easy_transfer easy.c:705
#5 easy_perform easy.c:813
SUMMARY: AddressSanitizer: stack-use-after-scope transfer.c:569 in Curl_pretransfer
```
### Fuzzer Discovery
This vulnerability was discovered using a custom libFuzzer fuzzing harness.
## Technical Analysis
### Root Cause
The vulnerability stems from libcurl's `CURLOPT_POSTFIELDS` behavior:
1. libcurl stores the pointer but doesn't copy the data
2. The application's stack buffer becomes invalid after scope exit
3. libcurl later dereferences the invalid pointer in `Curl_pretransfer()`
### Affected Code Path
curl_easy_setopt(CURLOPT_POSTFIELDS) →
curl_easy_perform() →
Curl_pretransfer() →
strlen(invalid_pointer) →
CRASH
### Recommended Fix
1. Documentation: Clarify that `CURLOPT_POSTFIELDS` data must remain valid until transfer completion
2. API Enhancement: Consider adding bounds checking or automatic copying for stack-detected pointers
3. Alternative API: Promote `CURLOPT_COPYPOSTFIELDS` for safer usage patterns
## Impact
## Security Impact
1. Denial of Service: Guaranteed crash leading to application termination
2. Memory Corruption: Use-after-scope can lead to unpredictable behavior
3. Potential Code Execution: In specific circumstances, memory corruption could be leveraged for control flow hijacking
### Affected Scenarios
- Applications using libcurl for HTTP/3 requests with POST data
- Any code pattern where CURLOPT_POSTFIELDS points to stack-allocated memory
- Particularly affects:
- HTTP/3 client applications
- API clients using stack buffers for request bodies
- Embedded systems with limited heap usage
### Real-World Exposure
- Language bindings: Many curl bindings may inadvertently create this pattern
- Example applications: CLI tools, web scrapers, API clients
- Severity: High due to HTTP/3 adoption growth and remote exploitability
Report Details
Additional information and metadata
State
Closed
Substate
Not-Applicable
Submitted
Weakness
Use After Free