Several months ago, the Constrast Security Team reported a Java deserialization vulnerability about Spring Kafka to VMWare Security Team. It immediately attracted my attention and I got started to analyse this bug. If you are interested in it, you could look up the details in my previous blog.
After analyzing explicitly, I consider it a thought-provoking report. Hence, I instantly write this blog down.
Java deserialization vulnerability is on the top of the list when it comes to Java Security. I would like to talk about that with the recent Java deserialization vulnerability of Spring Kafka.
People have been likely to know the fundamental reason is unsafe serialization stream from users without verification contributes to remote code execution.
A majority of Java applications have more or less paid attention to the deserialization vulnerability, like Weblogic Server, Apache Shiro. Personally, overwriting the
ObjectInputStream function becomes widespread use for defending against Java deserialization attack. It could make this problem alleviated. When overwriting the
resolveClass would be hooked and potentially dangerous functions revoking might be found out.
Actually, Spring Kafka also utilizes the same way to defend against Java deserialization vulnerability. Observe the Java fragment up close.
Although the defensive programming apparentlly existing, why still does the Java deserialization vulnerability take place in Spring Kafka? I guess the confusion has manifested in someone’s face in front of the screen.
- Customize ObjectInputStream & Hook resolveClass
I just supply a demonstration with an overwritten
ObjectInputStream function.Then, I attempt to deserialize the malicious deserialization stream.
Insecure attempt has been blocked successfully.
Then I mimic Spring Kafka’s code thoroughly. I replace the class
Person.classto make you aware that the exeception would be thrown.
Consequently, I could simply escape this verification in a way of encapsulation. After initializating
CustomExceptionClass , it could be inputted into the instance of
DeserializationExeception as an argument.
Last step is to embed the
CommonCollection6 gadget in a static code block.
In conclusion, the weakness of customized
ObjectInputStream contributes to Spring Kafka deserialization vulnerability. It only verifies the top layer function in stack.
Apart from the the way to customize
ObjectInputStreamfunction, there are some other choices for defence.
ValidatingObjectInputStream in Apache Commons IO library
The Apache Commons IO library contains utility classes, stream implementations, etc. It offers a function
ValidatingObjectInputStreamto only allow the specific classes to be deserialized, equal to a whitelist.
Besides the classes in the whitelist, any class could not be deserialized! As you see, the class
org.springframework.kafka.support.serializer.DeserializationExceptionhas been blocked, because it’s not included in the whitelist.
JEP290 is a JDK-based detective pragramming. It provides a flexible mechanism to prevent Java applications from deserialization attack.
Developers could customize a particular class as the filter. It permits the classes to be deserialized or not. In my illustration, the class
com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImplwould be blocked.
Unfortunately, this mechanism more or less has some shortages. I intend to talk about it next time.