
CVE-2026-3805: Use-After-Free in curl SMB कनेक्शन पुन: उपयोग - heap info disclosure
मुझे libcurl के SMB प्रोटोकॉल हैंडलर में एक use-after-free भेद्यता मिली। जब
एक दूसरा SMB स्थानांतरण उसी सर्वर के लिए मौजूदा कनेक्शन का पुन: उपयोग करता है, तो
नए अनुरोध के लिए फ़ाइल पथ (req->path) मुक्त हीप मेमोरी के लिए एक लटकता हुआ पॉइंटर है।
यह मेमोरी strlen() के माध्यम से पढ़ी जाती है और एक बाहर जाने वाले SMB
पैकेट में कॉपी की जाती है, जिससे हीप सामग्री सर्वर पर लीक हो जाती है या क्रैश हो जाती है।
एक-पंक्ति समाधान: req->path सुई के smbc->share से उधार लेने के बजाय अपनी स्वयं की प्रतिलिपि का मालिक बनता है।
| CVE | CVE-2026-3805 |
| बग वर्ग | Use-After-Free (CWE-416) |
| मूल कारण | req->path सुई के smbc->share में इंगित करता है, कनेक्शन पुन: उपयोग पर मुक्त हो जाता है |
| शुरू किया गया | 777c5209df (2025-04-30) - curl 8.13.0 |
| ठीक किया गया | e090be9f73a7a71459ef678c - curl 8.19.0 (Mar 11, 2026) |
| प्रभावित | curl 8.13.0 से 8.18.0 |
| प्रभाव | सर्वर को हीप जानकारी का खुलासा, क्रैश |
| गंभीरता | 7.5 - HIGH - CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H |
smb_setup_connection() कैश लुकअप के लिए उपयोग किए जाने वाले अस्थायी "सुई" कनेक्शन पर चलता है।
यह req->path को smbc->share (सुई के स्वामित्व वाली हीप मेमोरी) के अंदर इंगित करने के लिए सेट करता है। जब कनेक्शन कैश को एक पुन: उपयोग योग्य कनेक्शन मिलता है, तो सुई नष्ट हो जाती है - smbc->share मुक्त हो जाता है - लेकिन req->path आसान हैंडल पर बना रहता है, अब लटकता हुआ।
जब smb_send_open() SMB OPEN अनुरोध बनाता है, तो यह strlen(req->path) कहता है
और परिणाम को बाहर जाने वाले पैकेट में कॉपी करता है। उस मुक्त हीप क्षेत्र में जो भी डेटा है वह सर्वर पर जाता है। यदि हमलावर सर्वर को नियंत्रित करता है (SSRF, या उपयोगकर्ता दुर्भावनापूर्ण SMB से कनेक्ट कर रहा है), तो उन्हें SMB NT_CREATE_ANDX अनुरोध में "फ़ाइलनाम" के रूप में लीक हुई हीप सामग्री प्राप्त होती है।
libcurl प्रदर्शन के लिए आक्रामक रूप से कनेक्शन का पुन: उपयोग करता है। जब आप एक ही होस्ट के लिए कई अनुरोध करते हैं, तो curl जाँचता है कि क्या मौजूदा कनेक्शन का पुन: उपयोग किया जा सकता है, नया स्थापित करने के बजाय। तंत्र इस प्रकार काम करता है:
SMB प्रोटोकॉल हैंडलर दो स्थानों पर स्थिति संग्रहीत करता है:
smbc (कनेक्शन स्थिति) कनेक्शन के meta_hash परreq (अनुरोध स्थिति) आसान हैंडल के meta परबग: req->path सुई सेटअप के दौरान smbc->share के अंदर इंगित करने के लिए सेट किया जाता है। जब पुन: उपयोग पर सुई नष्ट हो जाती है, तो smbc->share मुक्त हो जाता है, लेकिन req->path अभी भी वहाँ इंगित करता है।
smb_parse_url_path() में, कोड SMB URL पथ को पार्स करता है और इसे शेयर नाम और फ़ाइल पथ में विभाजित करता है:
// lib/smb.c, smb_parse_url_path() line 431:
smbc->share = curlx_strdup((*path == '/' || *path == '\\') ? path + 1 : path);
// ...
*slash++ = 0;
req->path = slash; // <--- सुई पर smbc->share में इंगित करता है
smb://server/share1/file1.txt URL के लिए, यह बनाता है:
smbc->share = "share1\0file1.txt" (हीप आवंटित, सुई के स्वामित्व में)req->path = "file1.txt" की ओर पॉइंटर (smbc->share के अंदर)जब कनेक्शन पुन: उपयोग ट्रिगर होता है:
// lib/url.c, url_find_or_create_conn() line 3619:
out:
if(needle)
Curl_conn_free(data, needle); // सुई नष्ट करता है -> smbc->share मुक्त करता है
Curl_conn_free() Curl_hash_destroy(&conn->meta_hash) कॉल करता है जो smb_conn_dtor() को आमंत्रित करता है, smbc->share मुक्त करता है। लेकिन req->path (आसान हैंडल पर, जो बच जाता है) अभी भी अब मुक्त मेमोरी में इंगित करता है।
जब SMB अनुरोध आगे बढ़ता है:
// lib/smb.c, smb_send_open() line 750-769:
const size_t byte_count = strlen(req->path) + 1; // UAF पढ़ना
// ...
curlx_strcopy(msg.bytes, sizeof(msg.bytes), req->path, byte_count - 1); // UAF पढ़ना
मुक्त हीप मेमोरी को पुन: आवंटित किया जा सकता है और इसमें संवेदनशील डेटा हो सकता है।
strlen(req->path) तब तक आगे स्कैन करता है जब तक यह एक नल बाइट से नहीं टकराता, और
curlx_strcopy() उस सामग्री को सर्वर को भेजे गए SMB पैकेट में कॉपी करता है।
हमला परिदृश्य: SSRF जहाँ हमलावर SMB सर्वर को नियंत्रित करता है। पीड़ित एप्लिकेशन हमलावर के सर्वर पर दो SMB अनुरोध करता है। दूसरा अनुरोध SMB OPEN अनुरोध में "फ़ाइलनाम" के रूप में हीप सामग्री को लीक करता है।
यदि मुक्त मेमोरी OS (अनमैप) को वापस कर दी गई है, तो strlen() SIGSEGV/एक्सेस उल्लंघन को ट्रिगर करता है।
UAF के बिना भी, SMB कनेक्शन पुन: उपयोग शब्दार्थ रूप से टूट गया है।
smb_send_tree_connect() पुन: उपयोग किए गए कनेक्शन (पुराने शेयर) से smbc->share का उपयोग करता है, नए अनुरोध के शेयर का नहीं। TREE_CONNECT पूरी तरह से गलत शेयर पर जाता है।
# एक ही सर्वर, अलग-अलग शेयर/फ़ाइलों के लिए दो SMB URLs:
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);
// जब e2, e1 के पूरा होने के बाद चलता है और कनेक्शन का पुन: उपयोग करता है: UAF
curl को -fsanitize=address के साथ बनाएँ और उपरोक्त चलाएँ:
==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
पूर्ण प्रजनन स्क्रिप्ट के लिए poc/REPRODUCE_UAF.sh देखें।
मूलभूत मुद्दा यह है कि req->path सुई के smbc के स्वामित्व वाली मेमोरी में एक पॉइंटर उधार लेता है। समाधान req->path को अपनी स्वयं की प्रतिलिपि का मालिक बनाता है:
--- 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,
/* पथ को फ़ाइल पथ के लिए पार्स करें और किसी भी फॉरवर्ड स्लैश को बैकस्लैश में बदलें */
*slash++ = 0;
- req->path = slash;
+ req->path = curlx_strdup(slash);
+ if(!req->path) {
+ Curl_safefree(smbc->share);
+ return CURLE_OUT_OF_MEMORY;
+ }
Stefan Eissing ने e090be9f73a7a71459ef678c में आधिकारिक समाधान लागू किया।
डेवलपर आंशिक रूप से लटकते पॉइंटर जोखिम से अवगत थे। यह टिप्पणी
smb_easy_dtor() में मौजूद है:
/* `req->path` `struct smb_conn` में कहीं इंगित करता है जो
* कनेक्शन मेटा पर रखा जाता है। यदि कनेक्शन पहले नष्ट हो जाता है,
* तो req->path मुक्त मेमोरी की ओर इंगित करता है। */
लेकिन यह केवल उस परिदृश्य पर विचार करता है जहाँ कनेक्शन आसान हैंडल से पहले नष्ट हो जाता है। यह कनेक्शन पुन: उपयोग के दौरान सुई विनाश परिदृश्य से चूक गया, जो वास्तविक ट्रिगर है।
!defined(CURL_DISABLE_SMB)defined(USE_CURL_NTLM_CORE)sizeof(curl_off_t) > 4 (64-bit off_t, अधिकांश प्लेटफार्मों पर मानक)SMB डिफ़ॉल्ट रूप से उन curl बिल्ड में सक्षम है जिनमें NTLM समर्थन है।
e090be9f73a7a71459ef678c777c5209dfCVE-2026-3805 - curl 8.19.0 में ठीक किया गया। प्रभावित: 8.13.0 से 8.18.0।
Daniel Wade - GitHub - [email protected]
| तिथि |
|---|
| घटना |
|---|
| 2025-04-30 | 777c5209df SMB को मेटा हैश का उपयोग करने के लिए पुन: स्वरूपित करता है, बग पेश करता है |
| 2026-03-07 | मुझे सुरक्षा ऑडिट के दौरान बग मिला |
| 2026-03-08 | HackerOne (#3591944) के माध्यम से curl को रिपोर्ट किया गया |
| 2026-03-08 | curl distros@openwall से संपर्क करता है |
| 2026-03-11 | curl 8.19.0 समाधान के साथ जारी किया गया, CVE-2026-3805 प्रकाशित |