簡體   English   中英

序列化 - 如何保護序列化 JAVA object?

[英]Serialization - How to secure a serialized JAVA object?

如果我通過 .network 發送序列化的 object,我如何保護序列化的 object? 我懷疑黑客可能會中斷/破解我的數據。

任何人都可以詳細說明如何實現這個嗎?

此演示文稿提供了有關攻擊者如何有效篡改Java序列化流的想法:

  1. https://www.owasp.org/images/e/eb/OWASP_IL_2008_Shai_Chen_PT_to_Java_Client_Server_Apps.ppt

    如果服務器的類路徑上存在易受攻擊的類,則還存在注入意外行為並注入代碼的風險。 看到這篇文章:

[Look-ahead Java反序列化] [3]

java.crypto.SealedObject正是您要找的。

您可以加密或散列它,但java序列化格式是通過網絡發送的一個很好的選擇 - 更好的解決方案是JSON / XML(加密或用一些加密算法簽名)

如前所述,請查看加密,但更具體地說,請查看用於java中網絡通信的hte SSL / TLS庫。

http://juliusdavies.ca/commons-ssl/ssl.html

當Java內置一個非常強大的庫時,無需嘗試實現安全加密通信。

在我看來,您可以使用SSLSocketSealedObject 但是,它會讓你的事情變得有點沉重。 但是,本文還介紹了其中一個選項。 http://www.ibm.com/developerworks/library/j-5things1/

您可以使用簽名對象和密封對象來保護序列化對象

我在這里的線程中添加了一個有用的資源,Oracle 的Java SE 安全編碼指南(特別是在這種情況下,指南中的第 8 節“序列化和反序列化”):

https://www.oracle.com/java/technologies/javase/seccodeguide.html#8

保護 java 中任何 object 的一個好方法是在構造函數中強制執行不變量。 例如,想象一個 class Person ,您不想允許任何 13 歲以下的人的實例化:

public class Person implements Serializable{
    private String name;
    private Integer age;

    public Person(final String name, final Integer age) {
        if(age < 13) {
            throw new IllegalArgumentException("invalid age");
        }
        this.name = name;
        this.age = age;
    }
}

但是,當您實現Serializable時,可能會編寫繞過構造函數的代碼,這應該是我們的主要防御機制,因此有可能破壞封裝:

@Test
void testEncapsulationSerialization() throws IOException, ClassNotFoundException {
    Person a = new Person("dave", 23);
    ByteArrayOutputStream boas = new ByteArrayOutputStream();
    try (ObjectOutputStream oos = new ObjectOutputStream(boas)) {
        oos.writeObject(a);
    }
    byte[] bytes = boas.toByteArray();
    bytes[237] = 12; // trick: we are modifying the array of bytes manually
    try (ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bytes))) {
        Person b = (Person) ois.readObject();
        System.out.println(a);
        System.out.println(b);
    }
}

通過這個測試,我們能夠創建一個年齡為 12 歲的Person類型的 object(這在我們的構造函數中是不允許的)。

所以在這種情況下,如果你想保護序列化,你需要重寫Person class readResolve()方法來調用你的構造函數:

private Object readResolve() throws ObjectStreamException {
    return new Person(this);
}

這樣我們將強制任何實例化都遵循構造函數中聲明的不變量。

此外,如果您有一個實現序列化的父對象 class,您可能還需要覆蓋readObject()writeObject()方法。

此外,您應該確保 object 的不變性,因為 java 的默認可擴展性不利於安全。

總而言之,我們應該避免使用Serializable (和Clonable ),因為如果我們不明確保護它們,它們都會破壞封裝。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM