1

在Java中,可以通過網絡執行以下操作來發送和接收對象(不加密)。是否可以通過Man In The Middle攻擊將代碼注入通過網絡傳輸的Java對象?

class Dog { 
    public void bark(){ System.out.println("Woof! Woof!"); } 
} 

Client.java

Dog fido = new Dog(); 
Socket socket = new Socket(new InetSocketAddress("192.168.1.2"), 1234); 
ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream()); 
oos.writeObject(fido); 
oos.flush(); 
oos.close(); 

Server.java

ServerSocket server = new ServerSocket(1234); 
Socket client = server.accept(); 
ObjectInputStream ois = new ObjectInputStream(client.getInputStream()); 
Dog fido = (Dog)ois.readObject(); 
ois.close(); 

fido.bark(); 

我的問題是,假設你已經成功地建立其發送兩個網絡設備之間的攔截點Java在不安全的鏈接上來回對待,並且你知道他們的協議並且可以修改它們的數據,是否有可能將Java字節碼注入到對象中以改變它們的行爲?

在我們的小例子中,是否有可能使fido「moo!」而不是吠叫?

+1

您正在發送*數據*,而不是Java *代碼*,因此不會。 – Andreas

+1

請注意,對象序列化僅記錄值以及值應插入的類別。沒有字節碼。這必須已經存在於客戶端和服務器端。所以你可以修改要反序列化的類(到別的東西),它是數據。 –

+1

然而要注意研究發現的方法來創建對象圖,當反序列化導致遠程執行代碼:https://開頭foxglovesecurity。com/2015/11/06/what-do-weblogic-websphere-jboss-jenkins-opennms-and-your-application-common-this-vulnerability/ –

回答

1

當您在Java中序列化對象時,只有該對象的字段被序列化。客戶端和服務器上的字節碼必須相同(或至少兼容)。這由serialVersionUID執行。

序列化運行時相關聯,每個序列化類版本號,稱爲的serialVersionUID,其被反序列化過程用於驗證序列化對象的發送者和接收者都加載的類該對象是相對於兼容序列化。

考慮到這一點,如果更改字段的值,可以更改行爲。鑑於此實現Dog,您可以攔截該請求並將聲音的值更改爲"Moo!"

public class Dog { 
    private String sound = "Woof! Woof!"; 
    public void bark(){ System.out.println(sound); } 
} 

但由於在最初的實現"Woof! Woof!"是一個編譯時間常數,它不會被序列化,因爲它是不可能在運行時改變它。

+0

謝謝。這幫助我瞭解了Java如何將對象與流進行串行化。 – TheRealChx101

+0

@ TheRealChx101不客氣! – SilverNak

0

簡短的答案是肯定的,如果任何形式的數據流是不可信/妥協然後在序列化框架中的漏洞,你正在使用可能會導致在Java代碼中得到執行,可以反過來,推出一些更惡意的。

Apache Common Collection很少有這樣的漏洞。非常簡單地說,該類是基於數據流中的名稱而非預期名稱實例化的。 This would result in an arbitrary class getting instantiated

查看Java deserialization FAQ以更好地瞭解如何可靠地使用它們。