从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 伪代码不是实验,而是思想实验。我建议你在现实世界中尝试一下。
我尝试了以下实验(这只是一个伪代码):
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 伪代码不是实验,而是思想实验。我建议你在现实世界中尝试一下。