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();
在输出日志的过程中,会对字符串进行处理。
通过while循环逐个字符串寻找${
前缀
找到前缀之后开始找后缀,找到之后则会进入第三个阶段
提取内容赋给varNameExpr变量
然后调用resolveVariable()来解析满足Lookup功能的语法,并执行相应的lookup
这里会:
为分割,这里传入的jndi
,所以对应的是JndiLookup类
所以这里执行JndiLookup.lookup(),最终执行JndiManager.lookup()