loading...
Cover image for Avoid Java serialization

Avoid Java serialization

brianverm profile image Brian Vermeer ๐Ÿง‘๐Ÿผโ€๐ŸŽ“๐Ÿง‘๐Ÿผโ€๐Ÿ’ป ใƒป2 min read

Serialization in Java allows us to transform an object to a byte stream. This byte stream is either saved to disk or transported to another system. The other way around, a byte stream can be deserialized and allows us to recreate the original object.

The biggest problem is with the deserializing part. Typically it looks something like this:

ObjectInputStream in = new ObjectInputStream( inputStream );
return (Data)in.readObject();

Thereโ€™s no way to know what youโ€™re deserializing before you decoded it. It is possible that an attacker serializes a malicious object and send them to your application. Once you call readObject(), the malicious objects have already been instantiated. You might believe that these kinds of attacks are impossible because you need to have a vulnerable class on you classpath. However, if you consider the amount of class on your classpath โ€”that includes your own code, Java libraries, third-party libraries and frameworksโ€” it is very likely that there is a vulnerable class available.

Java serialization is also called โ€œthe gift that keeps on givingโ€ because of the many problems it has produced over the years. Oracle is planning to eventually remove Java serialization as part of Project Amber. However, this may take a while, and itโ€™s unlikely to be fixed in previous versions. Therefore, it is wise to avoid Java serialization as much as possible. If you need to implement serializable on your domain entities, it is best to implement its own readObject(), as seen below. This prevents deserialization.

private final void readObject(ObjectInputStream in) throws java.io.IOException {
   throw new java.io.IOException("Deserialized not allowed");
}

If you need to Deserialize an inputstream yourself, you should use an ObjectsInputStream with restrictions. A nice example of this is the ValidatingObjectInputStream from Apache Commons IO. This ObjectInputStream checks whether the object that is deserialized, is allowed or not.

FileInputStream fileInput = new FileInputStream(fileName);
ValidatingObjectInputStream in = new ValidatingObjectInputStream(fileInput);
in.accept(Foo.class);

Foo foo_ = (Foo) in.readObject();

Object deserialization problems are not restricted to Java serialization. Deserialization from JSON to Java Object can contain similar problems. An example of such a deserialization issue with the Jackson library is in the blog post โ€œJackson Deserialization Vulnerabilityโ€

This was just 1 of 10 Java security best practices. Take a look at the full 10 and the easy printable one-pager available

Discussion

pic
Editor guide