0

I tried the following experiment (this is just a pseudocode):

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());
    }
}

then created a malicious object:

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

and finally sent an instance of malicious object to the sever using another program:

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());
}

The output that Server printed to the screen was

I am malicious object

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.

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

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

mercury0114
  • 1,341
  • 2
  • 15
  • 29

2 Answers2

2

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.

No. The object doesn't contain the code. The class contains the code, and the class isn't serialized. You already had the 'hacked' code, so you already had the problem, prior to any serialization.

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

You can't, but the situation can only arise if the compiled code that produces the output shown is already present in your CLASSPATH, so you already have the problem, serialization or no serialization. Note that serialization does not serialize classes.

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

Yes.

NB Pseudocode is not an experiment, other than a thought-experiment. I suggest you try it in the real world.

user207421
  • 305,947
  • 44
  • 307
  • 483
  • I also thought that object should contain only its state. But how then toString method prints "I am malicious object"? – mercury0114 May 23 '16 at 10:09
  • 1
    @mercury0114 Because you already have the 'hacked' .class file in your CLASSPATH, as I have already stated. If you don't, the problem cannot arise, for the reasons which I have also already stated. – user207421 May 23 '16 at 10:10
  • @downvoter Please cite a relevant section of the [Object Serialization Specification](https://docs.oracle.com/javase/8/docs/platform/serialization/spec/serialTOC.html) that disagrees with this answer. If you can find one. – user207421 May 23 '16 at 10:13
  • Asked friend to send `MaliciousObject` from remote machine to my server, and got `ClassNotFoundException`. So your explanation seems to be correct. Thanks! – mercury0114 May 23 '16 at 12:48
0

Maybe serialVersionUID may help for defend against this. You may read: http://www.mkyong.com/java-best-practices/understand-the-serialversionuid/

What is a serialVersionUID and why should I use it?

Community
  • 1
  • 1
nikli
  • 2,281
  • 2
  • 24
  • 38
  • If the `serialVersionUIDs` didn't match, an `InvalidClassException` would have been thrown. There is nothing in either of your links that addresses the question asked. – user207421 May 23 '16 at 10:01
  • It must be throw, with `serialVersionUID` java validated that serverside and clientside objects are same, if hacker change you may catch it, so it prevents from malicious objects. – nikli May 23 '16 at 10:06
  • If 'hacker change' you must already have the hacked .class file on your CLASSPATH. Otherwise the problem cannot possibly arise; and if you already have the hacked .class file, you already have the problem, regardless of serialization. You are confusing objects with classes, and data with code. – user207421 May 23 '16 at 10:07
  • hacker can only catch object from network and change, java `serialVersionUID` for verifying. If hacker take over all server and client side classes you have other problem, network security or etc :) – nikli May 23 '16 at 10:15
  • That's what I said. Changing the `serialVersionUID` would not cause the problem described in the question. *Not* changing it wouldn't cause it either. The only way to cause it would be to take over the CLASSPATH of the receiver. `serialVersionUID` has nothing to do with it, and neither therefore does this answer. – user207421 May 23 '16 at 10:25
  • Please read http://www.mkyong.com/java-best-practices/understand-the-serialversionuid/ If `serialVersionUID` is used in case of serverside or clientside class change java throw exception for preventing attack. – nikli May 23 '16 at 10:27
  • **There is no attack.** There is no problem here to solve: *ergo* `serialVersionUID` isn't part of the solution. If there is anything in your non-normative citation that says the contrary, it is wrong. – user207421 May 24 '16 at 00:43