Use after free (read) in curl_multi_perform with DoH and Proxy options, and resolve timeouts
C
curl
Submitted None
Actions:
Reported by
catenacyber
Vulnerability Details
Technical details and impact analysis
## Summary:
[summary of the vulnerability]
There is a use after free in `curl_multi_perform` when DoH resolver timeouts and `CURLOPT_PROXY` is used (see reproducer and stack trace)
I found it via fuzzing with https://github.com/catenacyber/curl-fuzzer/tree/proxy (after fixing a small memory leak in curl)
Another reproducer was found with curl_fuzzer_mqtt
(I have other fuzzers reports)
## Affected version
[Which curl/libcurl version are you using to reproduce? On which platform? `curl -V` typically generates good output to include]
Master at commit 7b0240c07799c28dc84272f9e38e1092ce4cc498
```
curl 8.13.0-DEV (x86_64-apple-darwin23.6.0) libcurl/8.13.0-DEV OpenSSL/1.0.2n zlib/1.2.11 libidn2/2.0.4 libpsl/0.19.1 nghttp2/1.55.1 librtmp/2.3
Release-Date: [unreleased]
Protocols: dict file ftp ftps gopher gophers http https imap imaps ipfs ipns ldap ldaps mqtt pop3 pop3s rtmp rtsp smb smbs smtp smtps telnet tftp ws wss
Features: alt-svc AsynchDNS HSTS HTTP2 HTTPS-proxy IDN IPv6 Largefile libz NTLM PSL SSL threadsafe TLS-SRP UnixSockets
```
## Steps To Reproduce:
[add details for how we can reproduce the issue]
1. Run the following example
```c
#include <stdio.h>
#include <curl/curl.h>
int main(void)
{
CURL *curl;
int still_running;
curl = curl_easy_init();
if(curl) {
CURLM *multi_handle = curl_multi_init();
curl_multi_add_handle(multi_handle, curl);
curl_easy_setopt(curl, CURLOPT_DOH_URL, "doh");
curl_easy_setopt(curl, CURLOPT_PROXY, "proxy");
curl_easy_setopt(curl, CURLOPT_URL, "tftp://curl.se/");
curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, 50L);
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
curl_easy_setopt(curl, CURLOPT_SERVER_RESPONSE_TIMEOUT, 1L);
curl_easy_setopt(curl, CURLOPT_PROTOCOLS_STR, "tftp");
curl_multi_perform(multi_handle, &still_running);
while (still_running > 0) {
printf("still_running %d\n", still_running);
struct timespec remaining, request = { 0, 60000000 };
// We should do a select, but let's just wait for timeout for reproducibility
nanosleep(&request, &remaining);
curl_multi_perform(multi_handle, &still_running);
}
curl_multi_remove_handle(multi_handle, curl);
curl_multi_cleanup(multi_handle);
curl_easy_cleanup(curl);
}
return 0;
}
```
## Supporting Material/References:
[list any additional material (e.g. screenshots, logs, etc.)]
Output when curl is compiled with `--enable-debug` and stack trace from ASAN is
```
* Added connection 0. The cache now contains 1 members
* Resolving timed out after 61 milliseconds
* Curl_disconnect(conn #0, aborted=1)
* closing connection #0
=================================================================
==47284==ERROR: AddressSanitizer: heap-use-after-free on address 0x622000003148 at pc 0x00010e3a3397 bp 0x7ff7b25cf1c0 sp 0x7ff7b25cf1b8
READ of size 4 at 0x622000003148 thread T0
#0 0x10e3a3396 in Curl_node_elem llist.c:248
#1 0x10e3c5cba in curl_multi_perform multi.c:2604
#2 0x10d931c46 in main pocuaf.c:29
#3 0x7ff8011a4344 in start+0x774 (dyld:x86_64+0xfffffffffff5c344)
0x622000003148 is located 72 bytes inside of 5760-byte region [0x622000003100,0x622000004780)
freed by thread T0 here:
#0 0x10ecacdb6 in free+0xa6 (libclang_rt.asan_osx_dynamic.dylib:x86_64h+0xe0db6)
#1 0x10e3a47fd in curl_dbg_free memdebug.c:297
#2 0x10e436f30 in Curl_close url.c:337
#3 0x10e31d12a in Curl_doh_close doh.c:1305
#4 0x10e3e5ea4 in Curl_req_done request.c:110
#5 0x10e3c2308 in multi_done multi.c:597
#6 0x10e3ce6ff in multi_handle_timeout multi.c:1583
#7 0x10e3c72d3 in multi_runsingle multi.c:2242
#8 0x10e3c5c8e in curl_multi_perform multi.c:2620
#9 0x10d931c46 in main pocuaf.c:29
#10 0x7ff8011a4344 in start+0x774 (dyld:x86_64+0xfffffffffff5c344)
previously allocated by thread T0 here:
#0 0x10ecad042 in calloc+0xa2 (libclang_rt.asan_osx_dynamic.dylib:x86_64h+0xe1042)
#1 0x10e3a424d in curl_dbg_calloc memdebug.c:175
#2 0x10e4380fb in Curl_open url.c:499
#3 0x10e319c09 in doh_run_probe doh.c:272
#4 0x10e319445 in Curl_doh doh.c:436
#5 0x10e357a63 in Curl_resolv hostip.c:813
#6 0x10e44445c in resolve_server url.c:3250
#7 0x10e43e70c in Curl_connect url.c:3803
#8 0x10e3c76e2 in multi_runsingle multi.c:2275
#9 0x10e3c5c8e in curl_multi_perform multi.c:2620
#10 0x10d931bb9 in main pocuaf.c:22
#11 0x7ff8011a4344 in start+0x774 (dyld:x86_64+0xfffffffffff5c344)
```
## Impact
## Summary:
I am not sure if this UAF can be used to gain RCE, or as it is a UAF read to bypass ASLR
Report Details
Additional information and metadata
State
Closed
Substate
Informative
Submitted
Weakness
Use After Free