1. 程式人生 > >淺談Java反序列化漏洞原理(案例未完善後續補充)

淺談Java反序列化漏洞原理(案例未完善後續補充)

序列化與反序列化

序列化用途:方便於物件在網路中的傳輸和儲存

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物件

漏洞挖掘

  1. 確定反序列化輸入點
    首先應找出readObject方法呼叫,在找到之後進行下一步的注入操作。一般可以通過以下方法進行查詢:

    1. 原始碼審計:尋找可以利用的“靶點”,即確定呼叫反序列化函式readObject的呼叫地點。

    2. 對該應用進行網路行為抓包,尋找序列化資料,如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方法的函式邏輯是否存在問題。

  2. 再考察應用的Class Path中是否包含Apache Commons Collections庫

  3. 生成反序列化的payload

  4. 提交我們的payload資料

漏洞防禦

  1. 類的白名單校驗機制:

    實際上原理很簡單,就是對所有傳入的反序列化物件,在反序列化過程開始前,對型別名稱做一個檢查,不符合白名單的類不進行反序列化操作。很顯然,這個白名單肯定是不存在Runtime的。

  2. 禁止JVM執行外部命令Runtime.exec

    這個措施可以通過擴充套件 SecurityManager 可以實現。