从ObjectInputStream读取对象时如何保证安全?

How to ensure safety when reading objects from ObjectInputStream?

我尝试了以下实验(这只是一个伪代码):

class Server {
    public static void main(final String args[]) {
        final ServerSocket server = new ServerSocket(PORT);
        final Socket client = server.accept();
        final ObjectInputStream stream = new ObjectInputStream(client.getInputStream());
        final Object object = stream.readObject();
        // Can we hope that standard toString method will be called?
        System.out.println(object.toString());
    }
}

然后创建了一个恶意对象:

class MaliciousObject extends Object implements Serializable {
    private static final long serialVersionUID = 1L;
    @Override
    public String toString() {
        return "I am malicious object";
    }
}

最后使用另一个程序向服务器发送了一个恶意对象实例:

public static void main(final String args[]) {
    final Socket socket = new Socket();
    socket.connect(serversAddress, TIMEOUT);
    final ObjectOutputStream stream = new ObjectOutputStream(socket.getOutputStream());
    stream.writeObject(new MaliciousObject());
}

服务器打印到屏幕的输出是

I am malicious object

所以看起来黑客可以实现一个 class 扩展对象,覆盖任何方法 M 来执行一些恶意代码,然后通过网络发送这个对象,希望服务器调用 M。

因此,我的问题是:如何防御?要是我们 从 ObjectInputStream 读取对象,我们如何确定它们没有畸形?

作为附带问题,在这种情况下,从 ObjectInputStream 读取对象时是否涉及 Java class 加载程序?

也许 serialVersionUID 可以帮助抵御这种情况。你可能会读到: http://www.mkyong.com/java-best-practices/understand-the-serialversionuid/

What is a serialVersionUID and why should I use it?

So it seems that a hacker can implement a class extending object, override any method M to execute some malicious code, then send this object over the network in a hope that server will call M.

没有。该对象不包含代码。 class 包含代码,class 未序列化。您已经有了 'hacked' 代码,所以在任何序列化之前您就已经遇到了问题。

my question is: how to defend against this? If we read objects from ObjectInputStream, how can we be sure that they're not malformed?

你不能,但只有当生成所示输出的编译代码已经存在于你的 CLASSPATH 中时,这种情况才会出现,所以你已经遇到问题,序列化或没有序列化。注意序列化不序列化classes.

As a side question, is in this case Java class loader involved when reading objects from ObjectInputStream?

是的。

NB 伪代码不是实验,而是思想实验。我建议你在现实世界中尝试一下。