張 晨
(廈門(mén)軟件職業(yè)技術(shù)學(xué)院 軟件工程系,福建 廈門(mén) 361024)
關(guān)鍵字:網(wǎng)絡(luò)安全 漏洞分析 Web安全 Java反序列化
Java Web是用Java技術(shù)來(lái)解決相關(guān)web互聯(lián)網(wǎng)領(lǐng)域的技術(shù)棧[1],其在Web技術(shù)的基礎(chǔ)上融合了Java語(yǔ)言的優(yōu)勢(shì)特點(diǎn),是目前大型企業(yè)或者政府部門(mén)進(jìn)行Web系統(tǒng)開(kāi)發(fā)的主流方式。在互聯(lián)網(wǎng)發(fā)展浪潮的背景下,Java Web以簡(jiǎn)單易用的特點(diǎn)成為互聯(lián)網(wǎng)不可或缺的重要功能載體,但隨之而來(lái)的相關(guān)網(wǎng)絡(luò)安全問(wèn)題成為了不得不面對(duì)的難題,根據(jù)Akamai的通報(bào),每年針對(duì)Web應(yīng)用程序的攻擊數(shù)量居高不下,網(wǎng)絡(luò)攻擊的手段也呈現(xiàn)出了多樣化的情況,其中不安全的反序列化、開(kāi)源組件風(fēng)險(xiǎn)、SQL注入漏洞、XSS漏洞是產(chǎn)生網(wǎng)絡(luò)安全威脅的主要因素。在OWASP(開(kāi)放式Web應(yīng)用程序安全項(xiàng)目)組織發(fā)布的2021年全球十大Web應(yīng)用安全中[2],不安全設(shè)計(jì)(Insecure Design)和自帶缺陷和過(guò)時(shí)的組件(Vulnerable and Outdated Components)榜上有名。
不存在完美的編程語(yǔ)言,并且任何系統(tǒng)和應(yīng)用的安全性都不是絕對(duì)的,Java Web程序的安全問(wèn)題也是不可避免的,一些看似合理的功能邏輯卻常常有可能存在著可被非法利用的漏洞,如Java的反序列化機(jī)制所引發(fā)的反序列化漏洞問(wèn)題。
Java序列化和反序列化的初衷是為了有效實(shí)現(xiàn)對(duì)象在不同系統(tǒng)和進(jìn)程之間的數(shù)據(jù)快速傳輸和方便存儲(chǔ)[3]。為了滿(mǎn)足java的序列化與反序列化的需求,在開(kāi)發(fā)過(guò)程中通常需要使用到一些公共庫(kù),Apache Commons Collections 便是其中之一,該庫(kù)不僅能夠提供數(shù)據(jù)結(jié)構(gòu)類(lèi)型還包含了許多jar工具和接口。作為Apache開(kāi)源項(xiàng)目的重要組件,Commons Collections已被廣泛應(yīng)用于各種Java Web應(yīng)用的開(kāi)發(fā),據(jù)國(guó)家網(wǎng)絡(luò)安全漏洞共享平臺(tái)(CNVD)收錄的Apache Commons Components Invoker Transformer反序列化任意代碼執(zhí)行高危漏洞(編號(hào)為CNVD-2015-07556)顯示[4],代碼設(shè)計(jì)或自帶缺陷以及陳舊的組件將導(dǎo)致反序列化漏洞的存在,相關(guān)漏洞影響到了WebLogic、JBoss、Jenkins、WebSphere、OpenNMS等諸多Web應(yīng)用和中間件。雖然Apache Commons Collections不斷推陳出新,各大應(yīng)用廠(chǎng)商也陸續(xù)發(fā)布升級(jí)補(bǔ)丁,但網(wǎng)絡(luò)上還有很多Web站點(diǎn)和應(yīng)用受到此漏洞的影響。
反序列化漏洞的本質(zhì)是一種對(duì)象化注入漏洞,常常會(huì)被非法利用于代碼復(fù)用攻擊。分析Java Web序列化與反序列化的機(jī)制:首先序列化的過(guò)程是將對(duì)象轉(zhuǎn)換成包含該對(duì)象的數(shù)據(jù)、類(lèi)型等狀態(tài)信息的字節(jié)序列用來(lái)進(jìn)行數(shù)據(jù)的傳輸和存儲(chǔ),即通過(guò)ObjectOutputStream類(lèi)的writeObject()方法對(duì)參數(shù)指定的對(duì)象序列化的數(shù)據(jù)寫(xiě)入到一個(gè)目標(biāo)輸出流之中。而后再利用反序列化這一逆過(guò)程,通過(guò)ObjectInputStream類(lèi)的readObject()方法從一個(gè)源輸入流中讀取字節(jié)序列,并還原轉(zhuǎn)換成為對(duì)象。通常,序列化后的對(duì)象可以通過(guò)反序列化方法在其他平臺(tái)上利用對(duì)象的類(lèi)型信息、數(shù)據(jù)、數(shù)據(jù)類(lèi)型在內(nèi)存中完成對(duì)象的新建。反序列化適用于Java Web下的大量應(yīng)用場(chǎng)景,例如在Web服務(wù)器的物理硬盤(pán)中暫存用戶(hù)訪(fǎng)問(wèn)的Session對(duì)象,保證用戶(hù)信息不丟失,并有效騰挪服務(wù)器的內(nèi)存資源來(lái)提高相關(guān)業(yè)務(wù)的可用性。
Java的序列化和反序列化設(shè)計(jì)的初衷并不存在問(wèn)題,但如果存在代碼設(shè)計(jì)缺陷,例如ObjectInputStream類(lèi)的readObject()方法內(nèi)的代碼邏輯缺陷,則可能會(huì)存在反序列化漏洞。當(dāng)被非法利用時(shí),惡意構(gòu)造的數(shù)據(jù)被植入到了反序列化進(jìn)程,而后又由于類(lèi)庫(kù)未對(duì)序列化對(duì)象作相關(guān)的檢查或限制,就將導(dǎo)致沒(méi)有經(jīng)過(guò)檢測(cè)而產(chǎn)生的對(duì)象執(zhí)行任意非法的RCE(Remote command/Code execute,遠(yuǎn)程命令/代碼執(zhí)行)代碼,從而出現(xiàn)各種危害系統(tǒng)的操作被執(zhí)行的情況。Apache Commons Collections組件漏洞的問(wèn)題主要出現(xiàn)在org.apache.commons.collections.Transformer接口上,產(chǎn)生的根本原因在于對(duì)數(shù)據(jù)缺乏檢測(cè)與過(guò)濾的機(jī)制,這就造成在進(jìn)行反序列化操作時(shí)不會(huì)調(diào)用構(gòu)造函數(shù)對(duì)生成對(duì)象的類(lèi)型進(jìn)行檢測(cè)與校驗(yàn)的結(jié)果。并且組件中的特殊接口類(lèi)InvokerTransformer可以調(diào)用Java的反射機(jī)制來(lái)執(zhí)行一些函數(shù)函數(shù)或特定的命令以及SQL語(yǔ)句等。Java反序列化漏洞廣泛存在于Java Web中,只要包含了Commons Collections的jar包,無(wú)論源碼是否使用到了組件中的類(lèi),都存在遠(yuǎn)程代碼被執(zhí)行的風(fēng)險(xiǎn)。
以Commons Collections6為例(以下簡(jiǎn)稱(chēng)CC6)對(duì)Java Web反序列化利用鏈進(jìn)行分析:CC6的命令執(zhí)行載體為org.apache.commons. collections. functors.ChainedTransformer函數(shù),反序列化對(duì)象為HashMap,反序列化集合載體為HashSet。如圖1所示為漏洞的利用鏈,CC6利用鏈?zhǔn)抢肏ashSet來(lái)觸發(fā)LazyMap的get方法,即HashSet.readObject()完成元素的反序列化后,會(huì)調(diào)用HashMap.put()將結(jié)果放進(jìn)去,當(dāng)通過(guò) TiedMapEntry.hashCode()計(jì)算hash時(shí),會(huì)調(diào)用getValue()觸發(fā)LazyMap.get(),從而導(dǎo)致相關(guān)目標(biāo)命令的執(zhí)行。
圖1 CC6的利用鏈
由于反序列化漏洞都需要用到程序中存在的已知類(lèi),因此查找存在安全漏洞的類(lèi)很重要。反序列化代碼審計(jì)需要從Java Web應(yīng)用的本身以及應(yīng)用與Web服務(wù)器之間的組件所涉及到的序列化對(duì)象入手檢查,要定位出應(yīng)用的源碼中哪些是調(diào)用了反序列化函數(shù)的代碼。同時(shí),序列化內(nèi)容都需要遵從序列化協(xié)議,分析反序列數(shù)據(jù)特征,Java序列化后的數(shù)據(jù)包開(kāi)頭部分通常是一個(gè)雙字節(jié)的魔法數(shù)字0xACED。定位的過(guò)程可以使用Wireshark等工具對(duì)數(shù)據(jù)包進(jìn)行分析,查看數(shù)據(jù)包是否包含以“AC ED 00 05”標(biāo)記開(kāi)頭的序列化數(shù)據(jù),再進(jìn)一步審計(jì)目標(biāo)應(yīng)用Class Path中的Apache Commons Collections庫(kù)相關(guān)代碼[5]。
通常一個(gè)完整的漏洞包括已知原生反序列化源方法(source)和觸發(fā)漏洞的目標(biāo)方法(sink)的鏈?zhǔn)秸{(diào)用。source作為引入點(diǎn)可能會(huì)獲取外部不可信的輸入數(shù)據(jù)并返回,再通過(guò)遞歸檢查尋找一條調(diào)用鏈(gadget)進(jìn)行傳播,最后在目標(biāo)sink觸發(fā)執(zhí)行。代碼審計(jì)分析的過(guò)程需要判斷在sources和sinks之間是否存在一條可達(dá)的利用路徑。Java Web反序列化漏洞利用的常常是在目標(biāo)Web應(yīng)用中找到一個(gè)可接收外部輸入的序列化對(duì)象的反序列化接收點(diǎn),再利用反序列化的payload針對(duì)目標(biāo)應(yīng)用進(jìn)行注入,來(lái)觸發(fā)ObjectInputStream 的反序列化操作,并通過(guò)反射調(diào)用RunTime.exec從而實(shí)現(xiàn)對(duì)漏洞的利用。因此Java Web的代碼審計(jì)要先檢查找到HashSet.readObject、Fastjson等反序列化入口,再探尋調(diào)用鏈,從而找到LazyMap.get()、Runtime.exec等觸發(fā)漏洞的目標(biāo)方法。
如表1和表2所示為序列化和反序列化函數(shù)的使用實(shí)例:從“user.bin”二進(jìn)制文件中讀取數(shù)據(jù),并對(duì)其進(jìn)行反序列化。在該實(shí)例中如果未設(shè)置檢查和過(guò)濾機(jī)制,并且“user.bin”的文件內(nèi)容是用戶(hù)可控的,即用戶(hù)可以修改內(nèi)容的輸入,那么可能會(huì)存在反序列化漏洞。
表1 序列化serialization函數(shù)使用實(shí)例
表2 反序列化unserialization函數(shù)使用實(shí)例
反序列化的一系列的變換操作,是通過(guò)定義一個(gè)ChainedTransformer來(lái)實(shí)現(xiàn)的。對(duì)commons collections中利用的類(lèi)進(jìn)行分析,在該組件中有一個(gè)Transformer接口。通過(guò)傳入一個(gè)Transformer數(shù)組即可定義一個(gè)ChainedTransformer來(lái)實(shí)現(xiàn)一系列的變換操作。表3為漏洞利用代碼,commons collections組件中InvokerTransformer是實(shí)現(xiàn)Transformer接口的類(lèi)。RunTime類(lèi)常用于調(diào)用外部程序,將可能被用于執(zhí)行RCE。要找到調(diào)用了Transform方法的節(jié)點(diǎn),可以通過(guò)ReadObject入手,再順著利用鏈一步步分析定位。
表3 CC6的利用示例
網(wǎng)絡(luò)安全漏洞難以避免,采用安全技術(shù)手段也無(wú)法將其完全清除,但是使用合理有效的防范方法能夠降低網(wǎng)絡(luò)安全風(fēng)險(xiǎn),保證Web互聯(lián)網(wǎng)程序更加正常和穩(wěn)定的運(yùn)行[6]。針對(duì)Java Web的網(wǎng)絡(luò)安全問(wèn)題,應(yīng)當(dāng)在站點(diǎn)和程序的規(guī)劃設(shè)計(jì)階段就將各種可能產(chǎn)生漏洞的因素考慮進(jìn)去,在開(kāi)發(fā)階段和后期維護(hù)階段還要不斷進(jìn)行代碼審計(jì)、測(cè)試驗(yàn)證。做到以下幾點(diǎn)來(lái)保證客戶(hù)端和服務(wù)端的安全:
在站點(diǎn)程序設(shè)計(jì)、開(kāi)發(fā)建設(shè)階段和后期的維護(hù)過(guò)程都需要分析Java Web反序列化漏洞具體形成原因,有針對(duì)性地關(guān)注具體應(yīng)用中的可序列化類(lèi),開(kāi)展相關(guān)應(yīng)用的安全性檢查,通過(guò)代碼審計(jì)和行為分析等手段發(fā)現(xiàn)站點(diǎn)漏洞所在的靶點(diǎn)[7]。需要關(guān)注相關(guān)廠(chǎng)家官方的補(bǔ)丁發(fā)布情況及時(shí)進(jìn)行升級(jí),定期對(duì)站點(diǎn)的基礎(chǔ)庫(kù)進(jìn)行安全性檢查。定期采用白盒與黑盒相結(jié)合的方式進(jìn)行站點(diǎn)漏洞測(cè)試,對(duì)程序執(zhí)行動(dòng)態(tài)檢測(cè),通過(guò)動(dòng)態(tài)檢測(cè)對(duì)運(yùn)行的程序進(jìn)行網(wǎng)絡(luò)安全測(cè)試,再對(duì)比靜態(tài)分析結(jié)果可以進(jìn)一步確認(rèn)漏洞點(diǎn),并且還可以發(fā)現(xiàn)其他潛在的威脅漏洞。加強(qiáng)對(duì)Runtime.exec等相關(guān)代碼的檢測(cè),并對(duì)存在風(fēng)險(xiǎn)的應(yīng)用及時(shí)進(jìn)行代碼安全加固。
做好文件、接口、協(xié)議等細(xì)節(jié)問(wèn)題的優(yōu)化,在保證功能和業(yè)務(wù)正常運(yùn)行的前提下,刪除存在風(fēng)險(xiǎn)的文件、停用非必要的接口,如禁止JVM執(zhí)行外部命令和程序。關(guān)注敏感信息的加密,確保對(duì)象的成員變量符合正確的約束條件。對(duì)于HTTP請(qǐng)求中的cookies、Parameters和RMI遠(yuǎn)程調(diào)用接口、JMX擴(kuò)展接口等基于序列化操作的接口及協(xié)議開(kāi)展監(jiān)測(cè)。合理并有效使用加密功能進(jìn)行加密存儲(chǔ)。設(shè)計(jì)嚴(yán)格的訪(fǎng)問(wèn)和認(rèn)證的機(jī)制,利用數(shù)字簽名、數(shù)字證書(shū)等方式完成身份認(rèn)證,防止程序代碼的泄露及不合法的程序復(fù)制。反序列化漏洞被利用時(shí),通常攻擊者會(huì)通過(guò)如文件上傳、SQL注入、XSS利用等手段上傳一個(gè)webshell來(lái)進(jìn)一步入侵系統(tǒng),從而達(dá)到遠(yuǎn)程執(zhí)行命令、操作敏感信息的目的,因此要加強(qiáng)系統(tǒng)入侵檢測(cè)。另外,還可以利用蜜罐系統(tǒng),來(lái)偵測(cè)異常行為和隱藏真實(shí)的程序系統(tǒng)。
全球的網(wǎng)絡(luò)安全技術(shù)一直在不斷的變化和發(fā)展,網(wǎng)絡(luò)攻擊的發(fā)起者與系統(tǒng)開(kāi)發(fā)者以及網(wǎng)絡(luò)安全防御者也始終處于彼此博弈的狀態(tài)之中。作為系統(tǒng)開(kāi)發(fā)和維護(hù)人員不能僅僅將目光局限在系統(tǒng)的開(kāi)發(fā)和功能需求的實(shí)現(xiàn)上,在網(wǎng)絡(luò)安全已上升到國(guó)家高度的背景下,更需要加強(qiáng)網(wǎng)絡(luò)安全知識(shí)的學(xué)習(xí),及時(shí)關(guān)注全球網(wǎng)絡(luò)安全態(tài)勢(shì)、了解最新的網(wǎng)絡(luò)安全事件和主要的網(wǎng)絡(luò)攻擊手段,不斷精進(jìn)開(kāi)發(fā)技術(shù)。圍繞Java Web站點(diǎn)的開(kāi)發(fā)工作,從系統(tǒng)功能、網(wǎng)絡(luò)安全等多角度來(lái)分析、完善和提升相關(guān)程序的安全防御性能,保障網(wǎng)絡(luò)安全。
信息化時(shí)代,互聯(lián)網(wǎng)數(shù)據(jù)呈現(xiàn)爆炸式的增長(zhǎng),隨著《個(gè)人信息保護(hù)法》的施行,對(duì)于互聯(lián)網(wǎng)個(gè)人信息的保護(hù)也上升到了一個(gè)新的高度。在信息全球化發(fā)展的背景下,網(wǎng)絡(luò)黑客無(wú)處不在,因應(yīng)用系統(tǒng)存在漏洞,而造成個(gè)人信息泄露或經(jīng)濟(jì)損失等事件層出不窮。反序列化的漏洞存在于許多編程語(yǔ)言之中,是近些年出現(xiàn)較為頻繁的高危漏洞之一,也成為應(yīng)用安全研究的熱點(diǎn)之一。在Java Web中由于 Apache Commons Collections庫(kù)組件的廣泛使用加上該組件未能對(duì)用戶(hù)數(shù)據(jù)做出有效過(guò)濾,導(dǎo)致攻擊者可以在對(duì)象屬性中構(gòu)造惡意代碼進(jìn)而控制服務(wù)器[8]?;诖?,本文對(duì)序列化和反序列化的過(guò)程展開(kāi)分析,通過(guò)對(duì)Java Web反序列化漏洞形成原因及利用原理的研究,提出反序列代碼審計(jì)和安全檢查的的基本思路以及漏洞的防范方法,以幫助開(kāi)發(fā)和運(yùn)維人員提升相關(guān)程序的安全性,提高業(yè)務(wù)系統(tǒng)的防護(hù)水平。
四川職業(yè)技術(shù)學(xué)院學(xué)報(bào)2022年5期