Fastjson 1.2.24遠端程式碼執行漏洞(com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl)
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元件中的反序列化流程。
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 環境拓撲
2.2 應用協議
8080/HTTP
2.3 復現過程
基於Windows平臺,使用環境目錄下的fastjsondemo環境,拷貝後使用Idea開啟fastjsondemo資料夾,下載maven資源,執行DemoApplication類,即可啟動環境。效果如圖。
執行sniper工具箱,填寫表單資訊,點選Attack,效果如圖。
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資料。
呼叫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變數值,進行@typejson欄位值的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方法中,首先依然會與現有的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標誌位賦值
由於@type傳入的class中的javabean方法,存在只讀屬性,因此asmEnable標誌位變成false。
根據asmEnable標誌位,進行if條件判斷,呼叫JavaBeanDeserializer構造方法,並返回例項化物件。
在例項化過程中,會將beaninfo中的屬性賦值給JavaBeanDeserializer類中的filed反序列化器。
回到ParserConfig#getDeserializer方法,呼叫putDeserializer方法,將生成的反序列化器與@type傳入的class類進行關聯,最後返回反序列化器
回到DefaultJSONParser#parseObject方法,呼叫deserializer.deserialze方法進行反序列化。
進入deserialze方法中,首先根據token值進入到對應的條件程式碼塊。呼叫scanSymbol方法。
進入scanSymbol方法,對傳入的json字串進行解析,和解析@type的流程相同,解析傳入的其他屬性欄位。
回到JavaBeanDeserializer#deserialze方法中,解析的屬性值返回並賦值到key屬性中。
呼叫parseField方法解析屬性。
進入parseField方法,呼叫smartMatch方法,獲取field反序列化器。
進入smartMatch方法,首先會從建立的javabean中尋找是否存在對應key中屬性值的操作方法。
如果沒有匹配到javabean中的方法,則先消除掉屬性值中的_和-符號,再與javabean中的方法進行匹配,如果匹配成功,則返回反序列化器。如果匹配失敗,則返回null。
回到parseField方法中,設定Feature.SupportNonPublicField狀態,並根據狀態值進入if條件判斷的程式碼塊中,生成extraFieldDeserializers擴充套件的反序列化器。再從反序列化器中取出從fastjson獲取的json資料中指定的屬性。
呼叫parseField方法,按照獲取deserializer反序列化器的流程,獲取fieldValueDeserilizer反序列化器。得到的fieldValueDeserilizer反序列化器,在parseField方法中呼叫deserialze方法進行反序列化。
由於傳入的引數中存在陣列,fastjson首先會呼叫getFastMatchToken方法,獲取當前json字串位置的token標誌值。
由於json字串中的陣列是以[data]的形式傳入的,所以當檢測屬性值是以[開頭,則為token賦值為14。
由於是陣列型別,因此在獲取反序列化器時,會進入ObjectArrayCodec類進行解析。
呼叫ObjectArrayCodec#parseArray方法,進行陣列的解析。
根據陣列中的元素型別,進行token賦值,再依據token,選擇對應token值,進入對應的if程式碼塊。
解析陣列中元素時,如果元素時String型別,則將字串按照byte型別進行讀取,在讀取的過程中,會先進行base64解碼。
最終以]符號作為陣列結束符。
回到ObjectArrayCodec#deserialze方法中,呼叫toObjectArray方法,將傳入的陣列資料,轉換成陣列物件。
回到DefaultDeserializer#parseField方法中,呼叫setValue方法,將獲取的陣列物件,賦予到@type class中的對應屬性中。
在解析最後一個_outputProperties引數時,會在setValue方法中進行反射,呼叫getOutputProperties方法。
此方法會在呼叫的過程中,例項化從bytecode傳入惡意class檔案,從而實現攻擊。
3.2.2補丁分析
Fastjson1.2.25版本新增了checkAutoType方法,設定了autotype開關,對@type欄位進行限制。如果autotype開關關閉,則無法從@type欄位傳入類進行jndi攻擊。
增加了黑名單中的類,對fastjson的gadget進行攔截。
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
相關文章
- ThinkPHP遠端程式碼執行漏洞PHP
- phpunit 遠端程式碼執行漏洞PHP
- ThinkPHP 5.0.23 遠端程式碼執行漏洞PHP
- OpenWRT 曝遠端程式碼執行漏洞
- Joomla遠端程式碼執行漏洞分析OOM
- 關於fastjson出現反序列化遠端程式碼執行漏洞的通知ASTJSON
- 最新漏洞:Spring Framework遠端程式碼執行漏洞SpringFramework
- RCE(遠端程式碼執行漏洞)原理及漏洞利用
- WindowsJScript元件曝遠端程式碼執行漏洞WindowsJS元件
- .NET Remoting 遠端程式碼執行漏洞探究REM
- 什麼是遠端程式碼執行漏洞?
- 高危!Fastjson反序列化遠端程式碼執行漏洞風險通告,請儘快升級ASTJSON
- Fastjson反序列化遠端程式碼執行漏洞產生原因及修復建議ASTJSON
- Fastjson 程式碼執行漏洞 CVE-2022-25845ASTJSON
- Discuz! X系列遠端程式碼執行漏洞分析
- PHP CGI Windows下遠端程式碼執行漏洞PHPWindows
- log4j遠端程式碼執行漏洞
- crash_for_windows_pkg遠端程式碼執行漏洞Windows
- Apache Struts 再曝高危遠端程式碼執行漏洞Apache
- Fastjson反序列化漏洞分析 1.2.22-1.2.24ASTJSON
- Fastjson1.2.24反序列化漏洞復現ASTJSON
- [漏洞預警]Laravel <= 8.4.2 Debug模式 _ignition 遠端程式碼執行漏洞Laravel模式
- Spring WebFlow 遠端程式碼執行漏洞(CVE-2017-4971)SpringWeb
- Apache OFBiz遠端程式碼執行漏洞(CVE-2024-38856)Apache
- Log4j遠端程式碼執行漏洞漫談
- CVE-2020-17530——Apache Struts遠端程式碼執行漏洞Apache
- 網站漏洞檢測 squid反向代理存在遠端程式碼執行漏洞網站UI
- PHP-CGI遠端程式碼執行漏洞(CVE-2012-1823)PHP
- SMB遠端程式碼執行漏洞CVE-2020-0796安全通告
- Spring Cloud Gateway 遠端程式碼執行漏洞(CVE-2022-22947)SpringCloudGateway
- ElasticSearch Groovy指令碼遠端程式碼執行漏洞分析(CVE-2015-1427)Elasticsearch指令碼
- Steam客戶端發現遠端程式碼執行漏洞:已放補丁客戶端
- PHP-CGI遠端1程式碼執行漏洞(CVE-2012-1823)PHP
- PHP-fpm 遠端程式碼執行漏洞(CVE-2019-11043)分析PHP
- Apache Kylin遠端程式碼執行漏洞復現(CVE-2020-1956)Apache
- Weblogic遠端程式碼執行漏洞(CVE-2020-14750)修復方案Web
- Apache log4j2 遠端程式碼執行漏洞復現?Apache
- Apache Solr應用伺服器存在遠端程式碼執行漏洞?ApacheSolr伺服器