近日,2015年最為被低估的,具有巨大破壞力的漏洞浮出水面。在FoxGlove Security安全團(tuán)隊(duì)的@breenmachine 發(fā)布一篇博客中介紹了該漏洞在最新版的WebLogic、WebSphere、JBoss、Jenkins、OpenNMS中的應(yīng)用,實(shí)現(xiàn)遠(yuǎn)程代碼執(zhí)行。更為嚴(yán)重的是,在漏洞被發(fā)現(xiàn)的9個(gè)月后依然沒有有效的java庫補(bǔ)丁來針對(duì)受到影響的產(chǎn)品進(jìn)行加固?,F(xiàn)在,讓我們探討下該漏洞的原理以及應(yīng)用。
背景:
java反序列化漏洞
java反序列化漏洞是一類被廣泛應(yīng)用的漏洞,絕大多數(shù)的編程語言都會(huì)提供內(nèi)建方法使用戶可以將自身應(yīng)用所產(chǎn)生的數(shù)據(jù)存入硬盤或通過網(wǎng)絡(luò)傳輸出去。這種將應(yīng)用數(shù)據(jù)轉(zhuǎn)化為其他格式的過程稱之為序列化,而將讀取序列化數(shù)據(jù)的過程稱之為反序列化。
當(dāng)應(yīng)用代碼從用戶接受序列化數(shù)據(jù)并試圖反序列化改數(shù)據(jù)進(jìn)行下一步處理時(shí)會(huì)產(chǎn)生反序列化漏洞。該漏洞在不同的語言環(huán)境下會(huì)導(dǎo)致多種結(jié)果,但最有危害性的,也是之后我們即將討論的是遠(yuǎn)程代碼注入。
2.java反序列化漏洞發(fā)現(xiàn)歷程
在最近幾年間,不斷的有java反序列化漏洞被曝光。最近的幾次分別產(chǎn)生于spring框架以及Groovy還有文件上傳的java庫中,這些漏洞均得到了修復(fù)。
但在最近的研究中,安全人員發(fā)現(xiàn)java反序列漏洞遠(yuǎn)遠(yuǎn)不止上述幾處,該漏洞廣泛的存在于java庫中。
Java反序列化漏洞:
漏洞產(chǎn)生原因:
在java編寫的web應(yīng)用與web服務(wù)器間java通常會(huì)發(fā)送大量的序列化對(duì)象例如以下場景:
HTTP請(qǐng)求中的參數(shù),cookies以及Parameters。
RMI協(xié)議,被廣泛使用的RMI協(xié)議完全基于序列化
JMX 同樣用于處理序列化對(duì)象
自定義協(xié)議 用來接收與發(fā)送原始的java對(duì)象
在序列化過程中會(huì)使用ObjectOutputStream類的writeObject()方法,在接收數(shù)據(jù)后一般又會(huì)采用ObjectInputStream類的readObject()方法進(jìn)行反序列化讀取數(shù)據(jù)。其代碼示例如下:
▲
結(jié)果如圖:
▲
上述代碼中的java類ObjectInputStream在執(zhí)行反序列化時(shí)并不會(huì)對(duì)自身的輸入進(jìn)行檢查,意味著一種可能性,即惡意攻擊者構(gòu)建特定的輸入,在ObjectInputStream類反序列化之后會(huì)產(chǎn)生非正常結(jié)果。而根據(jù)最新的研究,利用這一方法可以實(shí)現(xiàn)遠(yuǎn)程執(zhí)行任意代碼。
為了進(jìn)一步說明,可以針對(duì)對(duì)上述代碼進(jìn)行了一點(diǎn)修改:
▲
結(jié)果:
▲
主要修改為自定義了一個(gè)被序列化的對(duì)象myobject,通過定義myobject實(shí)現(xiàn)了java序列化的接口并且定義了一種名為“readObject”的方法。通過對(duì)比上面例子的輸出,可以發(fā)現(xiàn)反序列化的相關(guān)數(shù)值被修改了,即執(zhí)行的用戶自身的代碼。造成結(jié)果不同的關(guān)鍵在于readObject方法,java在讀取序列化對(duì)象的時(shí)候會(huì)先查找用戶自定義的readObject是否存在,如果存在則執(zhí)行用戶自定義的方法。
2 漏洞觸發(fā)點(diǎn)尋找:
在之前的論述中可以發(fā)現(xiàn)利用該漏洞首先應(yīng)找出readObject方法調(diào)用,在找到之后進(jìn)行下一步的注入操作。一般可以通過以下方法進(jìn)行查找:
(1)針對(duì)特定的java應(yīng)用,對(duì)此漏洞的應(yīng)用應(yīng)首先尋找可以利用的“靶點(diǎn)”,即確定調(diào)用反序列化函數(shù)的地點(diǎn)。這可以通過對(duì)java應(yīng)用進(jìn)行源碼審計(jì),例如找尋反序列化函數(shù)readObject調(diào)用情況。
(2)對(duì)于該應(yīng)用的網(wǎng)絡(luò)行為進(jìn)行抓包,尋找序列化數(shù)據(jù)(在包數(shù)據(jù)中,序列化數(shù)據(jù)一般會(huì)以ac ed 00 05開頭)來進(jìn)行判斷。
3.漏洞利用
在發(fā)現(xiàn)序列化數(shù)據(jù)之后,需要產(chǎn)生一個(gè)用于測試的pyload。這里可以在github上下載一個(gè)工具“ysoserial”并執(zhí)行下列指令:
▲
當(dāng)/ tmp / pwned文件被創(chuàng)建時(shí)說明測試已經(jīng)開始,而后續(xù)的步驟將結(jié)合實(shí)例一起分析。
漏洞利用實(shí)例:
這里以Jboss為例,Jboss利用的是HTTP協(xié)議,可以在任何端口上運(yùn)行,默認(rèn)安裝在8080端口中。而且Jboss與“JMXInvokerServlet”的通信過程中存在一個(gè)公開漏洞。JMX是一個(gè)java的管理協(xié)議,在Jboss中的JMXInvokerServlet可以使用HTTP協(xié)議與其進(jìn)行通話。這一通信功能依賴于java的序列化類。
在默認(rèn)安裝的Jboss中,JMXInvokerServlet的路徑恰好為http://localhost:8080/invoker/JMXInvokerServlet。如果用戶訪問一個(gè)web瀏覽器,實(shí)際上會(huì)返回一個(gè)原始的java對(duì)象,這中行為顯然存在一個(gè)漏洞。
這個(gè)漏洞可以很經(jīng)常的通過互聯(lián)網(wǎng)被利用,由于jmxinvokerservlet與主要的Web應(yīng)用程序在同一個(gè)端口上運(yùn)行,因此它很少被防火墻所攔截。
基于以上原理可以通過以下指令收集jar文件來測試該漏洞是否可用:
由此可以以jmx作為Jboss接受外部輸入的點(diǎn),可以利用java HTTP client包構(gòu)建POST請(qǐng)求,post請(qǐng)求包中數(shù)據(jù)為使用ysoserial處理之后的構(gòu)建代碼。