Effective Java(3rd)-Item85 更喜歡Java序列化的替代品

??當(dāng)序列化在1997年添加到Java中時(shí)盈蛮,它被認(rèn)為有一定的風(fēng)險(xiǎn)匪凡。這種方法曾在研究語言(模塊3)中嘗試過路媚,但從未在生產(chǎn)語言中使用過骡和。雖然程序員不費(fèi)什么力氣就能實(shí)現(xiàn)分布式對象的承諾很吸引人箍鼓,代價(jià)是看不見的構(gòu)造函數(shù)和API與實(shí)現(xiàn)之間模糊的界限崭参,在性能、安全性和維護(hù)的正確性上存在潛在的問題款咖。支持者認(rèn)為收益大于風(fēng)險(xiǎn)何暮,但歷史證明并非如此。
??在本書之前的版本中描述的安全問題铐殃,結(jié)果和一些人擔(dān)心的一樣嚴(yán)重海洼。早期討論過的漏洞在接下來的十年里,21世紀(jì)頭十年變成了嚴(yán)重的網(wǎng)絡(luò)攻擊富腊,其中著名的包括針對舊金山大都會運(yùn)輸署(San Francisco Metropolitan Transit Agency)的勒索軟件攻擊2016年11月坏逢,市政鐵路(SFMTA Muni)關(guān)閉了整個(gè)收費(fèi)系統(tǒng)兩天[Gallagher16]。
??序列化的一個(gè)基本問題是它的攻擊面太大而無法保護(hù)赘被,并且不斷增長:通過調(diào)用ObjectInputStream上的readObject方法來反序列化對象圖是整。這個(gè)方法本質(zhì)上是一個(gè)神奇的構(gòu)造函數(shù),可以用來實(shí)例化類路徑上幾乎任何類型的對象民假,只要該類型實(shí)現(xiàn)Serializable接口浮入。在反序列化字節(jié)流的過程中,此方法可以執(zhí)行來自任何這些類型的代碼羊异,因此所有這些類型的代碼都是攻擊面的一部分事秀。
??攻擊面包括Java平臺庫彤断、第三方庫(如Apache Commons collection)和應(yīng)用程序本身中的類。即使您堅(jiān)持所有相關(guān)的最佳實(shí)踐并成功地編寫了不受攻擊的可序列化類秽晚,您的應(yīng)用程序仍然可能是脆弱的瓦糟。引用CERT協(xié)調(diào)中心技術(shù)經(jīng)理Robert Seacord的話:


image.png

(Java反序列化是一個(gè)明顯而又存在的危險(xiǎn),因?yàn)樗粦?yīng)用程序直接和間接地廣泛使用赴蝇,比如RMI
(遠(yuǎn)程方法調(diào)用)菩浙、JMX (Java管理擴(kuò)展)和
JMS (Java消息傳遞系統(tǒng))。不可信流的反序列化可能導(dǎo)致遠(yuǎn)程代碼執(zhí)行(RCE)句伶、拒絕服務(wù)(DoS)和一系列其他攻擊劲蜻。應(yīng)用程序很容易受到這些攻擊,即使它們沒有做錯(cuò)什么考余。(Seacord17))
??攻擊者和安全研究人員研究Java庫和常用的第三方庫中的可序列化類型先嬉,尋找在反序列化過程中調(diào)用的執(zhí)行潛在危險(xiǎn)活動的方法。這種方法稱為gadget楚堤。多個(gè)gadget可以同時(shí)使用疫蔓,形成一個(gè)gadget鏈。偶爾會發(fā)現(xiàn)一個(gè)小部件鏈身冬,它的功能足夠強(qiáng)大衅胀,允許攻擊者在底層硬件上執(zhí)行任意的本機(jī)代碼,只允許提交精心設(shè)計(jì)的字節(jié)流進(jìn)行反序列化酥筝。這正是SFMTA Muni襲擊中發(fā)生的事情滚躯。這次襲擊并不是孤立的,已經(jīng)有了,而且還會有更多嘿歌。
??不使用任何小工具掸掏,您就可以通過導(dǎo)致需要很長時(shí)間反序列化的短流反序列化,輕松地發(fā)起拒絕服務(wù)攻擊宙帝。種流被稱為反序列化炸彈[Svoboda16]丧凤。下面是Wouter Coekaerts的一個(gè)例子,它只使用哈希集和字符串[Coekaerts15]:


image.png

??對象圖由201個(gè)HashSet實(shí)例組成步脓,每個(gè)實(shí)例包含3個(gè)或更少的對象引用愿待。整個(gè)流的長度為5,744字節(jié),但是在您對其進(jìn)行反序列化之前沪编,太陽就已經(jīng)耗盡了呼盆。問題是反序列化HashSet實(shí)例需要計(jì)算其元素的哈希碼。根哈希集的兩個(gè)元素本身就是包含哈希集的哈希集2個(gè)哈希集合元素蚁廓,每個(gè)哈希集合元素包含2個(gè)哈希集合元素访圃,以此類推,100等級深度.因此相嵌,反序列化set會導(dǎo)致hashCode方法被調(diào)用超過2^100次腿时。除了反序列化會持續(xù)很長時(shí)間之外况脆,反序列化器沒有任何錯(cuò)誤的跡象。生成的對象很少批糟,并且堆棧深度是有界的格了。
??那么你能做些什么來抵御這些問題呢?當(dāng)您反序列化一個(gè)您不信任的字節(jié)流時(shí),您就會受到攻擊徽鼎。避免序列化利用的最佳方法是永遠(yuǎn)不要反序列化任何東西盛末。用1983年電影《戰(zhàn)爭游戲》(WarGames)中名為約書亞(Joshua)的電腦的話來說,“唯一的制勝招就是不玩否淤∏牡”沒有理由在編寫的任何新系統(tǒng)中使用Java序列化。還有其他一些機(jī)制可以在對象和字節(jié)序列之間進(jìn)行轉(zhuǎn)換石抡,從而避免了Java序列化的許多危險(xiǎn)檐嚣,同時(shí)提供了許多優(yōu)勢,比如跨平臺支持啰扛、高性能嚎京、大型工具生態(tài)系統(tǒng)和廣泛的專家社區(qū)。在本書中隐解,我們將這些機(jī)制稱為跨平臺結(jié)構(gòu)數(shù)據(jù)表示鞍帝。雖然其他人有時(shí)將它們稱為序列化系統(tǒng),但本書避免使用這種用法厢漩,以免與Java序列化混淆膜眠。
??這些表示的共同之處在于岩臣,它們要比原來Java序列化簡單得多.它們不支持任意對象圖的自動序列化和反序列化溜嗜。相反,它們支持由一組屬性值對組成的簡單結(jié)構(gòu)化數(shù)據(jù)對象架谎。只支持少數(shù)基本數(shù)據(jù)類型和數(shù)組數(shù)據(jù)類型炸宵。事實(shí)證明,這個(gè)簡單的抽象足以構(gòu)建功能極其強(qiáng)大的分布式系統(tǒng)谷扣,而且足夠簡單土全,可以避免Java序列化從一開始就存在的嚴(yán)重問題.
??領(lǐng)先的跨平臺結(jié)構(gòu)化數(shù)據(jù)表示是JSON [JSON]和協(xié)議緩沖區(qū),也稱為protobuf [protobuf]会涎。JSON是由
Douglas Crockford用于瀏覽器-服務(wù)器通信裹匙,協(xié)議緩沖區(qū)由谷歌設(shè)計(jì)用于在其服務(wù)器之間存儲和交換結(jié)構(gòu)化數(shù)據(jù)。盡管這些表示有時(shí)被稱為語言中立的末秃,
JSON最初是為JavaScript開發(fā)的概页,而protobuf最初是為c++開發(fā)的;這兩種表述都保留了其起源的痕跡。
??SON和protobuf之間最顯著的區(qū)別是JSON是基于文本的练慕,并且是人類可讀的惰匙,而protobuf是二進(jìn)制的技掏,而且本質(zhì)上更有效;JSON是一種專門的數(shù)據(jù)表示,而protobuf提供模式(類型)來記錄和執(zhí)行適當(dāng)?shù)挠梅ㄏ罟怼km然protobuf比JSON更有效哑梳,但是JSON對于基于文本的表示非常有效。雖然protobuf是一種二進(jìn)制表示绘盟,但它確實(shí)提供了另一種文本表示鸠真,可用于需要人類可讀性的地方(pbtxt)。
??如果您不能完全避免Java序列化龄毡,可能是因?yàn)槟谛枰倪z留系統(tǒng)上下文中工作弧哎,那么您的下一個(gè)最佳選擇就是永遠(yuǎn)不要反序列化不可信的數(shù)據(jù)。特別是稚虎,您不應(yīng)該接受來自不可信源的RMI流量撤嫩。Java的官方安全編碼指南說
“不可信數(shù)據(jù)的反序列化本質(zhì)上是危險(xiǎn)的,應(yīng)該避免蠢终⌒蛉粒”這個(gè)句子是用大的、粗體的寻拂、斜體的程奠、紅色的字體設(shè)置的,它是整個(gè)文檔中唯一得到這種處理的文本[Java-secure]祭钉。
??如果無法避免序列化瞄沙,并且不能絕對確定反序列化的數(shù)據(jù)的安全性,請使用Java9添加進(jìn)來的對象反序列化篩選
并向后移植到早期版本(Java .io. objectinputfilter)慌核。該工具允許您指定一個(gè)過濾器距境,該過濾器在反序列化數(shù)據(jù)流之前應(yīng)用于數(shù)據(jù)流。它在類粒度上運(yùn)行垮卓,允許您接受或拒絕某些類垫桂。默認(rèn)接受類并拒絕潛在危險(xiǎn)類的列表稱為黑名單;在缺省情況下拒絕類并接受假定安全的類的列表稱為白名單。比起黑名單粟按,更喜歡白名單诬滩,因?yàn)楹诿麊沃槐Wo(hù)你免受已知的威脅。一個(gè)工具叫串行白名單應(yīng)用培訓(xùn)器(SWAT)可用于為您的應(yīng)用程序自動準(zhǔn)備白名單[Schneider16]灭将。過濾工具還將保護(hù)您免受過度內(nèi)存使用和過于深入的對象圖的影響疼鸟,但它不能保護(hù)您免受如上面所示的序列化炸彈的影響。
??不幸的是庙曙,序列化在Java生態(tài)系統(tǒng)中仍然很普遍空镜。如果您正在維護(hù)一個(gè)基于Java序列化的系統(tǒng),請認(rèn)真考慮遷移到跨平臺的結(jié)構(gòu)化數(shù)據(jù)表示,盡管這可能是一項(xiàng)耗時(shí)的工作姑裂。實(shí)際上馋袜,您可能仍然需要編寫或維護(hù)一個(gè)可序列化的類。編寫一個(gè)正確舶斧、安全欣鳖、高效的可序列化類需要非常小心。本章的其余部分將提供何時(shí)以及如何進(jìn)行此操作的建議茴厉。
??總之泽台,序列化是危險(xiǎn)的,應(yīng)該避免矾缓。如果您從頭開始設(shè)計(jì)一個(gè)系統(tǒng)怀酷,可以使用跨平臺的結(jié)構(gòu)化數(shù)據(jù)表示,如JSON或protobuf嗜闻。不要反序列化不可信的數(shù)據(jù)蜕依。如果必須這樣做,請使用對象反序列化過濾琉雳,但要注意样眠,它不能保證阻止所有攻擊。避免編寫可序列化的類翠肘。如果你必須這樣做檐束,一定要非常小心。
本文寫于2019.7.23束倍,歷時(shí)1天

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末被丧,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子绪妹,更是在濱河造成了極大的恐慌甥桂,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件喂急,死亡現(xiàn)場離奇詭異格嘁,居然都是意外死亡笛求,警方通過查閱死者的電腦和手機(jī)廊移,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來探入,“玉大人狡孔,你說我怎么就攤上這事》渌裕” “怎么了苗膝?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長植旧。 經(jīng)常有香客問我辱揭,道長离唐,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任问窃,我火速辦了婚禮亥鬓,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘域庇。我一直安慰自己嵌戈,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布听皿。 她就那樣靜靜地躺著熟呛,像睡著了一般。 火紅的嫁衣襯著肌膚如雪尉姨。 梳的紋絲不亂的頭發(fā)上庵朝,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天,我揣著相機(jī)與錄音又厉,去河邊找鬼偿短。 笑死,一個(gè)胖子當(dāng)著我的面吹牛馋没,可吹牛的內(nèi)容都是我干的昔逗。 我是一名探鬼主播,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼篷朵,長吁一口氣:“原來是場噩夢啊……” “哼勾怒!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起声旺,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤笔链,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后腮猖,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體鉴扫,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年澈缺,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了坪创。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,161評論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡姐赡,死狀恐怖莱预,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情项滑,我是刑警寧澤依沮,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響危喉,放射性物質(zhì)發(fā)生泄漏宋渔。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一辜限、第九天 我趴在偏房一處隱蔽的房頂上張望傻谁。 院中可真熱鬧,春花似錦列粪、人聲如沸审磁。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽态蒂。三九已至,卻和暖如春费什,著一層夾襖步出監(jiān)牢的瞬間钾恢,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工鸳址, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留瘩蚪,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓稿黍,卻偏偏與公主長得像疹瘦,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子巡球,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評論 2 344

推薦閱讀更多精彩內(nèi)容