Overview
Our tech stack is Spring, JPA using Hibernate, and SQL server.
- We use Jackson for JSON serialization/deserialization for REST implementation.
- In our model class - we have
implements Serializable
. - Jackson
ObjectMapper
which Spring uses also implementsSerializable
.
As we can see, Hibernate has serialization which is binary (Java), and Jackson is text (JSON) based serialization.
We would like to harden all uses of ObjectInputStream
of java and make sure that there are no deserialization issues in our application.
@jhoeller, we request your insights in building a hardened application.
Questions
- When spring and jpa/hibernate are implemented, does hibernate use the
ConfigurableObjectInputStream
? - Does jackson use the
ConfigurableObjectInputStream
? - How can we configure Spring to use our
LookAheadObjectInputStream
instead ofConfigurableObjectInputStream
?
Custom ObjectInputStream
Inspired by an example from OWASP, we would like to define a LookAheadObjectInputStream
which would extend Spring's ConfigurableObjectInputStream
where we can define our own application classes that can be resolved.
public class LookAheadObjectInputStream extends ConfigurableObjectInputStream {
public LookAheadObjectInputStream(InputStream inputStream) throws IOException {
super(inputStream);
}
/**
* Only deserialize instances of our expected Bicycle class
*/
@Override
protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {
if (!desc.getName().equals(Bicycle.class.getName())) {
throw new InvalidClassException("Unauthorized deserialization attempt", desc.getName());
}
return super.resolveClass(desc);
}
}
Comment From: sbrannen
I've edited your comment to improve the formatting. You might want to check out this Mastering Markdown guide for future reference.
Comment From: sbrannen
Let me start by answering your questions.
- When spring and jpa/hibernate are implemented, does hibernate use the
ConfigurableObjectInputStream
?
No.
- Does jackson use the
ConfigurableObjectInputStream
?
No. Jackson deserializes JSON documents (i.e., text input) and therefore does not use an ObjectInputStream
(i.e., binary input).
- How can we configure Spring to use our
LookAheadObjectInputStream
instead ofConfigurableObjectInputStream
?
The only place where you can change the ObjectInputStream
used by the core Spring Framework is in a custom extension of the HttpInvokerServiceExporter
that overrides the createObjectInputStream(InputStream)
method. Note, however, that Spring's remoting technologies support was deprecated in conjunction with #25379.
19880 updated the guidelines for serialization-based endpoints, leading to the following note in the reference manual:
Be aware of vulnerabilities due to unsafe Java deserialization: Manipulated input streams can lead to unwanted code execution on the server during the deserialization step. As a consequence, do not expose HTTP invoker endpoints to untrusted clients. Rather, expose them only between your own services. In general, we strongly recommend using any other message format (such as JSON) instead.
If you are concerned about security vulnerabilities due to Java serialization, consider the general-purpose serialization filter mechanism at the core JVM level, originally developed for JDK 9 but backported to JDK 8, 7 and 6 in the meantime. See https://blogs.oracle.com/java-platform-group/entry/incoming_filter_serialization_data_a and https://openjdk.java.net/jeps/290.
In general, Spring cannot influence how third-party libraries handle Java deserialization (i.e., binary input).
If you really need to use Java deserialization to process binary input from untrusted sources, as an alternative to the LookAheadObjectInputStream
you have shared, you might be better off registering a custom ObjectInputFilter.
However, we strongly recommend using any other message format (such as JSON) instead.
In light of the above, I am closing this issue.
Comment From: mattjerry
thank you. I have one question:
When spring and jpa/hibernate are implemented, does hibernate use the ConfigurableObjectInputStream? Thanks for confirmation here that typically it is NO.
One more point is that as per JPA spec, PKs of classes with composite IDs have to be serializable. And in this specific context , can you pl confirm that hibernate would not be using Spring's ConfigurableObjectInputStream in this case as well? when there are composite IDs?
Comment From: sbrannen
One more point is that as per JPA spec, PKs of classes with composite IDs have to be serializable. And in this specific context , can you pl confirm that hibernate would not be using Spring's ConfigurableObjectInputStream in this case as well? when there are composite IDs?
That was covered by this part of my response:
In general, Spring cannot influence how third-party libraries handle Java deserialization (i.e., binary input).
In any case, when you're using Hibernate/JPA and your entities get serialized/deserialized (for example, due to the use of a 2nd-level cache with overflow to disk), you're talking about classes under your control. In other words, this is trusted code that is undergoing serialization. It's not some potentially malicious binary input provided by an external source.
Comment From: mattjerry
Thanks a lot for your clarifications. This really helped.