中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

怎樣進行Fastjson 1.2.24反序列化漏洞分析

發布時間:2021-12-14 09:39:17 來源:億速云 閱讀:257 作者:柒染 欄目:安全技術

這期內容當中小編將會給大家帶來有關怎樣進行Fastjson 1.2.24反序列化漏洞分析,文章內容豐富且以專業的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。

0x00 fastjson

fastjson是一個非常流行的庫,可以將數據在JSON和Java Object之間互相轉換,但是在2017年官方主動爆出了fastjson的反序列化漏洞以及升級公告,這次我們就學習一下這個漏洞。

最終的payload會放到我的GitHub上。

這次使用的fastjson是1.2.23版本:

<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson --><dependency>
   <groupId>com.alibaba</groupId>
   <artifactId>fastjson</artifactId>
   <version>1.2.23</version></dependency>

在分析漏洞之前,我們先看下這個庫都有什么樣的功能,我們先創建一個User對象:

class User {    private int age;    public String username;    private String secret;    public int getAge() {        return age;
   }    public void setAge(int age) {        this.age = age;
   }    public String getUsername() {        return username;
   }    public void setUsername(String username) {        this.username = username;
   }    public String getSecret() {        return secret;
   }
}

我們主要關注一下從JSON還原回Object的方法,主要的API有兩個,分別是JSON.parseObject和JSON.parse,最主要的區別就是前者返回的是JSONObject而后者返回的是實際類型的對象,當在沒有對應類的定義的情況下,通常情況下都會使用JSON.parseObject來獲取數據。

fastjson接受的JSON可以通過@type字段來指定該JSON應當還原成何種類型的對象,在反序列化的時候方便操作。

String myJSON = "{\"@type\":\"me.lightless.fastjsonvuln.User\",\"age\":99,\"username\":\"lightless\",\"secret\":\"2333\"}";
JSONObject u3 = JSON.parseObject(myJSON);
System.out.println("u3 => " + u3.get("secret"));

如果需要還原出private成員的話,還需要加上Feature.SupportNonPublicField:

User u3 = (User) JSON.parseObject(myJSON, User.class, Feature.SupportNonPublicField);

0x01 跟蹤分析

根據官方的公告中的WAF檢測方法來看,問題很有可能是因為反序列化了任意類型的class從而導致的RCE。

怎樣進行Fastjson 1.2.24反序列化漏洞分析

從網上找到的payload中也能看出利用的是TemplatesImpl來執行的命令,這個在之前的JDK7u21中已經分析過了,可能還存在其他的執行命令方法,這些我們暫且不談,主要來看fastjson的部分。

我們搭建一個簡單的Web應用來接受用戶POST過來的JSON并且進行反序列化: 

@RestControllerpublic class IndexController {    @RequestMapping(value = "/fastjson", method = RequestMethod.GET)    public String fastjson() {        return "Hello World!";
   }    @RequestMapping(value = "/fastjson", method = RequestMethod.POST)    public JSONObject testVuln(@RequestBody String data) {
       JSONObject obj = JSON.parseObject(data, Feature.SupportNonPublicField);
       JSONObject ret = new JSONObject();
       ret.put("code", 1001);
       ret.put("data", "Hello " + obj.get("name"));        return ret;
   }
}

傳入我們帶有@type類型的JSON字符串并且開始調試。在JSON.parseObject處下斷并開始向下跟。

怎樣進行Fastjson 1.2.24反序列化漏洞分析

一開始會跟進到JSON.parse方法,并且調用了parse()方法繼續進行JSON格式的匹配。繼續跟進parser.parse()方法。

怎樣進行Fastjson 1.2.24反序列化漏洞分析

到了這里之后,開始依次進行JSON的解析,我們傳入的第一個字符是{,所以進入LBRACE這個分支中,并繼續進入parseObject(object, fieldName)方法來解析對象。

怎樣進行Fastjson 1.2.24反序列化漏洞分析

這個時候lexer所在的字符為",會進入下面這個分支繼續解析JSON字符串,通過scanSymbol方法獲取到雙引號之間的字符串也就是@type

怎樣進行Fastjson 1.2.24反序列化漏洞分析

之后會獲取@type字段的值,并且嘗試獲取這個類的Class,經過一系列的判斷后,調用了deserializer.deserialize(this, clazz, fieldName)方法進行反序列化。

怎樣進行Fastjson 1.2.24反序列化漏洞分析

一開始沒找到sortedFieldDeserializers是在什么地方生成的,想仔細跟一下代碼,于是就從頭到尾的看了下getDeserializer(clazz)的部分,發現是在這里生成的。這個函數的目的是獲取一個可以反序列化我們通過@type指定的類的deserializer,由于預定于的列表中沒有,于是會繼續調用createJavaBeanDeserializer()來生成一個,實際上是調用了ParseConfig.build()方法,其中會通過反射機制獲取我們指定類的一些信息,通過對method進行一些過濾,猜測出getter和setter并推出一些可能存在的field。

具體的猜測規則這里不展開說明了,感興趣的話可以自行跟一下

緊接著就依次處理JSON字符串中的各個字段,當匹配到payload中的_tfactory字段的時候,由于我們傳入的JSON字符串中是一個空的對象,進入parseField方法后,繼續向下跟就會調用到JavaBeanDeserializer.deserialize()方法,在這里會為_factory創建一個TransformerFactoryImpl對象并賦值。

同樣的,_outputProperties字段我們也是傳入了一個空對象,會進入和上面相同的流程,仔細分析一下這段代碼,這里是觸發命令執行的關鍵部分。

怎樣進行Fastjson 1.2.24反序列化漏洞分析

首先依然會進入parseField方法

怎樣進行Fastjson 1.2.24反序列化漏洞分析

進入之后會調用smartMatch(key)方法,這個方法的主要作用是進行一些『智能匹配』,方便后續獲取對應變量的getter和setter。調用后這個方法會去掉字符串中的-、刪除開頭的下劃線等,所以當我們傳入了_outputProperties的時候,實際上就給處理成了outputProperties,并返回對應的FieldDeserializer對象,之后就會調用該對象的parseField方法。進入該方法后,就會調用setValue(object, value)方法,繼續跟進。

怎樣進行Fastjson 1.2.24反序列化漏洞分析

跟進之后顯而易見,getOutputProperties被調用了:

怎樣進行Fastjson 1.2.24反序列化漏洞分析

然后就會執行我們在_bytecodes構造的惡意字節碼,造成命令執行。

0x02 一些疑問

根據上面的流程,我們應該已經可以寫出PoC了,這里就不占用篇幅展示了,直接放到了我的GitHub上。 

一開始在構造的時候發現字節碼中存在許多的不可顯字符,網上公開的PoC中使用了base64來編碼,感覺非常神奇,為什么fastjson會幫我們解碼呢?于是構造了數組傳入之后,發現fastjson在處理[B類型的數組時,會調用lexer.bytesValue(),其中的lexer就是JSONScanner,這個bytesValue()方法會自動幫我們執行一次base64解碼,所以我們構造payload的時候只需要傳入base64編碼后的內容即可。

怎樣進行Fastjson 1.2.24反序列化漏洞分析怎樣進行Fastjson 1.2.24反序列化漏洞分析

至此,其實整個流程已經走完了,但是還有一點令我們非常難受,就是我們的demo中,在接收JSON的時候設置了Feature.SupportNonPublicField。默認情況下fastjson只會反序列化public的方法和屬性,而我們構造的PoC中有private的成員變量_bytecodes和_name,為了給這些變量賦值,則必須要假設服務端開啟了SupportNonPublicField功能。

而現實情況下,大部分都是parse(json)和parseObject(json)一把梭,使用這個功能的情況不是很多,這樣一來就導致我們的PoC沒有了良好的通用性,那么有沒有解決方案呢?答案當然是有的,那就是不使用TemplatesImpl,換一種RCE的觸發方式即可。在網上經過一番搜索,發現了一些可以利用的方法

主要是利用JNDI+RMI方法,這個可以參考之前的spring-tx.jar的反序列化問題,當時就是采用這種方式來觸發的。但是調用鏈不太好找,這個PPT中給出了多個利用鏈,這里的調用鏈后續再進行分析,這里暫且不做驗證。

這樣一來,只要是開發同學在編寫代碼時,直接反序列化了用戶傳入的JSON,就有可能造成RCE,而攻擊者也無需關心SupportNonPublicField是否開啟了,危害提高了許多。

0x03 修復措施

在fastjson的官方補丁中,將loadClass(typeName, config.getDefaultClassLoader())替換為了config.checkAutoType(typeName),并且擴充了黑名單列表,將傳入的類名與黑名單一一比較,如果發現了相同開頭的類就停止反序列化。

// 新增的黑名單
bsh
com.mchange
com.sun.
java.lang.Thread
java.net.Socket
java.rmi
javax.xml
org.apache.bcel
org.apache.commons.beanutils
org.apache.commons.collections.Transformer
org.apache.commons.collections.functors
org.apache.commons.collections4.comparators
org.apache.commons.fileupload
org.apache.myfaces.context.servlet
org.apache.tomcat
org.apache.wicket.util
org.codehaus.groovy.runtime
org.hibernate
org.jboss
org.mozilla.javascript
org.python.core
org.springframework

可以看到絕大部分常用的類都已經被加進來了,但是如果不經常維護此名單,一旦后面出現了新的可以利用的類,很容易就繞過這個限制。

上述就是小編為大家分享的怎樣進行Fastjson 1.2.24反序列化漏洞分析了,如果剛好有類似的疑惑,不妨參照上述分析進行理解。如果想知道更多相關知識,歡迎關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

府谷县| 关岭| 台北县| 湘潭市| 墨竹工卡县| 白山市| 分宜县| 万载县| 呼图壁县| 韩城市| 广东省| 衢州市| 白山市| 合江县| 务川| 托里县| 北票市| 金乡县| 河北省| 正镶白旗| 临桂县| 永善县| 陇南市| 准格尔旗| 宜黄县| 阿尔山市| 缙云县| 时尚| 泾源县| 库尔勒市| 织金县| 汾阳市| 弥渡县| 来安县| 玉门市| 旬阳县| 观塘区| 澜沧| 新郑市| 武义县| 赤壁市|