
CVE-2017-18349 Fastjson deserialization RCE exploitation का चरण-दर-चरण विवरण, जिसमें attack surface पहचान, fingerprinting, JNDI injection, और Docker प्रयोगशाला वातावरण में reverse shell प्राप्त करना शामिल है।
चलिए पर्यावरण में क्या चल रहा है, इससे शुरू करते हैं। मैं सभी सक्रिय कंटेनरों को सूचीबद्ध करता हूँ:
docker ps

पीड़ित केवल एक पोर्ट प्रकट करता है: 8090
वर्तमान में, मैं लक्ष्य के बारे में अभी तक पूरी तरह से स्पष्ट नहीं हूँ। docker ps परिणामों से, सिस्टम केवल एक उल्लेखनीय सेवा को बाहरी रूप से पोर्ट 8090 पर प्रकाशित करता है, जो कंटेनर की आंतरिक सेवा से मैप किया गया है। यह विश्लेषण किए जाने वाला मुख्य हमले की सतह है।
⇒ मैं अधिक जानकारी के लिए सीधे इसे Curl करता हूँ
curl -i 192.168.3.137:8090/

प्रतिक्रिया विश्लेषण:
Content-Type: application/json;charset=UTF-8 है।{"age": 25, "name": "Bob"}.⇒ विचार: जब पोर्ट 8090 तक पहुँचते हैं, तो सर्वर JSON डेटा लौटाता है। यह इंगित करता है कि एंडपॉइंट केवल एक स्थिर वेब पेज नहीं परोसता, बल्कि इसमें एक बैकएंड है जो अनुरोधों को संसाधित करता है और डेटा को JSON में सीरियलाइज़ करके क्लाइंट को लौटाता है। docker ps परिणामों से, कंटेनर के अंदर चल रहा कमांड एक Java एप्लिकेशन होने के संकेत दिखाता है, इसलिए अगली जांच की दिशा Java में सामान्य JSON पार्सर्स की फिंगरप्रिंटिंग करना है।
Java में, लोकप्रिय JSON लाइब्रेरीज़ जैसे Jackson, Gson, और Fastjson असामान्य इनपुट का सामना करने पर अलग-अलग व्यवहार करती हैं। इसलिए, हम Error-based Fingerprinting तकनीक का उपयोग कर सकते हैं। लौटाई गई त्रुटि कभी-कभी सीधे लाइब्रेरी या आंतरिक प्रसंस्करण तंत्र को प्रकट करती है। इनमें से, Fastjson एक लक्ष्य है जिसे जल्दी सत्यापित करने की आवश्यकता है क्योंकि पुराने संस्करणों में AutoType Deserialization से संबंधित कई गंभीर कमजोरियाँ थीं।
यहाँ, मैं तुरंत यह नहीं मानता कि बैकएंड Fastjson का उपयोग करता है। मैं केवल Fastjson को पहली जाँच की दिशा के रूप में चुनता हूँ क्योंकि इसमें @type कुंजी के माध्यम से स्पष्ट फिंगरप्रिंट है, और यदि यह वास्तव में Fastjson का पुराना संस्करण है, तो शोषण क्षमता मानक पार्सिंग त्रुटि से कहीं आगे जा सकती है, संभावित रूप से RCE तक ले जा सकती है।
Fastjson में फिंगरप्रिंटिंग के लिए एक बहुत ही उपयोगी विशेषता है: यह विशेष @type कुंजी को पहचानता है। यदि बैकएंड Fastjson का उपयोग करता है और डिसीरियलाइज़ फ्लो में भेजा गया अनुरोध बॉडी AutoType का समर्थन करता है, तो पार्सर @type मान को Java क्लास नाम के रूप में व्याख्या करने का प्रयास कर सकता है।
इसलिए, मैं एक पेलोड भेजता हूँ जिसमें @type एक गैर-मौजूद क्लास की ओर इशारा करता है। इस चरण का उद्देश्य तुरंत शोषण करना नहीं है, बल्कि यह देखना है कि क्या बैकएंड @type पर प्रतिक्रिया करता है।
curl -i -X POST -H "Content-Type: application/json" \
-d '{"@type":"com.non.existent.Class"}' \
http://192.168.3.137:8090/

यदि बैकएंड एक मानक JSON पार्सर का उपयोग करता और @type की परवाह नहीं करता, तो इस फ़ील्ड को अनदेखा किया जा सकता था या JSON में एक सामान्य कुंजी के रूप में माना जा सकता था। हालाँकि, यहाँ बैकएंड टाइप-संबंधित व्यवहार (type not match) के साथ प्रतिक्रिया करता है, जिसका अर्थ है कि अनुरोध क्लास/टाइप मैपिंग प्रसंस्करण प्रवाह में प्रवेश कर गया।
"type not match" संदेश एक विशिष्ट हस्ताक्षर है जो अक्सर तब सामने आता है जब Fastjson @type को संसाधित करता है लेकिन निर्दिष्ट क्लास एंडपॉइंट द्वारा अपेक्षित डेटा प्रकार से मेल नहीं खाती, या क्लास मौजूद नहीं है/डिसीरियलाइज़ करने की अनुमति नहीं है।
⇒ विचार: बैकएंड वास्तव में POST अनुरोध के JSON बॉडी को पार्स करता है, @type फ़ील्ड को अनदेखा नहीं किया जाता है, पार्सर में एक टाइप मेटाडेटा प्रसंस्करण तंत्र है, और लौटाई गई त्रुटि Alibaba Fastjson के व्यवहार से मेल खाती है। इसलिए, हम उच्च विश्वास के साथ निष्कर्ष निकाल सकते हैं कि बैकएंड Alibaba Fastjson का उपयोग करता है।
फिंगरप्रिंटिंग चरण के बाद, मैं तुरंत यह निष्कर्ष नहीं निकाल सकता कि सिस्टम शोषण योग्य है। बैकएंड द्वारा Fastjson का उपयोग केवल यह साबित करता है कि JSON अनुरोध @type प्रसंस्करण प्रवाह में प्रवेश करता है।
RCE शोषण को निष्पादित करने के लिए, निम्नलिखित सत्यापित किया जाना चाहिए:
⇒ विचार: type not match त्रुटि दर्शाती है कि बैकएंड @type पर प्रतिक्रिया करता है, लेकिन वर्तमान पेलोड केवल त्रुटि उत्पन्न करने के लिए एक नकली क्लास का उपयोग करता है। वास्तविक शोषण के लिए, हमें उस नकली क्लास को Java/JDK में मौजूद एक वास्तविक क्लास से बदलने की आवश्यकता है जो JNDI lookup जैसे आउटबाउंड व्यवहार बनाने में सक्षम हो।
संस्करण निर्धारित करने के लिए, मैं सीधे कंटेनर/एप्लिकेशन के अंदर जाँच करता हूँ।

यह पहचानने के बाद कि एप्लिकेशन फ़ाइल /usr/src/fastjsondemo.jar के रूप में पैकेज किया गया है, मैं JSON प्रसंस्करण लाइब्रेरी की खोज के लिए इस पैकेज संरचना का गहन विश्लेषण करता हूँ। BOOT-INF/lib/ निर्देशिका संरचना की जाँच करने पर फ़ाइल fastjson-1.2.24.jar का पता चलता है (चित्र X)।
बिल्कुल संस्करण 1.2.24 का उपयोग — जो बिना किसी autoType रक्षा तंत्र के डिसीरियलाइज़ेशन कमजोरी से प्रभावित पहला और सबसे प्रसिद्ध संस्करण है — हमें यह पुष्टि करने की अनुमति देता है कि सिस्टम CVE-2017-18349 के लिए कमजोर है।
fastjson-1.2.24.jar का पता लगना पुष्टि करता है कि एप्लिकेशन Fastjson का एक बहुत पुराना संस्करण उपयोग करता है, जो AutoType Deserialization दोष से प्रभावित समूह से संबंधित है। इस संस्करण में, AutoType पर नियंत्रण तंत्र बाद के संस्करणों की तरह कड़ा नहीं किया गया था, इसलिए लाइब्रेरी की स्थितियों के संदर्भ में, सिस्टम JdbcRowSetImpl जैसी गैजेट क्लास के माध्यम से शोषण के लिए संवेदनशील है।
हालाँकि, वास्तविक शोषण क्षमता अभी भी इस बात पर निर्भर करती है कि एंडपॉइंट Fastjson को कैसे आमंत्रित करता है। यदि एप्लिकेशन JSON को एक निश्चित क्लास में पार्स करता है, तो रूट ऑब्जेक्ट पर @type पेलोड सेट करने से "type not match" त्रुटि हो सकती है। इसलिए, संस्करण की पहचान करने के बाद, हमें यह पुष्टि करने के लिए JVM, गैजेट क्लास, और LDAP कॉलबैक व्यवहार का विश्लेषण जारी रखना होगा कि क्या शोषण श्रृंखला वास्तव में JNDI lookup तक पहुँचती है।
1. JVM बाधाओं का विश्लेषण
Fastjson संस्करण के अलावा, Java संस्करण भी एक निर्णायक कारक है। मैं कंटेनर के अंदर JVM की जाँच करता हूँ:
java -version

यह महत्वपूर्ण जानकारी है क्योंकि Fastjson शोषण श्रृंखलाएँ आमतौर पर JNDI Injection पर निर्भर करती हैं। नए Java संस्करणों ने डिफ़ॉल्ट रूप से LDAP/RMI के माध्यम से बाहरी कोडबेस से क्लास लोड करने को अवरुद्ध कर दिया है। हालाँकि, Java 8u102 एक पुराना संस्करण है जिसमें अभी तक ये अवरोधन तंत्र नहीं हैं।
इसलिए, यदि हमलावर JNDI lookup को ट्रिगर कर सकता है, तो पीड़ित के JVM में बाहरी HTTP सर्वर से क्लास डाउनलोड करने और उसे रनटाइम में लोड करने की क्षमता है।
पुराने Fastjson और JVM की पहचान करने के बाद, अगला कदम JDK में मौजूद एक ऐसी क्लास ढूंढना है जो डिसीरियलाइज़ होने पर खतरनाक व्यवहार उत्पन्न कर सके।
com.sun.rowset.JdbcRowSetImpl एक उपयुक्त गैजेट है क्योंकि यह क्लास JDK में मौजूद है और इसमें dataSourceName प्रॉपर्टी है। जब dataSourceName को LDAP URL प्रारूप मान निर्दिष्ट किया जाता है, तो ऑब्जेक्ट का शोषण करके आउटबाउंड JNDI lookup को ट्रिगर किया जा सकता है।