Web ApplicationSeptember 2, 2022Insecure Deserialization in Java

Our previous blogs covered Insecure Deserialization in PHP and Python. In this blog (the third in our “Insecure Deserialization” series), we’ll take a glance at how to exploit a deserialization vulnerability in Java. So, let’s begin with the fundamentals.

Insecure Deserialization in Java 

The use of Java deserialization is to create objects from input sources. These input sources are byte-streams in a range of different formats (some standard forms include JSON and XML). Systems use deserialization to ensure proper operation or to communicate with authorized external sources across networks. However, malicious or insecure byte-streams can take advantage of deserialization vulnerabilities.

Serialization Interface in Java 

Java’s serialization technique transforms “objects” into byte-streams so they can be saved for later usage in places like files, databases, and network traffic. We use the java.io implementation to make a Java object serializable. The writeObject() function of the ObjectOutputStream class is used to serialize an object. Only those objects from classes that implement java.io can be serialized.

Deserialization interface in Java 

Deserialization of a byte stream does not include calling the Object() function. In addition to this, the data is simply written to the fields of an empty object using reflection. The term “deserialization” refers to the process by which a serialised object is transformed into its original state as an object instance. The stream of bytes from the other end of the network or a database can be read directly as the input to the deserialization process.

To be exact, this stream of bytes, or serialized data, contains all the details about the instance that was serialized through the serialization process. This data consists of the class metadata and the values and type information for the instance field types. The same data is required when an object is rebuilt to create a new object instance. The JVM reads class metadata, which indicates whether an object’s class implements the “Serializable” or “Externalizable” interface, from the stream of bytes while deserializing an object. 

Java Deserialization Vulnerability 

When applications deserialize “objects” from unreliable sources, the Java deserialization vulnerability arises. In this attack, serialized Java objects are used, giving attackers full remote access over an application server. 

In complex modern systems, the native binary format is not optimal because the components that exchange information can talk to one another (for example, while moving data between services). Serialization, to put it simply, is the process of converting binary data into a string (ASCII characters) so that it can be transferred via common protocols. 

Serialization procedures are highly common in API, microservices, and client-side MVC designs. When the data is being serialized and deserialized it is trusted (within the system’s control). 

If an external user can modify the input, the outcome is an untrusted deserialization vulnerability. In this scenario, converting from string to binary (deserialization) is a sensitive procedure that can be abused easily. Typically, a payload that includes remote code execution in the targeted system is prepared and its purpose is frequently to execute system commands. 

The usage of deserialization itself is not a problem. When a malicious user (attacker) has access to the data that is being deserialized, such as when data is sent to the deserialization process over a network connection, problems occur at that point. An attacker could have some control over in-memory variables and code objects if they have access to the data being deserialized. They can therefore affect the flow of code that uses in-memory variables and code objects if they have control over the data. Let’s take a look at a Java deserialization example. As an example, we are going to use WebGoat. WebGoat is an OWASP-maintained deliberately insecure application that allows interested developers or security researchers to test vulnerabilities commonly found in Java-based applications that use common and popular open-source components. 

By observing the string, it appears that Java deserialization is in use. If it’s not correctly validated, then an attacker can send a specially crafted malicious object. This can lead to a dangerous RCE condition. As you can see from above, a magic sequence(rO0AB) identifying java serialized object has been detected (Base64: rO0AB, Raw: 0xac, 0xed, 0x00, 0x05). The challenge is to create a malicious Java serialized object in order to delay the page response by 5 seconds. 

Let’s inject sample data “test” in the input field and try to intercept using a proxy tool such as Burp Suite. 

As can be seen above, the HTTP POST request contains a “token” parameter in the body and it contains our sample data “test”. 

Let’s check the sources code by navigating to directory “WebGoat/webgoat-lessons/insecure-deserialization/src/main/java/org/owasp/webgoat/deserialization”. Next, open the file “InsecureDeserializationTask.java”. 

ObjectInputStream 

Java’s ObjectInputStream class is dangerous when used to deserialize untrusted data. So, we can start looking for its usage in the source code. 

The InsecureDeserializationTask class clearly uses user-provided data to instantiate some objects. 

This piece of Java code is the endpoint used by WebGoat to check for our token. It is expecting a VulnerableTaskHolder object and then performs checks to see if the serialized code is a timeout of 5 seconds as requested. 

Now we need some Java classes to execute arbitrary code on the system. Let’s look for Runtime.exec() method. This is a non-static method so it requires a runtime object instantiation, probably with GetRuntime(). We can see that Runtime.getRuntime().exec() is used directly and taskAction is assigned in the constructor. So, we can control taskAction to control the execution of commands.  

The VulnerableTaskHolder class has some caveats, particularly it executes sleep and ping commands and requires the requestedExecutionTime object variables to be set properly (and according to system ‘s time zone) if the object to deserialize is an instance of the VulnerableTaskHolder class. Luckily for us, this class performs OS commands on line 30. The taskAction attribute holds the command from the input which we control in the constructor. 

The VulnerableTaskHolder class accepts the taskAction in its constructor. 

Now we have identified the appropriate class to serialize and the location to inject our command. The goal is to put the application to sleep for 5 seconds. For this we are going to use the following gist. which stores the serialized payload in a file on disk as shown in the screenshot below.  

Let’s run the code which generates a file “serial”. For this, we are going to use Visual Studio Code 

We just need to base64 encode the malicious payload and send it through the application’s input field. Running Attack.java file will create a file “serial” which needs to be converted to base64. 

cat serial | base64 -w0 

Notice the payload starts with rO0AB. So, let’s send this payload to the application. 

As you can see, we have successfully demonstrated how attackers can exploit insecure deserialization vulnerabilities in Java. As for deserialization vulnerabilities in Java, we talked about them in this blog post. The next blog post will focus on insecure deserialization vulnerabilities in .NET.   

By partnering with Redfox Security, you’ll get the best security and technical skills required to execute an effective and a thorough penetration test. Our offensive security experts have years of experience assisting organizations in protecting their digital assets through penetration testing services. To schedule a call with one of our technical specialists, call 1-800-917-0850 now.

Redfox Security is a diverse network of expert security consultants with a global mindset and a collaborative culture. With a combination of data-driven, research-based, and manual testing methodologies, we proudly deliver robust security solutions.

“Join us on our journey of growth and development by signing up for our comprehensive courses, if you want to excel in the field of cybersecurity.”

Redfox Security Team

by Redfox Security Team

Redfox Security is a fast-growing cyber security consulting firm, spread across 4 countries. With over 10 years of global security consulting experience, we help businesses strengthen their security posture. Our mission is to help businesses grow securely with our top-line cyber security consulting services – and that’s exactly what we do.