Report

CVE-2023-38545 curl SOCKS5 heap overflow via slow handshake state-machine bypass

d528b487-216a-43b2-af8f-7fa76b1967dc

CVE-2023-38545 — curl SOCKS5 heap buffer overflow during slow proxy handshake. In lib/socks.c do_SOCKS5(), the socks5_resolve_local boolean is a stack-local re-initialized each call. The long-hostname guard (hostname_len > 255 forces local resolution) only executes inside case CONNECT_SOCKS_INIT. If the initial auth-method send is partial, the function returns early with state CONNECT_SOCKS_SEND; on re-entry, the INIT case is skipped, the guard never runs, and the code reaches CONNECT_RESOLVE_REMOTE which memcpys hostname_len bytes (can be ~64KB) into data->state.buffer (sized by CURLOPT_BUFFERSIZE, minimum 1024). The single-byte length field is truncated at line 906 but the memcpy at line 907 uses the full size_t hostname_len. Vulnerable code: lib/socks.c lines 573 (bool decl), 589-593 (guard), 624-626 (early return preserves state), 905-908 (overflow memcpy). 1) ls repos/curl/lib/ | grep socks — found socks.c, socks.h. 2) Grepped socks5_resolve_local|Curl_SOCKS5|SOCKS5 in socks.c — located do_SOCKS5 at line 548. 3) Read 540-740 to see state machine entry: local bool declaration (line 573-574), >255 guard (line 589-593), and early return on partial send via sx->outstanding (lines 624-626). 4) Read 775-920 to follow CONNECT_RESOLVE_REMOTE and find unchecked memcpy at line 907 with truncated length byte at line 906. 5) Confirmed socksreq aliases data->state.buffer via line 569: unsigned char *socksreq = (unsigned char *)data->state.buffer;. Call chain from briefing matches: curl_easy_perform -> Curl_connect -> Curl_SOCKS5 -> do_SOCKS5. Key grep patterns that worked fast: socks5_resolve_local, memcpy.*hostname, CONNECT_SOCKS_SEND.