
CVE-2021-44228 के लिए Byte Buddy Java agent-आधारित फिक्स, जो log4j 2.x 'JNDI LDAP' कमजोरी है।
CVE-2021-44228, यानी log4j 2.x "JNDI LDAP" भेद्यता के लिए एक Byte Buddy Java agent-आधारित फिक्स।
यह तीन काम करता है:
jndi: प्रारूप स्ट्रिंग्स ("लुकअप") के लिए आंतरिक विधि हैंडलर को अक्षम करता है।System.err (यानी stderr) पर एक संदेश लॉग करता है जो दर्शाता है कि log4j JNDI प्रयास किया गया है (प्रयास किए गए प्रारूप स्ट्रिंग सहित, जिसमें किसी भी ${} अक्षर को संक्रामक इंजेक्शन को रोकने के लिए सैनिटाइज़ किया गया है)।"(log4j jndi disabled)" में हल करता है (संक्रामक इंजेक्शन को रोकने के लिए)।अपने java कमांड में -javaagent:path/to/log4j-jndi-be-gone-1.0.0-standalone.jar जोड़ें।
नोट: यदि आपके पास पहले से ही क्लासपाथ में Byte Buddy है, तो log4j-jndi-be-gone-1.0.0.jar का उपयोग करने का प्रयास करें।
$ java -javaagent:path/to/log4j-jndi-be-gone-1.0.0-standalone.jar -jar path/to/some.jar
संस्करण 1.1.0 के अनुसार, log4j-jndi-be-gone डिफ़ॉल्ट रूप से log4j के पुनर्पैकेजित (उर्फ "शेडेड") संस्करणों को संभालने का प्रयास करता है जो किसी JAR में वैकल्पिक पैकेज नाम के अंतर्गत एम्बेडेड हो सकते हैं, ताकि किसी एप्लिकेशन के डिपेंडेंसी के संस्करण और किसी डिपेंडेंसी के उसी डिपेंडेंसी के संस्करण के बीच टकराव को रोका जा सके। हालांकि, यह ध्यान दिया जाना चाहिए कि log4j को स्थैतिक क्लासनाम और/या एम्बेडेड कॉन्फ़िगरेशन फ़ाइलों से क्लासनाम के साथ रिफ्लेक्शन के उपयोग के कारण वैकल्पिक पैकेज नामों/उपसर्गों के तहत आसानी से पुनर्पैकेज नहीं किया जा सकता है।
इस व्यवहार को -javaagent: तर्क में एजेंट JAR पथ के बाद =structureMatch=0 लगाकर अक्षम किया जा सकता है, उदाहरण:
-javaagent:path/to/log4j-jndi-be-gone-1.0.0-standalone.jar=structureMatch=0
जिसके परिणामस्वरूप 1.0.0 के समान मिलान व्यवहार होगा, यानी क्लास नाम के विरुद्ध एक सरल सटीक स्ट्रिंग तुलना।
आप ./gradlew के साथ JAR बना सकते हैं (build/libs/log4j-jndi-be-gone-1.0.0(-standalone).jar) या इसे रिलीज़ पेज से प्राप्त कर सकते हैं।
log4j-jndi-be-gone एजेंट JAR Java 6-17+ को सपोर्ट करता है।
कार्यान्वयन उन क्लासेज से मिलान करके शुरू होता है जिनके सफ़िक्स org.apache.logging.log4j.core.lookup.JndiLookup, lookup.JndiLookup के सबसे आंतरिक उप-पैकेज और क्लासनाम से मेल खाते हैं, क्योंकि org.apache.logging.log4j.core से उम्मीद की जा सकती है कि इसे उन पुनर्पैकेजिंग नियमों द्वारा विकृत किया गया होगा जो पैकेज नामों को संरक्षित करने का प्रयास नहीं करते हैं। इसके अतिरिक्त, केवल सभी अन्य अपेक्षित log4j प्रकारों के लिए समान जाँच करने के बजाय, यह सुनिश्चित करता है कि वे भी समान आधार पैकेज के अंतर्गत मौजूद हों।
कार्यान्वयन तब किसी भी पहचाने गए संभावित log4j lookup.JndiLookup क्लासेज की संरचना के माध्यम से चलता है, निम्नलिखित के विरुद्ध मान्य करने का प्रयास करता है:
org.apache.logging.log4j.core.config.plugins.Plugin एनोटेशन, जिसमें एनोटेशन पैरामीटर और उनके मान शामिल हैंlookup(), इसके मॉडिफायर और प्रकार हस्ताक्षर के विरुद्ध मिलान (और 2.0 से 1-आर्गुमेंट संस्करण को अनदेखा करते हुए)convertJndiName(), इसके मॉडिफायर और प्रकार हस्ताक्षर के विरुद्ध मिलानCONTAINER_JNDI_RESOURCE_PATH_PREFIX, इसके मॉडिफायर के विरुद्ध मिलानlog4j-jndi-be-gone काम नहीं करेगा यदि log4j लाइब्रेरी को अस्पष्ट (obfuscated) किया गया है या इसके क्लास पैकेज/नामों को मूल पुनर्पैकेजिंग (यानी "शेडिंग") के अलावा संशोधित किया गया है।
log4j-jndi-be-gone-1.0.0-standalone.jar में Byte Buddy बंडल है। यदि आप पहले से Byte Buddy का उपयोग करते हैं, तो आपको इससे समस्या हो सकती है। इसके बजाय संस्करण 1.1.0 के अनुसार, log4j-jndi-be-gone स्टैंडअलोन JAR अपने स्वयं के पैकेज उपसर्ग के तहत एक पुनर्पैकेजित Byte Buddy बंडल करता है। इससे किसी भी टकराव को रोका जाना चाहिए।log4j-jndi-be-gone-1.0.0.jar का प्रयास करें, हालांकि ध्यान दें कि log4j-jndi-be-gone Byte Buddy 1.12.x की अपेक्षा करता है।
यदि आपने अपनी JndiLookup क्लासेज को उन कार्यान्वयनों से बदल दिया है जो हनीपॉटिंग या lookup() कॉल को लॉग करने का प्रयास करते हैं, तो log4j-jndi-be-gone संभावित रूप से उनकी lookup विधि को अक्षम कर देगा, जिससे वे काम करने से रुक जाएँगे।
tests/jnditest निर्देशिका में एक सरल परीक्षण मामला है जहाँ एक log4j लॉगिंग कॉल एक JNDI LDAP प्रारूप स्ट्रिंग पास करता है। यह यह निर्धारित करने के लिए अपना स्वयं का पोर्ट श्रोता भी सेट करता है कि क्या log4j द्वारा कनेक्शन प्रयास किया गया था और यदि कनेक्शन प्राप्त हुआ तो परीक्षण विफल कर देता है।
$ ./tests/jnditest/test-uninstrumented.sh
BUILD SUCCESSFUL in 1s
6 actionable tasks: 5 executed, 1 up-to-date
BUILD SUCCESSFUL in 1s
3 actionable tasks: 3 up-to-date
JUnit version 4.12
.16:08:49.547 [main] ERROR trust.nccgroup.jnditest.test.JndiTest - Hello, _${jndi:ldap://127.0.0.1:8899/evil}_!
E
Time: 0.929
There was 1 failure:
1) logging(trust.nccgroup.jnditest.test.JndiTest)
java.lang.AssertionError: jndi ldap connection received
at org.junit.Assert.fail(Assert.java:88)
at trust.nccgroup.jnditest.test.JndiTest.logging(JndiTest.java:55)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runners.Suite.runChild(Suite.java:128)
at org.junit.runners.Suite.runChild(Suite.java:27)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runners.Suite.runChild(Suite.java:128)
at org.junit.runners.Suite.runChild(Suite.java:27)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
at org.junit.runner.JUnitCore.runMain(JUnitCore.java:77)
at org.junit.runner.JUnitCore.main(JUnitCore.java:36)
at trust.nccgroup.jnditest.Main.main(Main.java:24)
FAILURES!!!
Tests run: 1, Failures: 1
$ ./tests/jnditest/test-instrumented.sh
BUILD SUCCESSFUL in 1s
6 actionable tasks: 5 executed, 1 up-to-date
BUILD SUCCESSFUL in 1s
3 actionable tasks: 3 up-to-date
JUnit version 4.12
.log4j jndi lookup attempted: (sanitized) ldap://127.0.0.1:8899/evil
16:09:06.064 [main] ERROR trust.nccgroup.jnditest.test.JndiTest - Hello, _(log4j jndi disabled)_!
Time: 1.362
OK (1 test)
Apache 2 लाइसेंस के अंतर्गत लाइसेंस प्राप्त है।
log4j-jndi-be-gone का परीक्षण OpenJDK 6, 8, 11, और 17 पर तथा HotSpot और OpenJ9 JVMs पर किया गया है।