序列化與反序列化
序列化用途:方便於對象在網絡中的傳輸和存儲
java的反序列化
序列化就是將對象轉換為流,利於儲存和傳輸的格式
反序列化與序列化相反,將流轉換為對象
例如:json序列化、XML序列化、二進制序列化、SOAP序列化
-
序列化:
java.io.ObjectOutputStream
類中的writeObject()
該方法把對象序列化,將字節序列寫到一個目標輸出流中(.ser擴展名)
-
反序列化:
java.io.ObjectInputStream
類中的readObject()
從輸入流中讀取字節序列,再將其反序列化為對象
實現Serializable和Externalizable接口的類的對象才能被序列化。
漏洞危害
導致代碼執行、文件操作、執行數據庫操作等不可控后果
漏洞原理
如果Java應用對用戶輸入,即不可信數據做了反序列化處理,那么攻擊者可以通過構造惡意輸入,讓反序列化產生非預期的對象,非預期的對象在產生過程中就有可能帶來任意代碼執行。
漏洞發現
存在於 WebLogic、WebSphere、JBoss、Jenkins、OpenNMS 等等
- HTTP請求中的參數,cookies以及Parameters。
- RMI協議,被廣泛使用的RMI協議完全基於序列化
- JMX 同樣用於處理序列化對象
- 自定義協議 用來接收與發送原始的java對象
漏洞挖掘
-
確定反序列化輸入點
首先應找出readObject方法調用,在找到之后進行下一步的注入操作。一般可以通過以下方法進行查找:-
源碼審計:尋找可以利用的“靶點”,即確定調用反序列化函數readObject的調用地點。
-
對該應用進行網絡行為抓包,尋找序列化數據,如wireshark,tcpdump等
黑盒流量分析(可能面試)
在Java反序列化傳送的包中,一般有兩種傳送方式,在TCP報文中,一般二進制流方式傳輸,在HTTP報文中,則大多以base64傳輸。因而在流量中有一些特征:
(1)TCP:必有aced0005,這個16進制流基本上也意味者java反序列化的開始;
(2)HTTP:必有rO0AB,其實這就是aced0005的base64編碼的結果;
以上意味着存在Java反序列化,可嘗試構造payload進行攻擊。
黑盒java的RMI
RMI是java的一種遠程對象(類)調用的服務端,默認於
1099
端口,基予socket通信,該通信實現遠程調用完全基於序列化以及反序列化。白盒代碼審計
(1)觀察實現了Serializable接口的類是否存在問題。
(2)觀察重寫了readObject方法的函數邏輯是否存在問題。
-
-
再考察應用的Class Path中是否包含Apache Commons Collections庫
-
生成反序列化的payload
-
提交我們的payload數據
漏洞防御
-
類的白名單校驗機制:
實際上原理很簡單,就是對所有傳入的反序列化對象,在反序列化過程開始前,對類型名稱做一個檢查,不符合白名單的類不進行反序列化操作。很顯然,這個白名單肯定是不存在Runtime的。
-
禁止JVM執行外部命令Runtime.exec
這個措施可以通過擴展 SecurityManager 可以實現。