
SolarWinds Serv-U CVE-2026-28318: अप्रमाणित Content-Encoding: deflate क्रैश। रूट-कॉज़ विश्लेषण (इंटीरियर पॉइंटर का अमान्य फ्री -> हीप करप्शन) + केवल DoS PoC। 15.5.4 हॉटफिक्स 1 में फिक्स किया गया।
मूल कारण विश्लेषण + DoS प्रूफ-ऑफ-कॉन्सेप्ट। सार्वजनिक सलाहकार इसे एक अप्रमाणित सेवा-निषेध / अनियंत्रित संसाधन खपत के रूप में वर्गीकृत करता है। बाइनरी विश्लेषण से पता चलता है कि अंतर्निहित दोष मेमोरी-सुरक्षा है: HTTP
deflateडिकोड पथ में एक आंतरिक पॉइंटर का अमान्यfree(), जो प्रक्रिया ढेर को दूषित करता है (STATUS_HEAP_CORRUPTION,0xC0000374). यह नहीं है एक डीकंप्रेसन बम, और क्रैश डीकंप्रेस्ड आकार से स्वतंत्र है।
केवल HTTP/HTTPS लिसनर (वेब/प्रबंधन पथ) को प्रभावित करता है। FTP/FTPS/SFTP इस कोड पथ पर नहीं हैं।
Content-Encoding: deflate वाला कोई भी HTTP अनुरोध जिसमें एक वैध deflate बॉडी है, सेवा को क्रैश कर देता है। हैंडलर बॉडी को डीकंप्रेस करता है, फिर संकुचित (compressed) बॉडी के पॉइंटर को मुक्त करता है और डीकंप्रेस्ड बफर को स्वैप करता है — लेकिन वह पॉइंटर एक HTTP प्राप्त बफर में आंतरिक पॉइंटर है (यह \r\n\r\n के तुरंत बाद बॉडी की ओर इंगित करता है), ढेर आवंटन आधार नहीं। गैर-आधार, असंरेखित पॉइंटर पर free() कॉल करने से ढेर दूषित हो जाता है और प्रक्रिया मर जाती है।
चूंकि बग बॉडी पॉइंटर को कैसे मुक्त किया जाता है में है — न कि कितना डेटा उत्पन्न होता है — लगभग 25-बाइट का एक संकुचित बॉडी (जो कुछ KB तक डीकंप्रेस होता है) विश्वसनीय रूप से इसे क्रैश करता है। मेमोरी उपयोग नहीं बढ़ता; यह 'zip/deflate बम' नहीं है।
डिफ्लेट-डीकोड रूटीन RhinoNET.dll (Serv-U का नेटवर्क लाइब्रेरी) में रहता है और HTTP प्राप्त पथ (ProcessReceive) से पहुँचा जाता है जब हेडर पार्सर Content-Encoding: deflate देखकर 'deflate' फ्लैग सेट करता है।
सरलीकृत, रूटीन को decode(this, &bodyPtr, &bodyLen) के रूप में कॉल किया जाता है और यह निम्नलिखित करता है:
1. inflate bodyPtr[0..bodyLen] -> grows an accumulator buffer `acc` (stock zlib, bounded, correct)
2. free(*bodyPtr) <-- *bodyPtr is an INTERIOR pointer into the receive buffer
3. *bodyPtr = acc // replace compressed body with decompressed buffer
4. *bodyLen = total
चरण 2 बग है। *bodyPtr एक स्वतंत्र रूप से आवंटित ब्लॉक नहीं है: यह अनुरोध बॉडी की ओर एकल HTTP प्राप्त बफर के अंदर, यानी receive_buffer + header_length को इंगित करता है। एक आंतरिक (और 16-बाइट-असंरेखित) पॉइंटर को मुक्त करने से आवंटक एक हमलावर-प्रभावित क्षेत्र को ढेर चंक हेडर के रूप में पार्स करता है → ढेर मेटाडेटा भ्रष्टाचार → 0xC0000374।
zlib1.dll!inflate है और प्रत्येक कॉल पर avail_out का सम्मान करता है (100+ चंकों में देखा गया; शून्य सीमा-बाह्य लेखन)।prev_total + produced + 1 के रूप में आवंटित किया जाता है और ठीक उतना ही लिखा जाता है — सख्त, कोई ओवरफ्लो नहीं।भ्रष्टाचार पूरी तरह से चरण 2 में अमान्य free() है।
रनटाइम (Frida) पर Serv-U 15.5.4.108 के विरुद्ध एक Content-Encoding: deflate अनुरोध भेजते समय कैप्चर किया गया जिसका बॉडी "A" * 8192 तक डीकंप्रेस होता है:
…ce — mod 16 == 14 है। ढेर आवंटन आधार 16-बाइट संरेखित होते हैं, इसलिए यह आवंटन आधार नहीं है; यह एक आंतरिक पॉइंटर है।\r\n\r\n पर समाप्त होते हैं:
…tream\r\nContent-Length: 26\r\nConnection: close\r\n\r\n
ed c1 01 0d 00 …)।ntdll.dll, अपवाद 0xC0000374 (STATUS_HEAP_CORRUPTION), जिसमें कॉल RhinoNET.dll डिफ्लेट हैंडलर में free से उत्पन्न होता है। क्रैश से पहले का अंतिम ढेर संचालन बिल्कुल यह free(bodyPtr) है।0xC0000374) हमारे परीक्षण में, और हमने कोड निष्पादन प्राप्त नहीं किया। इसे प्री-प्रमाणीकरण ढेर-भ्रष्टाचार DoS जिसका मूल कारण मेमोरी-सुरक्षा है के रूप में मानें; RCE न मानें।Python 3 (केवल मानक लाइब्रेरी) की आवश्यकता है। इसे एक Serv-U HTTP लिसनर पर इंगित करें जिसके परीक्षण के लिए आप अधिकृत हैं। Windows पर यह लिसनर PID पढ़ने के लिए एक Get-NetTCPConnection कॉल और ढेर-भ्रष्टाचार क्रैश की पुष्टि करने के लिए एप्लिकेशन इवेंट लॉग का उपयोग करता है।
python poc_verify.py # default 127.0.0.1:80, tiny packet, 1 shot
python poc_verify.py --host <ip> --port 80
python poc_verify.py --big # body decompresses to 8192 bytes
python poc_verify.py --shots 3
python poc_verify.py --no-events # skip event-log check (no privileges needed)
PoC एक न्यूनतम अनुरोध बनाता है:
POST / HTTP/1.1
Host: <target>
Content-Encoding: deflate
Content-Type: application/octet-stream
Content-Length: <n>
Connection: close
<raw-deflate body — even a few dozen bytes is enough>
यह PASS रिपोर्ट करता है यदि सेवा क्रैश हुई (लिसनर PID बदल गया / 0xC0000374 घटना दिखाई दी) और FAIL यदि यह बच गई (पहले से पैच, प्रभावित नहीं, या बॉडी को डिफ्लेट के रूप में संसाधित नहीं किया गया)।
Content-Encoding को हटाएँ या अस्वीकार करें, उदा. रिवर्स प्रॉक्सी पर:
if ($http_content_encoding) { return 400; }
free का पता लगाने के लिए RhinoNET.dll / Serv-U.exe (इमेज बेस 0x180000000) का पैरामीटराइज्ड PE डिसअसेंबली।zlib avail_out का सम्मान करता है, डीकंप्रेसर को हुक करना, डीकोड कॉल के हर alloc/free/memcpy को डिस्क पर ट्रेस करना, और भ्रष्टाचार के क्षण में दोषपूर्ण निर्देश और 0xC0000374 स्टैक को कैप्चर करने के लिए एक प्रक्रिया अपवाद हैंडलर। फिर मुक्त पॉइंटर के आसपास के बाइट्स (HTTP हेडर टेल + कच्चा-डिफ्लेट बॉडी, 16-बाइट-असंरेखित) को डंप करके आंतरिक-पॉइंटर मुक्ति की पुष्टि की गई।विश्लेषण में संदर्भित ऑफसेट बिल्ड 15.5.4.108 के लिए विशिष्ट हैं और बिल्डों में भिन्न होंगे।
विक्रेता पैच उपलब्धता के बाद रक्षात्मक अनुसंधान के रूप में प्रकाशित। PoC केवल DoS है और अधिकृत परीक्षण के लिए अभिप्रेत है।
| उत्पाद | SolarWinds Serv-U (FTP / MFT / फ़ाइल सर्वर) |
| संवेदनशील संस्करण | 15.5.4 और उस शाखा में पहले के संस्करण Hotfix 1 के बिना (विश्लेषण बिल्ड 15.5.4.108 पर किया गया) |
| निवारण | Serv-U 15.5.4 Hotfix 1 (2026-06-04 को जारी) |
| वेक्टर | प्रमाणीकरण रहित, नेटवर्क (HTTP/HTTPS प्रबंधन/वेब पोर्ट) |
| सार्वजनिक वर्ग | CWE-400 अनियंत्रित संसाधन खपत · DoS · CVSS 7.5 · CISA KEV |
| वास्तविक वर्ग | CWE-763 अमान्य पॉइंटर का विमोचन / CWE-590 ढेर पर न होने वाली मेमोरी का मुक्तीकरण → ढेर भ्रष्टाचार |