Apache Log4j2 RCE(CVE-2021-44228)分析

前言

Log4j2是一个强大的Java日志框架,用于在应用程序中记录日志信息。它是Log4j的升级版本,旨在提供更高的性能、更丰富的功能和更灵活的配置选项。

漏洞分析

通常我们使用LogManager.getLogger()方法来获取一个Logger对象,并调用其 debug/info/error/warn/fatal/trace/log 等方法记录日志等信息。

在这些方法中,都会先使用org.apache.logging.log4j.spi.AbstractLogger#logIfEnabled的多个重载方法来根据当前的配置,来判断是否需要输出console和记录日志文件。默认的日志等级为:

ALL < DEBUG < INFO < WARN < ERROR < FATAL < OFF

在不做配置的情况下,默认会输出ERROR/FATAL等级的日志,可以通过配置文件修改,也可以通过代码修改输出等级。

<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
    <Loggers>
        <Logger name="org.su18" level="All"/>
    </Loggers>
</Configuration>
LoggerContext ctx          = (LoggerContext) LogManager.getContext(false);
Configuration config       = ctx.getConfiguration();
LoggerConfig  loggerConfig = config.getLoggerConfig(LogManager.ROOT_LOGGER_NAME);
loggerConfig.setLevel(Level.ALL);
ctx.updateLoggers();

在输出日志的过程中,会对字符串进行处理。

1685013194647.png

通过while循环逐个字符串寻找${前缀

1685013519925.png

找到前缀之后开始找后缀,找到之后则会进入第三个阶段

1685014005235.png

提取内容赋给varNameExpr变量

1685014271853.png

然后调用resolveVariable()来解析满足Lookup功能的语法,并执行相应的lookup

1685014578627.png

这里会:为分割,这里传入的jndi,所以对应的是JndiLookup类

1685014719588.png

所以这里执行JndiLookup.lookup(),最终执行JndiManager.lookup()

1685014779376.png

漏洞复现

Screen-2023-05-25-195731.gif