EXPLOITIING INSECURE DESERALIZATION VULNERABILITIES FOUND IN THE WILD
This blog post was written by Ian Musyoka.
Introduction
Deserialization is the process of converting a byte stream back into an object so that it can be used by the web application the way it was intended.
The importance of serialization and deserialization of data is that it ensures that the object remains a replica of the original object before it was serialized. Insecure deserialization comes when unsanitized user-controlled data is passed to an unserialized call, allowing an attacker to leverage the vulnerability which in turn leads to code execution or arbitrary file read on any system.
INSECURE PHP DESERIALIZATION VULNERABILITY
Insecure PHP deserialization object of any class can be deserialized and instantiated regardless of the class which was expected. This allows an attacker to leverage functionality that a particular class can perform, for example, writing files to the system using the file_put_contents() method. This is why the vulnerability is sometimes referred to as Object Injection Vulnerability. Though deserialization of objects from a different class might cause an exception in the web application, the damage might already be done since most deserialization processes are completed before the deserialization process finishes. In Insecure PHP deserialization we jump to functions that have magic methods for example, __wakeup (), __destruct (), __toString ()
To demonstrate the vulnerability, I’ll use a system fromTryHackMe called debug.
When we do an nmap scan of the box we see that the port has two ports open.
- SSH (Secure Shell)
- HTTP
On opening the web application, we get a standard webpage with nothing too interesting. The next logical step is to do a directory brute force and I normally use the tool – gobuster.
Looking at the results returned by gobuster we have a backup directory and index.php file.
Looking at the backup folder we have an index.php backup file. I downloaded the file and reviewed the PHP Source code to see if we could find any vulnerabilities.
Looking at line 216 of the code we see that it uses the unserialize() call which deserializes any byte stream that is provided through the debug GET parameter.
Also looking through the source code we see that the class FormSubmit has a function that uses the magic method __destruct ()
We can abuse the file_put_contents () functionality to drop a web shell on the system. I created a PHP exploit script that creates a serialized object which when passed to the debug parameter on the web application should drop a shell on the system.
On executing the PHP exploit script, it generates a serialized payload.
On submitting the payload to the server we see that nothing changes.
However, if we try to access the file macrosec.php which the serialized payload was supposed to create, we notice that it exists because we do not get a 404 error.
I then add the cmd parameter which we had specified on the script and I try to execute System commands. We see that it works and we now have code execution on the system.
The next step is getting a reverse shell on the system. I created a Netcat listener on my box.
Using the web shell backdoor we had created on the system, we execute a bash reverse shell and get a shell back on our box from the system.
INSECURE NODE JS EXPRESS FRAMEWORK DESERIALIZATION VULNERABILITY
In Node JS, deserialization vulnerability exists when an untrusted user-controlled data is passed to an unserialized call leading to remote code execution since the object that has “:”_$$ND_FUNC passes to an eval() statement.
The “:”_$$ND_FUNC is declared in a variable called FUNC FLAG.
And Looking through the source code we see that the FUNCFLAG is passed to an eval() function and this leads to code execution on the system.
To demonstrate the vulnerability, I’ve used a system from TryHackMe. Looking through the Nmap results we notice that the web application is running node JS framework.
When we open the web application, we get a standard web page. However, when we send the request to burpsuite we see that there’s a cookie assigned to us.
On examining the cookie, we find out that it’s a JSON object and it’s a cookie belonging to the guest user. My first thought was to try to convert the cookie to impersonate the admin user of the web application. I changed some values on the JSON object and encoded the cookie with base64 encoding and URL encoding.
I then copied the cookie to the request and ran it. Looking at the response we get from the web application, we see that we were able to impersonate the admin user of the web application but we are still asked to log into the web application.
We are sure that the web application is utilizing the cookie somehow just not how we thought. Next, I tried deleting a section of the cookie and see if the web application would cough out an error or stack trace messages. We see that the web application throws errors and it shows a stack trace error indicating that the cookie wasn’t deserialized correctly.
I then searched online for Node JS deserialization vulnerability and I came across an interesting article from opsecx. A Sample payload was even provided.
So we craft a payload using the sample payload already provided. Looking at the payload, it is supposed to create a reverse shell to the attacker box using the IP Address provided.
Before sending the payload we create a Netcat listener to our box.
We then send the serialized payload to the server using the request we already intercepted.
Going back to our Netcat listener, we have a shell on the victim’s box.
Insecure deserialization is a really difficult vulnerability to find if you are performing a black-box penetration test on a particular system. However, deserialization might be identified by:
-
- By seeing chucks of base64 encoded data traversing through a network.
- By using another vulnerability like Local File inclusion to leak the source code of the web application (This is where the concept of chaining vulnerability comes in handy).
- By coming across a source code backup of the web application.
- Through Fuzzing the web application using a common wordlist. Personally, I recommend Seclists and Web Application Fuzzers (ffuf,burpsuite and wfuzz).
Insecure deserialization can be prevented through the following methods
-
- Validation: making sure that the user input meets a certain criterion. Use whitelisting of expected types/data.
- Verification: if the input is valid, check for integrity using Digital signatures on the serialized objects. This will prevent tampering.
- Isolate and run deserialization code in a low privileged environment.
- Constantly monitor deserialization activities on servers since it makes the job of blue teamers easier in case incident response is ever required in case of a breach.
Disclaimer
The MacroSec blogs are solely for informational and educational purposes. Any actions and or activities related to the material contained within this website are solely your responsibility. The misuse of the information on this website can result in criminal charges brought against the persons in question. The authors and MacroSec will not be held responsible in the event any criminal charges be brought against any individuals misusing the information in this website to break the law.