Java Deserialization Vulnerability Still Alive

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.

https://blog.pyn3rd.com/2023/09/15/CVE-2023-34040-Spring-Kafka-Deserialization-Remote-Code-Execution

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 ObjectInputStream, 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.

upload successful

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.

upload successful

Insecure attempt has been blocked successfully.

upload successful

Then I mimic Spring Kafka’s code thoroughly. I replace the class DeserializationException.class with Person.classto make you aware that the exeception would be thrown.

upload successful

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.

upload successful

Last step is to embed the CommonCollection6 gadget in a static code block.

upload successful

In conclusion, the weakness of customized ObjectInputStream contributes to Spring Kafka deserialization vulnerability. It only verifies the top layer function in stack.

upload successful

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 ValidatingObjectInputStream to 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.

upload successful

  • JEP290

    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.TemplatesImpl would be blocked.

upload successful

Unfortunately, this mechanism more or less has some shortages. I intend to talk about it next time.

upload successful