Insecure Deserialization in Java Applications

How Organizations Should Prepare for Penetration Testing
February 10, 2023
4 Best Penetration Testing Service Companies In India
February 10, 2023

February 10, 2023

In this blog, we will delve into the topic of Insecure Deserialization in Java Applications. To understand this vulnerability, we need to first comprehend what serialization and deserialization are and their importance in applications. Serialization is the process of converting an object into a format that can be saved or transmitted, while deserialization refers to the reverse process of converting the format back into an object. However, when an attacker can manipulate the serialized object, it can lead to serious consequences such as Denial of Service, authentication bypass, and even Remote Code Execution. 

Insecure Deserialization in Java occurs when a malicious user tries to insert a modified serialized object, leading to an arbitrary code execution vulnerability. This blog will take you through the process of identifying serialized objects in Java applications, selecting a suitable gadget chain, and exploiting the vulnerability using tools such as ysoserial. Stay tuned as we dig deeper into the world of Insecure Deserialization in Java Applications

What is serialization?

Serialization is a process during which an object in a programming language is converted into a format that can be saved to the database or transferred over a network. 

What is deserialization?

Deserialization refers to the opposite: the serialized object is read from a file or the network and converted back into an object.

Insecure deserialization is a vulnerability that arises when an attacker can manipulate a serialized object, causing unintended consequences in the program’s flow. This can result in Denial of Service (DoS), authentication bypass, or even Remote Code Execution (RCE). 

For example, let’s suppose an application uses a serialized object from a user to determine who is logged in. In that case, a malicious user could tamper with the object to authenticate as someone else.

If the application uses an unsafe deserialization operation, the attacker could even embed code snippets in the object and execute them during deserialization leading to Remote Code Execution (RCE).

Multiple programming languages, such as Java, Python, PHP, and Ruby, support serialization. But in this blog, we will be specifically looking into Java applications.

Insecure Deserialization in Java

Insecure Deserialization in Java occurs when a malicious user tries to insert a modified serialized object into the system to compromise the system or its data.

Think of an arbitrary code execution vulnerability that can be triggered when deserializing a serialized object. To better explain Java deserialization vulnerabilities, we first need to understand how serialization and deserialization work in Java.

The class implementing the java.io.Serializable interface enables the serialization of Java classes. Classes implement special methods, writeObject() and readObject(), to handle the serialization and deserialization of objects of that class. Classes that do not implement this interface will not have any of their objects serialized or deserialized.

The writeObject() method will be called if an object is serialized. The readObject() method will be called when the object is deserialized. 

Identifying Java Serialized Objects

Before proceeding to the vulnerability exploitation, we need to find an entry point to insert our malicious serialized object.

In Java applications, serializable objects transport data in HTTP headers, parameters, or cookies.

The following signatures can assist in identifying potential entry points for your exploits in Java serialized objects:

  • The content-type header of an HTTP response is set to application/x-java-serialized-object.
  • Serialized objects start with AC ED 00 05 in Hex or rO0 in Base64.

It is common in Java applications to encode serialized objects as it contains many special characters. So, look for differently encoded versions of these serialized objects in the application.

Gadget Chains

A “gadget” is a snippet of code already existing in the application. It can help an attacker achieve a specific goal.

Insecure deserialization vulnerabilities can be exploited by chaining multiple “gadgets” together to pass malicious input into a “sink gadget,” where it can cause maximum damage. These gadget chains are not payloads constructed by the attacker, but rather the attacker controls the data passed into the gadget chain.

This is typically done through a magic method invoked during deserialization, also known as a “Kick-off gadget.” Manually identifying gadget chains can be difficult without source code access, but there are tools available that provide pre-discovered chains that have been successfully exploited on other websites.

This approach is made possible due to the widespread use of libraries that contain exploitable gadget chains.

Gadget Selection

When performing an insecure deserialization attack on a Java application, you must select a gadget that can exploit the vulnerability. Here are a few things to check about when picking out a gadget.

  • Compatibility: The gadget must be compatible with the Java version and application environment that you are targeting. 
  • Capabilities: The gadget should have the necessary capabilities to perform the desired actions, such as reading or writing files, executing commands, or creating a remote shell.
  • Ease of use: The gadget should be easy to use and have clear documentation or usage instructions. 
  • Detection: The gadget should be designed to evade detection by security tools and anti-virus software. 
  • Open-Source: The gadget should be open-source and widely used in the community, and it should be updated frequently. 

Here are some examples of popular gadgets for insecure Java deserialization:

  • JRMPListener: A Java RMI (Remote Method Invocation) listener that can create a remote shell on the target system.
  • Apache commons-collections: It contains multiple gadgets that can be used to exploit insecure deserialization vulnerabilities. 

It is important to note that the examples above are only a few of the many gadgets available, and new gadgets are discovered regularly.

It’s crucial to keep an eye on the latest research in this area and to test the gadgets against the specific environment you are targeting.

One such tool for Java deserialization is “ysoserial.” This lets you choose one of the provided gadget chains for a library you think the target application is using, then pass in a command you want to execute. It then creates an appropriate serialized object based on the selected chain.

Listing Gadgets

To list all the gadget chains available on the ysoserial tool, you can use the below command:

‘java -jar ysoserial.jar’

Using ysoserial, you can create malicious Java serialized objects using gadget chains from specified libraries with a single command. The usage is as follows:

Java -jar ysoserial.jar [gadget chain] '[command to execute].'

Now, as per the library used by the application, you can select the appropriate gadget chain for exploitation. For example, to create a payload that uses a gadget chain in the Commons Collections library that would open a calculator on the target host, you can use the payload:

java -jar ysoserial.jar CommonsCollections4 ‘calc.exe’

Sometimes it would be obvious which library to use for your gadget chain, but often, it would be a matter of trial and error to see which vulnerable libraries are available to the application.

Also, read Insecure Deserialization Attack in Python Application

Exploitation

For the exploitation part, we will solve this lab from PortSwigger Academy, which uses a serialization-based session mechanism and loads the Apache Commons Collections library.

We will be exploiting this lab using pre-built gadget chains with the help of the ysoserial tool.

This lab aims to generate a malicious serialized object containing a remote code execution payload to delete the morale.txt file from Carlos’s user’s home directory.

After starting the lab, log in to the system using the credentials wiener: peter.

Observe that the session cookie contains a serialized Java object with “rO0,” which we already discussed in the Java Serialized object section. 

We have found the entry point to insert our malicious serialized object. We will generate a malicious serialized object containing a remote code execution payload to delete the morale.txt file from Carlos’s user’s home directory.

Let’s start with creating a payload using the ysoserial tool.

java -jar path/to/ysoserial.jar CommonsCollections4 'rm /home/carlos/morale.txt' | base64

This will generate a Base64-encoded serialized object containing your payload to delete the txt file.

  • java -jar: to run the ysoserial tool
  • CommonsCollections4: Apache Commons Collections library gadget from ysoserial
  • ‘rm /home/carlos/morale.txt’: Command to execute
  • base64: encode it as base64

Copy the above payload and replace the session cookie with it. Then, select the entire cookie and URL-encode it.

Send the request and observe the lab is solved as our payload is executed and the file is deleted.

Remediation

To prevent insecure deserialization in Java applications, it is important to follow best practices such as the following.

  • To ensure the non deserialization of objects in your application, declare a readObject() method (with the “final” modifier), which throws an exception. This is particularly important for objects that may be forced to implement the Serializable interface due to their hierarchy.
    Here’s an example of how to override the readObjectNoData() method to prevent deserialization:

private final void readObject(ObjectInputStream in) throws java.io.IOException {

           throw new java.io.IOException("Cannot be deserialized");            }

  • A whitelist approach to deserialization is one of the most effective ways to prevent insecure deserialization. This involves only allowing certain classes to be deserialized and blocking any classes, not on the whitelist. This can be done using a custom deserialization method, which can be used to validate the data before deserializing it.
  • Using a custom deserialization method can also be used to prevent insecure deserialization. This method can be used to validate the data before deserializing it. It can be implemented using various techniques, such as input validation, data sanitization, etc.
  • Implementing a library or framework specifically designed to handle deserialization securely can also be an effective way to prevent insecure deserialization. These libraries and frameworks can handle the deserialization process for you and often include built-in security measures to prevent insecure deserialization.
  • Finally, keeping the application and its dependencies up to date is an important step in preventing insecure deserialization. Many vulnerabilities are discovered and patched in the software, so it is important to keep the application and its dependencies up to date to prevent these vulnerabilities from being exploited.

Conclusion

Insecure deserialization in Java applications is a serious threat that can lead to unauthorized access, data theft, and even Remote Code Execution (RCE). Java applications rely on serialization and deserialization for communication and storage, which can be exploited by attackers if not handled securely. Understanding the basics of serialization and deserialization in Java, identifying entry points, and using gadgets and tools, like ysoserial, are crucial steps in securing Java applications from insecure deserialization attacks. Stay vigilant and be informed on the latest research in this field, to ensure the security of your Java applications. Act now and secure your Java applications today!

Enable Notifications OK No thanks