
इस रिपोजिटरी में CVE-2018-19987 के मेरे विश्लेषण के बारे में एक ब्लॉग पोस्ट है, जो कई D-Link राउटरों को प्रभावित करने वाला एक प्रमाणित OS कमांड इंजेक्शन है।
नमस्ते!
इस छोटी ब्लॉग पोस्ट में मैं CVE-2018-19987 के पीछे के विवरणों को बेहतर ढंग से समझने के लिए किए गए अपने एक त्वरित विश्लेषण को विस्तार से बताऊँगा। शुरुआत में मैं इस CVE के पीछे गया क्योंकि मुझे लगा कि इसके बारे में कोई सार्वजनिक जानकारी या एक्सप्लॉइट मौजूद नहीं था। पहला विश्लेषण करने के तुरंत बाद, मुझे GitHub पर दो सार्वजनिक PoC मिले जिन्हें आप यहाँ और यहाँ पा सकते हैं।
चूँकि मैंने अधिकांश काम पहले ही कर लिया था और मुझे कोई पूर्ण विश्लेषण नहीं मिला था, मैंने फिर भी ब्लॉग पोस्ट लिखने का निर्णय लिया।
आशा है आपको यह पसंद आएगा!
अद्यतन: खैर.. इस ब्लॉग पोस्ट के साथ अटका हुआ था, तभी गूगल करते समय मुझे निम्नलिखित लेख मिला जो D-Link DIR-818 में एक बहुत ही समान भेद्यता (CVE-2018-19986) का वर्णन करता है। राउटर भेद्यता विश्लेषण श्रृंखला (5): CVE-2018-19986 DIR-818LW&828 कमांड इंजेक्शन भेद्यता विश्लेषण और पुनरुत्पादन (Google अनुवादित) Ogur1 द्वारा।
मैंने अपना विश्लेषण उस डिवाइस के बारे में जितनी भी जानकारी मिल सकती थी, एकत्र करके शुरू किया:
नोट: मैंने सारा विश्लेषण फर्मवेयर v3.01B02 के साथ किया।
इस भेद्यता के लिए सार्वजनिक जानकारी, जो Mitre के पृष्ठ पर उपलब्ध है, ने शुरू करने के लिए पर्याप्त जानकारी प्रदान की:
D-Link DIR-822 Rev.B 202KRb06, DIR-822 Rev.C 3.10B06, DIR-860L Rev.B 2.03.B03, DIR-868L Rev.B 2.05B02, DIR-880L Rev.A 1.20B01_01_i3se_BETA, and DIR-890L Rev.A 1.21B02_BETA devices mishandle IsAccessPoint in /HNAP1/SetAccessPointMode. In the SetAccessPointMode.php source code, the IsAccessPoint parameter is saved in the ShellPath script file without any regex checking. After the script file is executed, the command injection occurs. A vulnerable /HNAP1/SetAccessPointMode XML message could have shell metacharacters in the IsAccessPoint element such as the `telnetd` string.
विश्लेषण शुरू करने के लिए मुझे कुछ ऐसा चाहिए था जिसे देखा जा सके, इसलिए मैंने राउटर के FS को निकालने की प्रक्रिया शुरू की।
binwalk -eM DIR822C1_FW301WWb02.bin
DECIMAL HEXADECIMAL DESCRIPTION
--------------------------------------------------------------------------------
0 0x0 DLOB firmware header, boot partition: "dev=/dev/mtdblock/1"
10380 0x288C LZMA compressed data, properties: 0x5D, dictionary size: 8388608 bytes, uncompressed size: 4213444 bytes
1376372 0x150074 PackImg section delimiter tag, little endian size: 10505216 bytes; big endian size: 5021696 bytes
1376404 0x150094 Squashfs filesystem, little endian, version 4.0, compression:lzma, size: 5019773 bytes, 2282 inodes, blocksize: 131072 bytes, created: 2016-03-18 09:35:31
जैसा कि हम देख सकते हैं, Binwalk एक Linux फ़ाइल सिस्टम का पता लगाता है। यदि हम अपने पास मौजूद जानकारी पर गहराई से नज़र डालें, तो हम देख सकते हैं कि एडवाइज़री /HNAP1 पथ का उल्लेख करती है। इसलिए, हम देखना शुरू कर सकते हैं कि राउटर इन URL को कैसे संभालता है।
जैसा कि उत्कृष्ट /dev/tty0 ब्लॉग पोस्ट में समझाया गया है, अंततः इन URL को cgibin नामक एक बाइनरी द्वारा संभाला जाता है, जो htdocs/cgibin पर स्थित है। लेकिन मैं यह बेहतर ढंग से समझना चाहता था कि यह कैसे कॉन्फ़िगर किया गया था और अंततः इसने मुझे यह समझने के लिए प्रेरित किया कि HTTP सर्वर को अनुरोधों को संसाधित करने के लिए कैसे कॉन्फ़िगर किया गया था। मैंने httpd.conf फ़ाइल नाम की खोज की, यह मानते हुए कि इसका उपयोग HTTP सर्वर को कॉन्फ़िगर करने के लिए किया गया था, और /etc/services/ फ़ोल्डर के अंतर्गत HTTP.php नामक एक फ़ाइल मिली, जिसमें अन्य चीज़ों के अलावा निम्नलिखित रोचक पंक्तियाँ शामिल थीं:
$httpd_conf = "/var/run/httpd.conf";
fwrite("a",$START, "xmldbc -P /etc/services/HTTP/httpcfg.php > ".$httpd_conf."\n");
fwrite("a",$START, "event PREFWUPDATE add /etc/scripts/prefwupdate.sh\n");
fwrite("a",$START, "httpd -f ".$httpd_conf."\n");
fwrite("a",$START, "event HTTP.UP\n");
fwrite("a",$START, "exit 0\n");
मैंने मान लिया कि किसी बिंदु पर यह फ़ाइल निष्पादित होती है और /var/run/httpd.conf फ़ाइल लिखती है। यह जानने के लिए कि वेब सर्वर कैसे कॉन्फ़िगर किया गया था, मैंने /etc/services/HTTP/httpcfg.php फ़ाइल का विश्लेषण करना शुरू किया (मैंने केवल प्रासंगिक भागों को शामिल किया):
if ($hnap > 0)
{
echo
" Control". "\n".
" {". "\n".
" Alias /HNAP1". "\n".
" Location /htdocs/HNAP1". "\n".
" External". "\n".
" {". "\n".
" /usr/sbin/hnap { hnap }". "\n".
" }". "\n".
" IndexNames { index.hnap }". "\n".
" }". "\n";
}
अब हमारे पास सभी टुकड़े हैं! हम मान सकते हैं कि वेब सर्वर /usr/sbin/hnap का उपयोग करके /HNAP1 के HTTP अनुरोधों को संभालने के लिए कॉन्फ़िगर किया गया है, और /dev/tty0 ब्लॉगपोस्ट के आधार पर हम जानते हैं कि यह htdocs/cgibin बाइनरी का एक लिंक होगा।
अगला कदम cgibin बाइनरी पर नज़र डालना था ताकि यह समझा जा सके कि यह HNAP अनुरोधों को कैसे संभालता है। निम्नलिखित छवि में हम डिकंपाइल किए गए main फ़ंक्शन का कुछ भाग देख सकते हैं, जहाँ इसे पारित किया गया URL पथ विभिन्न पथों (जैसे session.cgi, authentication.cgi, captcha.cgi, कुछ नाम बताने के लिए) के साथ तुलना किया जाता है, जब तक कि hnap नहीं मिल जाता और हमारा फ़ंक्शन hnap_main कॉल नहीं हो जाता।
नोट: main फ़ंक्शन का विश्लेषण करते समय, मुझे hnap स्ट्रिंग की पहचान करने में कुछ समस्याएँ आईं, क्योंकि Ghidra ने प्रारंभिक विश्लेषण के दौरान इसे स्ट्रिंग के रूप में नहीं पहचाना।
अगला कदम यह समझना था कि यह फ़ंक्शन क्या करता था। मैं केवल प्रासंगिक भागों के लिए कोड स्निपेट प्रदान करूँगा जो यह बेहतर ढंग से समझने में मदद करेंगे कि फ़ंक्शन क्या करता है, साथ ही मैं अन्य प्रासंगिक भागों को कुछ स्यूडोकोड के साथ पूरा करूँगा —मैंने इसके उद्देश्य को स्पष्ट करने के लिए कुछ वेरिएबल्स का नाम बदल दिया है।
...
HTTP_SOAPACTION = getenv("HTTP_SOAPACTION");
REQUEST_METHOD = getenv("REQUEST_METHOD");
HNAP_AUTH = getenv("HTTP_HNAP_AUTH");
__haystack = getenv("HTTP_COOKIE");
pcVar1 = getenv("HTTP_REFERER");