fastjson及其反序列化分析--TemplatesImpl


fastjson及其反序列化分析


源碼取自
https://www.github.com/ZH3FENG/PoCs-fastjson1241

參考
(23條消息) Json詳解以及fastjson使用教程_srj1095530512的博客-CSDN博客_fastjson

parse方法和parseObject方法區別:

	parse()及parseObject()進行反序列化時的細節區別在於,parse() 會識別並調用目標類的 setter 方法,而 parseObject() 由於要將返回值轉化為JSONObject,多執行了 JSON.toJSON(obj),所以在處理過程中會調用反序列化目標類的getter 方法來將參數賦值給JSONObject

ParserConfig類:配置反序列化信息

Autotype:

​ Fastjson提供了autotype功能,允許用戶在反序列化數據中通過“@type”指定反序列化的Class類型。

AutoType安全校驗
知道了AutoType的作用后,假設如下場景,

​ 服務端接收到的請求Json串中包含了指定惡意代碼Class的@Type,
​ 服務端調用JSON.parseObject()時觸發了該Class中的構造函數、或者是getter、setter方法中的惡意代碼

AutoType黑名單機制:在反序列化時,會校驗指定的class是否在黑名單中,若在,則拋出異常

Safemode機制:配置safeMode后,無論白名單和黑名單,都不支持autoType,可一定程度上緩解反序列化Gadgets類變種攻擊。

TemplatesImpl 利用鏈

fastjson反序列化TemplatesImpl - Afant1 - 博客園 (cnblogs.com)

在fastjson中調用Templateslmpl可以構造一條反序列化攻擊鏈。

攻擊鏈分析

TemplatesImpl攻擊調用鏈路
com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl是歷史上出現過存在FastJson反序列漏洞的一個第三方類

TemplatesImpl中存在一個get方法為getOutputProperties(),其在調用FastJson.parseObject()序列化為Java對象時會被調用
getOutputProperties內部調用了newTransformer()方法,newTransformer()內部調用了getTransletInstance()方法獲取Translet對象
獲取Translet對象時,其通過內部的私有變量_bytecodes生成返回的Translet對象
這里這個_bytecodes私有變量就是整個攻擊設計的核心所在,雖然FastJson默認只能反序列化公有屬性,但是可以在JSON串中指定_bytecodes為我們惡意攻擊類的字節碼,同時調用JSON.parseObject(json, Object.class, Feature.SupportNonPublicField)來反序列化私有屬性,那么_bytecodes就可以是任意指定代碼

也就是說,如果事先定義好了Translet返回Class類的內容,並且在自定義的Translet類的構造函數中實現攻擊代碼,並且把攻擊代碼轉化成字節碼,傳入TemplatesImpl的私有變量_bytecodes中,那么反序列化生成TemplatesImpl時就會使用我們自定義的字節碼來生成Translet類,從而觸發Translet構造函數中的攻擊代碼

​ 首先使用parseObject對payload進行反序列化。parseObject會調用payload中存儲的@type信息,即Templateslmpl的getter,setter,和構造方法。

在TypeUtil.class中下斷點,此處加載Templateslmpl類。

這里調用了getter方法,getOutputProperties

調用newTransformer方法

調用getTransletInstance方法

這里會調用defineTransletClasses,通過傳入的_bytecodes生成 _class

此處可以看到成功傳入類名,調用newInstance實例化為tranlet對象

此處調用惡意構造方法

完整的利用鏈

payload構造分析

 String payload = "{\"@type\":\"" + NASTY_CLASS +
     "\",\"_bytecodes\":[\""+evilCode+"\"],'_name':'a.b','_tfactory':{ },\"_transletIndex\":0,\"_auxClasses\":{},\"_outputProperties\":{}}";

這里NASTY_CLASS是指要加載的類,這里evilCode時包含惡意代碼的類路徑,需要使用字節碼在進行base64編碼。getTransletInstance方法中會判斷_name是否為空,因此這里需要設置 _name字段。

 public static String readClass(String cls){
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        try {
            IOUtils.copy(new FileInputStream(new File(cls)), bos);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return Base64.encodeBase64String(bos.toByteArray());
    }

這里對整個_bytecodes部分做了base64解碼,所以payload要進行base64編碼

JdbcRowSetImpl利用鏈

fastjson反序列化JdbcRowSetImpl - Afant1 - 博客園 (cnblogs.com)
待更新


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM