關於Java解序列化

來源:互聯網
上載者:User

本文是IBM developerWorks中的一篇文章,介紹了不使用加密與簽章技術,如何防止對不可信資料輸入的解序列化。(2013.01.18最後更新)

Java序列化允許開發人員將Java對象儲存為二進位格式,以便將該對象持久化到一個檔案中或將其在網路中進行傳遞。遠程方法調用(RMI)使用序列化作為用戶端與伺服器端之間的通訊媒介。當服務從用戶端接收位元據,以及將輸入的資料進行解序列化去構造Java執行個體時,就會產生多種安全問題。本文關注其中一種問題:駭客可能序列化另一個類的執行個體,並將其傳給服務程式。那麼服務程式就會解序列化該惡意對象,並很可能將該對象強制轉換為服務所期望得到的合法類型,而這將導致異常的發生。然而,該異常對於確保資料安全性則顯得太晚了。本文解釋了為什麼要以及怎樣去實現一種安全的序列化。

脆弱的類

你的服務程式不可能還原序列化任意類的對象。為什麼不能呢?簡單的回答是:因為在伺服器端的類路徑中可能存有被駭客利用的脆弱類。這些類所包含的代碼為駭客造就了拒絕服務(DOS)的條件,或者--在極端情況下--會允許駭客注入任意代碼。

你可能會相信存在這種攻擊的可能性,但考慮到一個典型的伺服器端程式的類路徑中存在太多的類,不僅包含你自己的代碼,還包括Java核心類庫,第三方的類庫,以及其它的中介軟體或架構中的類庫。另外,在應用程式的生命週期中,類路徑可能會被改變,或者為了應對底層運行環境的變化,應用程式的類路徑也可能被修改。當試圖去利用這樣的弱點時,通過傳送多個序列化對象,駭客能夠將這些操作組合到一塊。

我應該強調一下,僅當滿足如下條件時,服務才會解序列化一個惡意對象:

1. 惡意對象的類存在於伺服器端的類路徑中。駭客不可能隨便地傳遞任意類的序列化對象,因為應用服務可能無法載入這個類。

2. 惡意對象的類要麼是可序列化的,要麼是可外部化的。(即,伺服器端的這個類要實現java.io.Serializable或java.io.Externalizable)

另外,通過從序列化流中直接複製資料,在不調用構造器的情況下,解序列化操作就能產生對象樹,所以駭客不可能執行序列化對象類的構造器中的Java代碼。

但駭客還有其它途徑在伺服器端去執行代碼。無論JVM在何時去解序列化一個對象,都將實現如下三個方法中的一個,都將調用並執行該方法中的代碼:

1. 方法readObject(),當標準的序列化機制不適用時,開發人員一般就會用到該方法。例如,當需要對transient成員變數進行賦值時。

2. 方法readResolve(),一般用於序列化單例對象。

3. 方法readExternal(),用於外部化對象。

所以,如果在你的類路徑中存在著使用上述方法的類,你就必須意識到駭客可能會在遠程調用這些方法。此類攻擊在過往曾被用於破壞Applet安全沙箱;同樣地,相同的攻擊技術也可用於伺服器端應用。

繼續讀下去,將會看到如何才能只允許應用服務對其期望的類的對象進行解序列化。

Java序列化二進位格式

一個對象被序列化之後,位元據將包含有中繼資料(指與資料的結構相關的資訊,例如類的名稱,成員的數量,以及成員的類型),及對象資料本身。我將以一個簡單的Bicycle類作為例子,如清單1所示,該類包含三個成員變數(id,name和nbrWheels)以及與之對應的set與get方法。

清單1. Bicycle類

package com.ibm.ba.scg.LookAheadDeserializer;    public class Bicycle implements java.io.Serializable {        private static final long serialVersionUID = 5754104541168320730L;        private int id;    private String name;    private int nbrWheels;        public Bicycle(int id, String name, int nbrWheels) {        this.id = id;        this.name = name;        this.nbrWheels = nbrWheels;    }        public String getName() {        return name;    }        public void setName(String name) {        this.name = name;    }        public void setId(int id) {        this.id = id;    }        public int getId() {        return id;    }        public int getNbrWheels() {        return nbrWheels;    }        public void setNbrWheels(int nbrWheels) {        this.nbrWheels = nbrWheels;    }}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.