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
Top comments (0)