
CVE-2026-3805: Use-After-Free in curl SMB-Verbindungswiederverwendung - Heap-Info-Offenlegung
Ich habe eine Use-After-Free-Sicherheitslücke im SMB-Protokollhandler von libcurl gefunden. Wenn eine zweite SMB-Übertragung eine bestehende Verbindung zum selben Server wiederverwendet, ist der Dateipfad für die neue Anfrage (req->path) ein baumelnder Zeiger auf freigegebenen Heap-Speicher. Dieser Speicher wird über strlen() gelesen und in ein ausgehendes SMB-Paket kopiert, wodurch Heap-Inhalte an den Server gelangen oder ein Absturz verursacht wird.
Korrektur in einer Zeile: req->path besitzt seine eigene Kopie, anstatt von smbc->share der Nadel zu borgen.
| CVE | CVE-2026-3805 |
| Fehlerklasse | Use-After-Free (CWE-416) |
| Grundursache | req->path zeigt auf smbc->share der Nadel, wird bei Verbindungswiederverwendung freigegeben |
| Eingeführt | 777c5209df (2025-04-30) - curl 8.13.0 |
| Behoben | e090be9f73a7a71459ef678c - curl 8.19.0 (11. März 2026) |
| Betroffen | curl 8.13.0 bis 8.18.0 |
| Auswirkung | Offenlegung von Heap-Informationen an den Server, Absturz |
| Schweregrad | 7.5 - HOCH - CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H |
smb_setup_connection() wird auf einer temporären „Nadel“-Verbindung ausgeführt, die für die Cache-Suche verwendet wird. Es setzt req->path so, dass es innerhalb von smbc->share (Heap-Speicher, der der Nadel gehört) zeigt. Wenn der Verbindungscache eine wiederverwendbare Verbindung findet, wird die Nadel zerstört – dabei wird smbc->share freigegeben – aber req->path bleibt auf dem easy-Handle erhalten und zeigt nun auf freigegebenen Speicher.
Wenn smb_send_open() die SMB-OPEN-Anfrage erstellt, ruft es strlen(req->path) auf und kopiert das Ergebnis in das ausgehende Paket. Welche Daten auch immer in dieser freigegebenen Heap-Region liegen, gelangen zum Server. Wenn der Angreifer den Server kontrolliert (SSRF oder Benutzer, der eine Verbindung zu einem bösartigen SMB-Server herstellt), erhält er die geleakten Heap-Inhalte als „Dateiname“ in der SMB-NT_CREATE_ANDX-Anfrage.
libcurl verwendet aggressiv Verbindungswiederverwendung für die Leistung. Wenn Sie mehrere Anfragen an denselben Host stellen, überprüft curl, ob eine bestehende Verbindung wiederverwendet werden kann, anstatt eine neue aufzubauen. Der Mechanismus funktioniert wie folgt:
Der SMB-Protokollhandler speichert den Zustand an zwei Stellen:
smbc (Verbindungszustand) auf dem meta_hash der Verbindungreq (Anforderungszustand) auf dem meta des easy-HandlesDer Fehler: req->path wird während der Nadel-Einrichtung so gesetzt, dass er innerhalb von smbc->share zeigt. Wenn die Nadel bei der Wiederverwendung zerstört wird, wird smbc->share freigegeben, aber req->path zeigt immer noch dorthin.
In smb_parse_url_path() analysiert der Code den SMB-URL-Pfad und teilt ihn in Freigabenamen und Dateipfad auf:
// lib/smb.c, smb_parse_url_path() line 431:
smbc->share = curlx_strdup((*path == '/' || *path == '\\') ? path + 1 : path);
// ...
*slash++ = 0;
req->path = slash; // <--- points into smbc->share on the NEEDLE
Für die URL smb://server/share1/file1.txt wird Folgendes erstellt:
smbc->share = "share1\0file1.txt" (Heap-alloziert, gehört der Nadel)req->path = Zeiger auf "file1.txt" (innerhalb von smbc->share)Wenn die Verbindungswiederverwendung ausgelöst wird:
// lib/url.c, url_find_or_create_conn() line 3619:
out:
if(needle)
Curl_conn_free(data, needle); // Destroy needle -> free smbc->share
Curl_conn_free() ruft Curl_hash_destroy(&conn->meta_hash) auf, was smb_conn_dtor() aufruft und smbc->share freigibt. Aber req->path (auf dem easy-Handle, der überlebt) zeigt immer noch auf den nun freigegebenen Speicher.
Wenn die SMB-Anfrage fortgesetzt wird:
// lib/smb.c, smb_send_open() line 750-769:
const size_t byte_count = strlen(req->path) + 1; // UAF READ
// ...
curlx_strcopy(msg.bytes, sizeof(msg.bytes), req->path, byte_count - 1); // UAF READ
Der freigegebene Heap-Speicher kann neu zugewiesen worden sein und sensible Daten enthalten. strlen(req->path) sucht vorwärts, bis ein Nullbyte gefunden wird, und curlx_strcopy() kopiert diesen Inhalt in das an den Server gesendete SMB-Paket.
Angriffsszenario: SSRF, bei dem der Angreifer den SMB-Server kontrolliert. Die Opferanwendung stellt zwei SMB-Anfragen an den Server des Angreifers. Die zweite Anfrage gibt Heap-Inhalte als „Dateiname“ in der SMB-OPEN-Anfrage preis.
Wenn der freigegebene Speicher an das Betriebssystem zurückgegeben wurde (nicht zugeordnet), löst strlen() einen SIGSEGV/Zugriffsverletzung aus.
Selbst ohne den UAF ist die SMB-Verbindungswiederverwendung semantisch fehlerhaft. smb_send_tree_connect() verwendet smbc->share von der wiederverwendeten Verbindung (der alten Freigabe), nicht von der neuen Anfrage. Die TREE_CONNECT geht vollständig zur falschen Freigabe.
# Two SMB URLs to the same server, different shares/files:
curl smb://192.168.1.100/share1/file1.txt -o /dev/null \
smb://192.168.1.100/share2/file2.txt -o /dev/null
CURLM *multi = curl_multi_init();
CURL *e1 = curl_easy_init();
curl_easy_setopt(e1, CURLOPT_URL, "smb://server/share1/file1");
curl_multi_add_handle(multi, e1);
CURL *e2 = curl_easy_init();
curl_easy_setopt(e2, CURLOPT_URL, "smb://server/share2/file2");
curl_multi_add_handle(multi, e2);
// When e2 runs after e1 completes and reuses the connection: UAF
Bauen Sie curl mit -fsanitize=address und führen Sie das obige aus:
==PID==ERROR: AddressSanitizer: heap-use-after-free on address 0x...
READ of size 1 at 0x... thread T0
#0 strlen
#1 smb_send_open lib/smb.c:750
#2 smb_request_state lib/smb.c:1163
...
freed by thread T0 here:
#0 free
#1 smb_conn_dtor lib/smb.c:388
#2 Curl_hash_destroy
#3 Curl_conn_free lib/url.c:557
Siehe poc/REPRODUCE_UAF.sh für das vollständige Reproduktionsskript.
Das grundlegende Problem ist, dass req->path einen Zeiger auf Speicher leiht, der der Nadel smbc gehört. Die Korrektur sorgt dafür, dass req->path seine eigene Kopie besitzt:
--- a/lib/smb.c
+++ b/lib/smb.c
@@ -378,7 +378,7 @@ static void smb_easy_dtor(void *key, size_t klen, void *entry)
(void)key;
(void)klen;
+ curlx_free(req->path);
curlx_free(req);
}
@@ -428,7 +428,10 @@ static CURLcode smb_parse_url_path(struct Curl_easy *data,
/* Parse the path for the file path converting any forward slashes into
backslashes */
*slash++ = 0;
- req->path = slash;
+ req->path = curlx_strdup(slash);
+ if(!req->path) {
+ Curl_safefree(smbc->share);
+ return CURLE_OUT_OF_MEMORY;
+ }
Stefan Eissing hat die offizielle Korrektur in e090be9f73a7a71459ef678c implementiert.
Die Entwickler waren sich des Risikos des baumelnden Zeigers teilweise bewusst. Dieser Kommentar existiert in smb_easy_dtor():
/* `req->path` points to somewhere in `struct smb_conn` which is
* kept at the connection meta. If the connection is destroyed first,
* req->path points to free'd memory. */
Dies berücksichtigt jedoch nur das Szenario, bei dem die Verbindung vor dem easy-Handle zerstört wird. Es übersehen wurde das Szenario der Nadelzerstörung während der Verbindungswiederverwendung, das den tatsächlichen Auslöser darstellt.
!defined(CURL_DISABLE_SMB)defined(USE_CURL_NTLM_CORE)sizeof(curl_off_t) > 4 (64-Bit off_t, Standard auf den meisten Plattformen)SMB ist standardmäßig in curl-Builds aktiviert, die NTLM-Unterstützung haben.
e090be9f73a7a71459ef678c777c5209dfCVE-2026-3805 - Behoben in curl 8.19.0. Betroffen: 8.13.0 bis 8.18.0.
Daniel Wade - GitHub - [email protected]
| Datum |
|---|
| Ereignis |
|---|
| 2025-04-30 | 777c5209df überarbeitet SMB zur Verwendung von Meta-Hash, wodurch der Fehler eingeführt wird |
| 2026-03-07 | Ich finde den Fehler während eines Sicherheitsaudits |
| 2026-03-08 | An curl über HackerOne (#3591944) gemeldet |
| 2026-03-08 | curl kontaktiert distros@openwall |
| 2026-03-11 | curl 8.19.0 mit Fix veröffentlicht, CVE-2026-3805 veröffentlicht |