Log4j反序列化分析(CVE-2019-17571&CVE-2017-5645)
字数 1714 2025-08-26 22:11:45
Log4j反序列化漏洞深度分析(CVE-2019-17571 & CVE-2017-5645)
1. 漏洞概述
本文档将详细分析Log4j的两个反序列化漏洞:CVE-2019-17571(影响Log4j 1.2.x)和CVE-2017-5645(影响Log4j 2.x)。这两个漏洞的本质都是由于对从socket流中获取的数据没有进行过滤而直接进行反序列化操作,导致在特定条件下可实现远程代码执行。
2. CVE-2019-17571 (Log4j 1.2.x反序列化漏洞)
2.1 影响版本
- Log4j 1.2.x <= 1.2.17
2.2 漏洞环境搭建
- Log4j 1.2.17
- Debian系统
- JDK 1.7
- 下载地址: Apache Log4j 1.2.17
2.3 漏洞分析
2.3.1 漏洞原理
漏洞存在于SimpleSocketServer类中,该服务从socket流中获取数据后直接进行反序列化操作,没有对数据进行任何过滤或验证。如果环境中存在可利用的反序列化Gadget链(如commons-collections),攻击者可以构造恶意数据实现远程代码执行。
2.3.2 漏洞复现代码
// src/SocketDeserializeDemo.java
import org.apache.log4j.net.SimpleSocketServer;
public class SocketDeserializeDemo {
public static void main(String[] args){
System.out.println("INFO: Log4j Listening on port 8888");
String[] arguments = {"8888", (new SocketDeserializeDemo()).getClass().getClassLoader().getResource("log4j.properties").getPath()};
SimpleSocketServer.main(arguments);
System.out.println("INFO: Log4j output successfuly.");
}
}
2.3.3 配置文件示例
# src/resources/log4j.properties
log4j.rootCategory=DEBUG,stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.threshold=DEBUG
log4j.appender.stdout.layout.ConversionPattern=[%d{yyy-MM-dd HH:mm:ss,SSS}]-[%p]-[MSG!:%m]-[%c\:%L]%n
2.3.4 关键代码分析
SimpleSocketServer.main()方法调用了SocketNode类SocketNode类实现了Runnable接口:- 构造方法从socket流中获取数据并封装为
ObjectInputStream对象 run()方法中直接调用readObject()进行反序列化操作
- 构造方法从socket流中获取数据并封装为
- 由于没有数据过滤机制,导致反序列化漏洞
2.4 利用条件
- 目标系统使用Log4j 1.2.x <= 1.2.17
- 目标系统classpath中存在可利用的反序列化Gadget链(如commons-collections 3.1)
3. CVE-2017-5645 (Log4j 2.x反序列化漏洞)
3.1 影响版本
- Log4j 2.x <= 2.8.1
3.2 漏洞环境搭建
- Log4j 2.8.1
- Debian系统
- JDK 1.7
- 下载地址: Apache Log4j 2.8.1
3.3 漏洞分析
3.3.1 漏洞原理
与Log4j 1.x的漏洞类似,漏洞存在于TcpSocketServer类中,该服务接收到的数据会被转换为ObjectInputStream对象并直接进行反序列化操作,没有进行任何过滤或验证。
3.3.2 漏洞复现代码
// src/main/java/Log4jSocketServer.java
import org.apache.logging.log4j.core.net.server.ObjectInputStreamLogEventBridge;
import org.apache.logging.log4j.core.net.server.TcpSocketServer;
import java.io.IOException;
import java.io.ObjectInputStream;
public class Log4jSocketServer {
public static void main(String[] args){
TcpSocketServer<ObjectInputStream> myServer = null;
try {
myServer = new TcpSocketServer<ObjectInputStream>(8888, new ObjectInputStreamLogEventBridge());
} catch (IOException e){
e.printStackTrace();
}
myServer.run();
}
}
3.3.3 Maven依赖配置
<!-- maven文件pom.xml -->
<?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>log4j-2.x-rce</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-core -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.8.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-api -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.8.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-collections/commons-collections -->
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.1</version>
</dependency>
</dependencies>
</project>
3.3.4 关键代码分析
- 程序在8888端口监听,接收数据并转换为
ObjectInputStream对象 - 在
handler.start()中调用SocketHandler类的run方法 ObjectInputStream对象被传入ObjectInputStreamLogEventBridge类的logEvents方法- 反序列化操作发生在
logEvents方法中
3.4 利用条件
- 目标系统使用Log4j 2.x <= 2.8.1
- 目标系统classpath中存在可利用的反序列化Gadget链(如commons-collections 3.1)
4. 漏洞修复建议
4.1 CVE-2019-17571修复方案
- 升级到Log4j 1.2.18或更高版本
- 如果无法升级,应避免使用
SimpleSocketServer功能 - 在反序列化前添加数据验证机制
4.2 CVE-2017-5645修复方案
- 升级到Log4j 2.8.2或更高版本
- 如果无法升级,应避免使用
TcpSocketServer功能 - 在反序列化前添加数据验证机制
5. 总结
这两个Log4j反序列化漏洞(CVE-2019-17571和CVE-2017-5645)都源于对socket流数据的不安全反序列化操作。漏洞利用的关键在于目标系统classpath中存在可利用的反序列化Gadget链。开发人员应及时升级受影响版本,或采取其他缓解措施防止漏洞被利用。