Fastjson 1.2.24遠端程式碼執行漏洞(com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl)

systemino發表於2020-11-24

1.漏洞資訊

1.1 漏洞簡介

· 漏洞名稱:Fastjson 1.2.24遠端程式碼執行漏洞(com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl)

· 漏洞編號:無

· 漏洞型別:遠端程式碼執行

· CVSS評分:無

· 漏洞危害等級:高危

1.2 元件概述

Fastjson是一個Java語言編寫的高效能功能完善的JSON庫。它採用一種“假定有序快速匹配”的演算法,把JSON Parse的效能提升到極致,是目前Java語言中最快的JSON庫。Fastjson介面簡單易用,已經被廣泛使用在快取序列化、協議互動、Web輸出、

Android客戶端等多種應用場景。下圖是Fastjson元件中的反序列化流程。Fastjson 1.2.24遠端程式碼執行漏洞(com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl)

1.3 漏洞概述

漏洞是利用fastjson autotype在處理json物件的時候,未對@type欄位進行完全的安全性驗證,攻擊者可以傳入危險類,奇熱伺服器接收到危險類執行其中惡意程式碼。攻擊者通過這種方式可以實現遠端程式碼執行漏洞的利用,獲取伺服器的敏感資訊洩露,甚至可以利用此漏洞進一步對伺服器資料進行修改,增加,刪除等操作,對伺服器造成巨大的影響。

1.4 漏洞利用條件

· 

1.5 漏洞影響

影響版本:
Fastjson < 1.2.25

1.6 漏洞修復

獲取Fastjson最新版本,下載連結:https://github.com/alibaba/fastjson

2.漏洞復現

2.1 環境拓撲

Fastjson 1.2.24遠端程式碼執行漏洞(com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl)

2.2 應用協議

8080/HTTP

2.3 復現過程

基於Windows平臺,使用環境目錄下的fastjsondemo環境,拷貝後使用Idea開啟fastjsondemo資料夾,下載maven資源,執行DemoApplication類即可啟動環境。效果如圖。


Fastjson 1.2.24遠端程式碼執行漏洞(com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl)

執行sniper工具箱,填寫表單資訊,點選Attack,效果如圖。

Fastjson 1.2.24遠端程式碼執行漏洞(com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl)

3.漏洞分析

3.1 技術背景

JavaBean:

JavaBean 是特殊的 Java 類,使用 Java 語言書寫,並且遵守 JavaBean API 規範。JavaBean的特徵

· 提供一個預設的無參建構函式。

· 需要被序列化並且實現了 Serializable 介面。

· 可能有一系列可讀寫屬性。

· 可能有一系列的 getter 或 setter 方法

方法描述
getPropertyName()舉例來說,如果屬性的名稱為 myName,那麼這個方法的名字就要寫成 getMyName() 來讀取這個屬性。這個方法也稱為訪問器。
setPropertyName()舉例來說,如果屬性的名稱為 myName,那麼這個方法的名字就要寫成 setMyName()來寫入這個屬性。這個方法也稱為寫入器。

程式例項

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

public class StudentsBean implements java.io.Serializable

{

   private String firstName = null;

   private String lastName = null;

   private int age = 0;

 

   public StudentsBean() {

   }

   public String getFirstName(){

      return firstName;

   }

   public String getLastName(){

      return lastName;

   }

   public int getAge(){

      return age;

   }

 

   public void setFirstName(String firstName){

      this.firstName = firstName;

   }

   public void setLastName(String lastName){

      this.lastName = lastName;

   }

   public void setAge(int age) {

      this.age = age;

   }

}

3.2 詳細分析

3.2.1 程式碼分析

Fastjson通過parseObject方法解析傳入的json資料。

Fastjson 1.2.24遠端程式碼執行漏洞(com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl)

呼叫DefaultJSONParser預設方法對json格式資料進行解析

Fastjson 1.2.24遠端程式碼執行漏洞(com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl)

在方法的引數中,呼叫ParserConfig.getGlobalInstance()方法獲取ParserConfig類中的初始配置,其中黑名單(denyList)也在此類中進行配置

 

Fastjson 1.2.24遠端程式碼執行漏洞(com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl)

呼叫addDeny方法迴圈新增denyList陣列中的黑名單。

Fastjson 1.2.24遠端程式碼執行漏洞(com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl)

Fastjson 1.2.24遠端程式碼執行漏洞(com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl)

回到DefaultJSONParser方法,初始化結束後,呼叫JSONScanner方法對傳入的json字串設定讀取位置,判斷過程中處理Unicode字符集的BOM標識

Fastjson 1.2.24遠端程式碼執行漏洞(com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl)

回到DefaultJSONParser方法,為token賦值。

Fastjson 1.2.24遠端程式碼執行漏洞(com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl)

回到JSON入口類,獲取到DefaultJSONParser型別物件,呼叫parse()方法進行解析。

Fastjson 1.2.24遠端程式碼執行漏洞(com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl)

在parse方法中,通過判斷lexer.token(),進入對應的程式碼塊。

Fastjson 1.2.24遠端程式碼執行漏洞(com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl)

呼叫JSONObject構造方法,初始化JSONObject類中的map屬性。

Fastjson 1.2.24遠端程式碼執行漏洞(com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl)

回到DefaultJSONParser#parse方法,呼叫parseObject方法,對傳入的json資料進行位元組讀取

Fastjson 1.2.24遠端程式碼執行漏洞(com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl)

一般會讀取json字串中的雙引號進入scanSymbol方法中,在scanSymbol方法中計算字串的hash。

Fastjson 1.2.24遠端程式碼執行漏洞(com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl)

呼叫addSymbol方法,將鍵名新增到SymbolTable中。

Fastjson 1.2.24遠端程式碼執行漏洞(com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl)

回到DefaultJSONParser#parseObject方法中,判斷key值是否為@type。如果是,獨步則進入if判斷條件下的程式碼塊中。

Fastjson 1.2.24遠端程式碼執行漏洞(com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl)

呼叫scanSymbol方法,以雙引號作為quote變數值,進行@typejson欄位值的value讀取

Fastjson 1.2.24遠端程式碼執行漏洞(com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl)

獲得@type的鍵值,呼叫addSymbol方法,將@type的欄位值新增到SymbolTable中

Fastjson 1.2.24遠端程式碼執行漏洞(com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl)

回到DefaultJSONParser#parseObject方法中,呼叫TypeUtils.loadClass方法進行類載入操作

Fastjson 1.2.24遠端程式碼執行漏洞(com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl)

進入loadClass方法中,首先會在現有的mappings中尋找從@type傳入的classname

Fastjson 1.2.24遠端程式碼執行漏洞(com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl)

如果在原有的mappings中沒有記錄傳入的classname,則呼叫contextClassLoader.loadClass獲取AppClassLoader類載入器並載入到mappings中與@type傳入的類進行關聯,最後返回clazz物件。

Fastjson 1.2.24遠端程式碼執行漏洞(com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl)

回到DefaultJSONParser#parseObject方法中,呼叫this.config.getDeserializer(clazz)獲取反序列化器。

Fastjson 1.2.24遠端程式碼執行漏洞(com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl)

進入getDeserializer方法中,首先現有的IdentityHashMap中進行hash匹配,如果無法匹配,則進入第二個if判斷條件中過載getDeserializer方法繼續獲取反序列化器。

Fastjson 1.2.24遠端程式碼執行漏洞(com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl)

在getDeserializer(Class方法中,首先依然會與現有的IdentityHashMap中進行hash匹配。如果無法匹配會事先進行黑名單匹配,在呼叫ServiceLoader.load判斷META-INF/services/下是否存在傳入的classname類。Fastjson 1.2.24遠端程式碼執行漏洞(com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl)

如果沒有尋找到對應的類,則判斷傳入的classname是否是繼承java.lang.Enum、是否是array型別選擇對應的反序列化器生成方法。如果上述條件不滿足,則繼續判斷傳入的classname是否為Set、HashSet、Collection、List、ArrayList,如果不是則繼續判斷classname是否繼承Collection,Map,Throwable介面。如果上述條件都不滿足,則呼叫createJavaBeanDeserializer方法生成JavaBean反序列化器

Fastjson 1.2.24遠端程式碼執行漏洞(com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl)

進入createJavaBeanDeserializer方法,判斷asmEnable是否為true,呼叫JavaBeanInfo.build方法建立JavaBean

Fastjson 1.2.24遠端程式碼執行漏洞(com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl)

建立JavaBean過程中,通過反射機制獲取傳入的class中所有的屬性,方法,並儲存在陣列中。選擇一個無參建構函式作為預設的建構函式

Fastjson 1.2.24遠端程式碼執行漏洞(com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl)

迴圈遍歷method陣列中的方法,並從中選取符合條件的方法。(條件:同時滿足方法名長度大於4;非靜態方法;方法型別為Void。或者方法型別與方法所在類相同)

Fastjson 1.2.24遠端程式碼執行漏洞(com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl)

再從篩選的規則中繼續篩選出形引數量為1的方法。

Fastjson 1.2.24遠端程式碼執行漏洞(com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl)

再從篩選出的方法中獲取以set方法開頭的方法,並檢測JavaBean的方法命名規範,篩選出符合規範的方法。呼叫TypeUtils.getField方法獲取與set方法對應的屬性值

Fastjson 1.2.24遠端程式碼執行漏洞(com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl)

進入getField方法中,遍歷@type傳入的class以及其父類的所有屬性值,返回尋找到屬性。

Fastjson 1.2.24遠端程式碼執行漏洞(com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl)

最終呼叫add方法,將獲取的Field屬性儲存到fieldList列表中。

Fastjson 1.2.24遠端程式碼執行漏洞(com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl)

再以相同的流程篩選出存在get方法的屬性值,如果篩選出的filed屬性值不在fieldList,則新增到fieldList列表中。

Fastjson 1.2.24遠端程式碼執行漏洞(com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl)

 

呼叫JavaBeanInfo方法對JavaBeanInfo中的屬性進行初始化,並返回例項化物件。

Fastjson 1.2.24遠端程式碼執行漏洞(com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl)

Fastjson 1.2.24遠端程式碼執行漏洞(com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl)

回到ParserConfig#createJavaBeanDeserializer方法中,獲取到beanInfo物件,並從beaninfo中取出defaultConstructor預設構造器、field屬性

Fastjson 1.2.24遠端程式碼執行漏洞(com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl)

通過檢測fieldClass屬性值,為asmEnable標誌位賦值

Fastjson 1.2.24遠端程式碼執行漏洞(com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl)

由於@type傳入的class中的javabean方法,存在只讀屬性,因此asmEnable標誌位變成false。

Fastjson 1.2.24遠端程式碼執行漏洞(com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl)

根據asmEnable標誌位,進行if條件判斷,呼叫JavaBeanDeserializer構造方法,並返回例項化物件。

Fastjson 1.2.24遠端程式碼執行漏洞(com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl)

在例項化過程中,會將beaninfo中的屬性賦值給JavaBeanDeserializer類中的filed反序列化器。

Fastjson 1.2.24遠端程式碼執行漏洞(com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl)

回到ParserConfig#getDeserializer方法,呼叫putDeserializer方法,將生成的反序列化器與@type傳入的class類進行關聯,最後返回反序列化器

Fastjson 1.2.24遠端程式碼執行漏洞(com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl)

回到DefaultJSONParser#parseObject方法,呼叫deserializer.deserialze方法進行反序列化。

Fastjson 1.2.24遠端程式碼執行漏洞(com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl)

進入deserialze方法中,首先根據token值進入到對應的條件程式碼塊。呼叫scanSymbol方法。

Fastjson 1.2.24遠端程式碼執行漏洞(com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl)

進入scanSymbol方法,對傳入的json字串進行解析,和解析@type的流程相同,解析傳入的其他屬性欄位。

Fastjson 1.2.24遠端程式碼執行漏洞(com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl)

回到JavaBeanDeserializer#deserialze方法中,解析的屬性值返回並賦值到key屬性中。

Fastjson 1.2.24遠端程式碼執行漏洞(com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl)

呼叫parseField方法解析屬性。

Fastjson 1.2.24遠端程式碼執行漏洞(com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl)

進入parseField方法,呼叫smartMatch方法,獲取field反序列化器。

Fastjson 1.2.24遠端程式碼執行漏洞(com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl)

進入smartMatch方法,首先會從建立的javabean中尋找是否存在對應key中屬性值的操作方法。

Fastjson 1.2.24遠端程式碼執行漏洞(com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl)

如果沒有匹配到javabean中的方法,則先消除掉屬性值中的_和-符號,再與javabean中的方法進行匹配,如果匹配成功,則返回反序列化器。如果匹配失敗,則返回null。

Fastjson 1.2.24遠端程式碼執行漏洞(com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl)

Fastjson 1.2.24遠端程式碼執行漏洞(com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl)

回到parseField方法中,設定Feature.SupportNonPublicField狀態,並根據狀態值進入if條件判斷的程式碼塊中,生成extraFieldDeserializers擴充套件的反序列化器。再從反序列化器中取出從fastjson獲取的json資料中指定的屬性。Fastjson 1.2.24遠端程式碼執行漏洞(com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl)

呼叫parseField方法,按照獲取deserializer反序列化器的流程,獲取fieldValueDeserilizer反序列化器。得到的fieldValueDeserilizer反序列化器,在parseField方法中呼叫deserialze方法進行反序列化Fastjson 1.2.24遠端程式碼執行漏洞(com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl)

由於傳入的引數中存在陣列,fastjson首先會呼叫getFastMatchToken方法,獲取當前json字串位置的token標誌值。

Fastjson 1.2.24遠端程式碼執行漏洞(com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl)

由於json字串中的陣列是以[data]的形式傳入的,所以當檢測屬性值是以[開頭,則為token賦值為14。

Fastjson 1.2.24遠端程式碼執行漏洞(com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl)

由於是陣列型別,因此在獲取反序列化器時,會進入ObjectArrayCodec類進行解析。

呼叫ObjectArrayCodec#parseArray方法,進行陣列的解析。

Fastjson 1.2.24遠端程式碼執行漏洞(com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl)

根據陣列中的元素型別,進行token賦值,再依據token,選擇對應token值,進入對應的if程式碼塊。

Fastjson 1.2.24遠端程式碼執行漏洞(com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl)

解析陣列中元素時,如果元素時String型別,則將字串按照byte型別進行讀取,在讀取的過程中,會先進行base64解碼。

Fastjson 1.2.24遠端程式碼執行漏洞(com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl)

Fastjson 1.2.24遠端程式碼執行漏洞(com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl)

最終以]符號作為陣列結束符。

Fastjson 1.2.24遠端程式碼執行漏洞(com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl)

回到ObjectArrayCodec#deserialze方法中,呼叫toObjectArray方法,將傳入的陣列資料,轉換成陣列物件。

Fastjson 1.2.24遠端程式碼執行漏洞(com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl)

回到DefaultDeserializer#parseField方法中,呼叫setValue方法,將獲取的陣列物件,賦予到@type class中的對應屬性中。

Fastjson 1.2.24遠端程式碼執行漏洞(com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl)

在解析最後一個_outputProperties引數時,會在setValue方法中進行反射,呼叫getOutputProperties方法。

Fastjson 1.2.24遠端程式碼執行漏洞(com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl)

此方法會在呼叫的過程中,例項化從bytecode傳入惡意class檔案,從而實現攻擊。

Fastjson 1.2.24遠端程式碼執行漏洞(com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl)

3.2.2補丁分析

Fastjson1.2.25版本新增了checkAutoType方法,設定了autotype開關,對@type欄位進行限制。如果autotype開關關閉,則無法從@type欄位傳入類進行jndi攻擊。

Fastjson 1.2.24遠端程式碼執行漏洞(com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl)

增加了黑名單中的類,對fastjson的gadget進行攔截。

Fastjson 1.2.24遠端程式碼執行漏洞(com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl)

4.參考連結

1.https://www.runoob.com/jsp/jsp-javabean.html
2.http://xxlegend.com/2018/10/23/%E5%9F%BA%E4%BA%8EJdbcRowSetImpl%E7%9A%84Fastjson%20RCE%20PoC%E6%9E%84%E9%80%A0%E4%B8%8E%E5%88%86%E6%9E%90/
3.https://github.com/alibaba/fastjson/compare/1.2.24...1.2.25

相關文章