看雪編輯按:隨著REST
API的流行,Json的使用也越來越多,但是其中存在的安全問題卻不容忽視,特別是由於反序列化導致的遠端程式碼執行更是威力十足。雖然此類漏洞出來已有一段時間了,並且前期的一些防禦方案也隨著時間的推移不再有效,但其傳播仍然很廣泛。在此次看雪峰會演講中,綠盟科技網路安全攻防實驗室安全研究員廖新喜為大家闡述了由Java
Json庫的反序列化特性導致的RCE,議題內容涉及Gson,Jackson和Fastjson這三個最常用的Json庫的序列化和反序列化討論,並分析了這裡面的安全機制,再從安全機制上發現其潛在的安全漏洞。另外,講師還公佈了部分未公開的反序列化payload。
以下內容為廖新喜演講實錄,由看雪學院(微信公眾號:ikanxue)整理。
廖新喜
廖新喜(xxlegend),綠盟科技網路安全攻防實驗室安全研究員,擅長程式碼審計,Web漏洞挖掘,擁有豐富的程式碼審計經驗,曾在Pycon
2015
China大會上分享Python安全編碼。安全行業從業六年,做過三年開發,先後擔任綠盟科技極光掃描器的開發和開發代表。目前專注於Web漏洞挖掘、Java反序列化漏洞挖掘。曾向RedHat、Apache、Amazon和Oracle提交多份漏洞報告。2016年網路安全周接受央視專訪。《誰動了我的VIP賬號?》
廖新喜:這兩年這個影響非常廣,主持人也介紹了。我主要講java json,也講到Java防禦。我來自綠盟科技,我叫廖新喜。首先介紹一下json,再介紹一下json安全特性,接著會介紹一下Fastjson,還會介紹一下Java反序列化防禦。
主流 JSON 庫
json是什麼東西,就是一個大的結構,有一些鍵值。
Gson是谷歌公司釋出的一個開原始碼的json庫。這是GSON的事例,講一個物件轉化為JSON,有這樣一個字串。將這個物件轉換為這個字串。
Fastjson是由阿里巴巴開發,號稱速度非常快。這是一個事例。
JSON 安全特性
再看一下它的安全特性,首先我們看一下GSON,主要是用了預設的建構函式,如果沒有找到的話會呼叫sun.misc.Unsafe生成一個例項,如果這個之內就需要程式設計師自己實現,需要這個基本型別就是需要反射執行呼叫,這一塊應該不存在安全問題的,也是推薦使用的。
jackson的安全特性,無參預設構造方法,不會序列化非Public屬性。這一塊其實還有很多繞過,我們看一下Jackson階層,序列化和反序列化非常相似,也需要一個無參的預設方法,也有Jackson特有的屬性,它也有一個@type可以開啟序列化以及反序列化的結構。
我們可以看一下json的階層,這個階層提供的方法就是parserconfig,主要儲存這個Java一些配置,我們可以看到他在實現由javabean等等。還有parserconfig實現這個解析上下文,這就用到反序列化,反序列化實現又有幾部分,我們主要應用這個Javabean。
Fastjson PoC
Fastjson PoC,一個是基於Templatelmpl,還有基於JNDI。
簡單解說一下一些方法來觸發,field型別是不需要的,也在那個上面放了一個Demo。構造一個Templatelmpl,各個方法裡面我們實現了一個計算器,複寫幾個方法,看一下PoC,主要是前面加入了黑名單。
這些輔助程式碼,如果這些輔助程式碼不會觸發,從這個情況下可以觸發我們的惡意情況。如果說你解析的時候比如說呼叫fastjson,需要開啟……(英文),這個其他下可以觸發我們的漏洞。
為什麼會觸發,就涉及到fastjson會呼叫…首先我的這個應用調層Fastjson會實體化,會呼叫slmpl的方法,或者開啟了之後就不需要了,最後會呼叫json方法。
這是整個呼叫棧,這個呼叫棧還是挺簡單的。
基於JNDI,之前的時候也講到了,對於json這一塊沒有想到還會可以利用起來,可以看到JNDI是什麼東西,是提供兩種基本方法,我們可以看一下它的圖,JNDI提供一個外部介面,主要是包括MI或者IDE。如果那個裡面內容是我們可以控制的,直接可以切入。比如說可以切換引數,比如說切換我們自己控制的途徑,切換到SDP自己控制的伺服器。
RMI的這個服務端的程式碼,我會建立1099的一個服務,然後把那個放到外部伺服器裡面,通過RMI指向那個服務,指向那個STV服務,載入那個回來,會在RMI client上執行,基本上大部分都是這樣的方式。
攻擊流程:首先攻擊者準備Rmi服務和wed服務,攻擊者將Rmi絕對路徑注入Lookup方法中,受害者JNDI介面會指想空寂者控制的RMI伺服器,JNDI介面向執行建構函式,把那個載入進來進行識別化,識別化的過程中就會執行我們的惡意程式碼。
這是另外一種型別,比如說基於Field的型別,不適用setter方法,利用hashset,比如說階層這個序列化的機制觸發的,Fastjson預設處理Set型別都是通過hashset來實現,通過equals方法觸發。一般通過Pieid型別都是利用Collecton來載入的。
這是呼叫棧。
首先Pastjson,一個類別加入到會叫做hashset.add,最後跑到putval,再到這個載入的equals方法。我們認為那個抵制我們可以控制,可以遠端載入那個類別,然後來執行。這是他們的區別。這是它的調動站。
簡單來說還是很相似的,首先是parse反序列化,通過這個get的方法,然後調到Lookup再調多遠端載入的機動器。這是其他的POC。這是基於springpropertypathfactoy可以把這個載入進來。這個也是C3P0的結構。這個呼叫站,我們前面介紹的,所有的基於GDR都是類似的結構。
看完了Fastjson PoC。我們主要講這個json反序列化防禦和Java反序列化防禦,這一塊對於開發者來說是最需要的。
JSON 反序列化防禦
GSON基本無安全風險。
Jackson支援這個格式轉換。有一個方法可以在所有地方使用了,如果說替代方案是什麼,在具體類上加上jsonTypelnfo註解,這樣子類也生效,在反序列化的時候,就不存在著這樣的問題。
Fastjson不起用Autotype就沒問題。其他的json庫,因為是非主流,還是不建議使用,裡面的問題更多。
這是對於json的想法,因為現在都是堵RCE的漏洞,堵遠端程式碼執行的漏洞,但是對於DOS或者一些其他漏洞可能不是太關注,像json或者Fastjson裡面有很多的漏洞,但是沒有精力關注。像實現類和自動串以及二進位制結構會存在這樣或者那樣的風險。
Java 反序列化防禦
主要從三個方面來講:1、過時的建議。2、錯誤的建議。3、正確的建議。
這是反序列化利用時序圖,整個反序列化利用的過程。
首先我們解釋一下Java應用,這一塊就會實現類的實現化。像我們現在的主流機制,阻止這種方案都是在這一塊實行的,其實他有很多這樣的介面,這個介面的話還包括resolveproxyclas。據說很多介面都會利用到那個一些介面,很多方法都會利用到。這個時候就返回,返回之後強制轉換,這個時候其實相對來說已經過時了。因為前面已經去完成了我的反序列化了。最後,會有一個垃圾回收機制。
我們也可以看到Gadget還是非常多的,如果要防禦的話怎麼防禦呢?首先是在實地化之前可能把類別阻攔,另外實地化之後,如果說這個Gadget是第三方庫要以來依賴於,把這個一些方法之前加上白名單或者黑名單的控制,這樣可以實現第三方庫以及自己一些黑名單的控制,這是整個反序列化利用過程主流方案,目前也是如此。
過時的建議都是我從網上抄下來的,這個過時的建議當時是2015年,現在有兩年多的時間了,大家當時都是按照這樣方法做的防禦,但是這種方法現在來看是過時了。
第一種方法,使用Serialkiller替代進行序列化操作的objectinputstream類。另外,建議臨時刪除專案庫,這是我們常常用的commmons而,這是所有反序列化出現最多的,這種建議還是被大家廣泛傳播,也沒有說改變的趨勢,因為搜尋引擎都收錄了。
還有使用grep的方法把那個commons方法刪除了,我們看一下這個方法為什麼是無效的呢?因為POC出現多達29種,實在太多了。
我也跟了很多種,一起POC僅僅依賴於JDK,跟第三方沒有關係。還有一些問題,第三方庫Gadget和應用方在打架,這不是我的問題,應用方也說這不是我的問題。到底是誰的問題呢?自從這個漏洞爆發影響面非常廣了之後,大家說這是我們的問題,我們都來幹。
典型的錯誤方案:大廠的安全編碼規範,為什麼拿出來講,因為這個廠非常大,但是安全編碼規範居然是錯的,可想而知,很多人到現在沒有理解這個反序列化漏洞。
為什麼是錯的?我也是推薦通過加密實現這個反序列化的機制,但是這存在一個問題主要問題,首先是反序列化,之後再解密。解密之後再得到Gadget,也是一個反序列化的過程。在第一次反序列化的時候可能存在著問題,因為這個介面的服務不光光是開在內部,可能說我是一個服務的方式來展現了出來,這種就會存在著問題。
錯就錯在反序列在前,解密在後。首先的話要把資料解密,解密完了之後再反序列化,不然那個資料還是被控的。我也希望這個大廠看到之後把他們的程式碼規範給改了。
一些其他的建議:
不要反序列化不可信的資料,反序列建議加密、簽名,我們建議的話,加密簽名是在之前,反序列化之後,這樣反序列化的東西才不會被使用者控制。比如說緩解這個漏洞的方式,給反序列化介面新增一些認證授權,還有反序列化介面只允許艦艇在本地,沒有對外開通服務或者開通相應防火牆加控制。當然了,這些都是緩解。
目前業內主流方案,採用LOOK-AHeadObject,兩種解決方法:一種是serialkiller還有一種是coetrost Security Contrast-Ro0。基本上出現這樣一個反序列化漏洞進行更新,如果沒有跟上它的腳步,就存在著問題。
2015-2017年的時間,反序列化PoC太多了,加註了很多的黑名單進來。所以說一定要緊急更新,跟上反序列化的步伐,重新提了一下,你可以使用這個方法,但是你一定要保持隨著這個更新而更新。
實現方式,其實很簡單。前面已經介紹了,反序列化就是在resolveclass五之前進行控制,在判斷它是不是在我的黑名單裡面,如果在就直接加入到黑名單裡面。
還有一些其他的建議——我們升級第三方庫。
剛開始Gadget或者其他應用方都不承認是自己的問題,自從這個漏洞大了之後大家都說是自己的問題,然後推出相應更新機制。一個是Apache
Commens Collections,要設定一個系統引數才可以拉動,就預設存在這個漏洞。像apache Commons
Fileupload,就是預設不開啟,這些漏洞可以得到緩解,還有第三方的庫不承認是自己的問題,有沒有修改,就不提了。
還有升級JDK,它是加的一個過濾價值,在JDK86121會加入一些黑名單,把一些常用的黑名單放在裡面,你也可以新增自己的白名單,這個機制還通過MRI,就是通過的這個越權載入的問題。
完~
本演講PPT 下載:https://bbs.pediy.com/thread-223079.htm