Hello everyone,
I am Nitin yadav(KD) back again with another write-up
What are deserialization attacks?
I'll try to tell you right away. Every day this topic is getting more and more famous. There are a lot of tutorials, articles, and blog posts about this topic.
Deserialization attacks are an attacker's way to make your computer do what it wants.
It is the type of vulnerability that can severely impact your application's security.
It arises when client-side JavaScript code deserializes the input data into the data structures.
This can leave a large amount of sensitive information in the hands of attackers like hackers who use it to access sensitive information such as credit cards, passwords, emails, and more.
In many programming languages, including Java, PHP, ASP.NET, and Python, it is necessary to represent arrays, lists, dictionaries, and other objects in a serialized data format that can be sent through streams and over a network and restored later.
This process is called serialization.
The final serialized format may be represented in binary or as structured text.
JSON and XML are two commonly used structured text formats used for serialization within web applications.
The reverse of the serialization process is called deserialization.
Deserialization takes serialized data from a source (a string, stored file, etc.) or network socket and turns it back into an object.
Deserialization attacks, or insecure deserialization, are the exploitation of vulnerabilities within the deserialization process by using untrusted data to abuse the logic of an application, access control, or even instigate remote code execution (RCE).
Deserialization example explained
Now let's understand the serialization and deserialization process in PHP to familiarize you with the concept before we move on to the offensive strategy.
Here's a simple class in PHP that we would like to serialize so we can deserialize it later:
Executing this script will serialize the PHP class to the following string:
Similarly, in Python, the same process can be performed with the default pickle serialization class, as demonstrated below:
The output will be an encoded string value:
Using the serialized string, we can store or transfer an array, object, or other complex data structure as a string representation.
By using unserialize, we can reverse the process and instantly access the array or object items.
Insecure deserialization
Insecure deserialization refers to a deserialization process in which the serialized string is converted back to its original object in memory by using untrusted user inputs.
Insufficient input validation can lead to logic manipulation or arbitrary code execution. Some common attack vectors in web applications that use serialization include:
1. Abusing an application’s logic operation that relies on serialized objects (i.e., purchase action)
2. Accepting user-supplied serialized objects in the cookies to identify a user
3. Using serialized objects as API authentication tokens
4. Transferring user data via Streams, WebSockets, or WebRTC channels
5. Executing serialized objects as inputs to execute commands in the file system
Many programming languages provide APIs and capabilities to perform native serialization and deserialization processes—but most of them include inherently unsafe operations, which could easily result in code execution depending on their application logic context.
For example, let’s assume our application uses PHP object serialization to determine user application privileges:
GET /login.php HTTP/1.0
Host: vuln.lab
Cookie: data=a:2: {s:8:”username”;s:4:”user”;s:4:”guid”s:32:”b6a8b…bc960”;}
Connection: close
And that the PHP server-side logic is as follows:
In this situation, an attacker could give itself administrator privileges by changing the cookie from
to the following serialized object:
PHP Object Injection
Two factors are required to successfully carry out attacks on PHP Object Injection vulnerabilities:
1. There must be an insecure implementation of the unserialize() method based on client input (i.e., cookies, stored serialized data, or serialized request parameters)
2. There must be a PHP magic method (e.g., __wakeup or __destruct) within the class that is vulnerable to being exploited to create our malicious payload or “POP Chain” (we’ll discuss this topic later)
In PHP, methods that begin with two underscores (__) are called “magic methods.” These magic methods play an important role in the application’s lifecycle, as they can be invoked during specific events.
There are 15 different magic methods:
__construct() __set() __toString()
__destruct() __isset() __invoke()
__call() __unset() __set_state()
__callStatic() __sleep() __clone()
__get() __wakeup() __debugInfo()
In PHP Object Injection attacks, we use magic methods to reconstruct our payload. Some magic methods are commonly used in serialization.
For example:
1. __sleep is called when an object is serialized and must be returned to an array.
2. __wakeup is called when an object is deserialized.
3. __destruct is called when a PHP script ends and the object is destroyed.
4. __toString is called to convert an object into a string.
PHP Object Injection with the magic method
Let’s look at an example where the user inputs proceed as a command using the __wakeup magic method. Consider the following vulnerable PHP code:
In this class, we see the implementation of a PHP magic method, __wakeup.
The script also declares a vulnerable unserialize() function. When both conditions are met, it can result in arbitrary PHP object(s) injection into the current application scope.
To create our payload, we can execute the following script:
This results in:
After URL encoding, our final payload will appear as:
Now we can append our payload as a data query string value:
GET /auth_check.php?data=O%3A13%3A%22InsecureClas… HTTP/1.0
Host: vuln.lab
Connection: close
As a result, the script will evaluate our payload command and return the phpinfo() output.
One important thing to keep in mind in PHP serialization is that the method is not serialized and will not be saved; only the name of the class and its properties are serialized.
Please notice, that the payload has been shortened for readability
Property oriented programming
The Property Oriented Programming (POP) technique can be used to create so-called POP chains that allow control over all the properties of a deserialized object.
In POP chains, magic methods are used as the initial “gadget”—a snippet of code borrowed from the codebase—and these gadgets can then be chained together to achieve our goal (i.e., code execution).
As a basic example, let’s assume we’ve found vulnerable code that implements the __destruct() magic method in our library as follows:
What this block of code does is define a class named LoggerIO—which inherits from a parent class IO—and implements the magic method __destruct().
This calls the removeFile() method internally.
In addition, it sets the filename property to a predefined string “log.txt.” To better understand the vulnerability impact of the removeFile() method, let’s inspect class IO:
Until now, our initial gadget is the __destruct() magic method, which calls the removeFile() method.
The removeFile() method then becomes our new gadget. Inspecting the destroy() method reveals its susceptibility to classic remote code execution (RCE) vulnerabilities.
To exploit this vulnerability, we need to change the value of the LoggerIO class property to a string such as “log.txt | touch hack.txt,” which will then allow us to execute a command using the destroy() method within the IO class.
To create our final POP chain, we can use the following script:
This will result in our final payload being submitted to the following serialized string:
In the next example, the declared magic methods in the classes do not contain any useful code in terms of exploitation.
However, it is still possible to create POP chains in such cases.
Consider the following classes:
The first block of code here defines a class named LoadObjectInternal, which calls the eval() method of obj when the __wakeup() function is called.
The second block of code describes the CodeLoad class, which has a private property named code that contains the code string to be executed, and a run() method that calls eval() on the given code string.
At first, this seems complicated and not exploitable.
But to exploit it, all we need to do is overwrite the code propriety to contain our malicious payload and prompt the LoadObjectInternal class to create an instance of the CodeLoad using the __wakeup() method.
Hence, we can use the following script to generate our payload
This will result in our final payload being submitted to the following serialized string:
For more refer to this tool
Python pickle serialization
In Python, the serialization and deserialization processes are based on the pickle module, which is a built-in module for serializing and deserializing Python objects.
Four methods can be used in a pickle: dump, dumps, load, and loads.
As the pickle method is not secure against erroneous or maliciously constructed data, it may lead to remote code execution (RCE) vulnerabilities if the un-pickled data is received from an untrusted or unauthenticated source.
The pickle framework method works as follows:
1. Dump— Write a serialized object to an open file
2. Load—Convert a serialized byte stream back to an object
3. Dumps—Return a serialized object as a string
4. Loads—Return the deserialization process as a string
For more Click Here
How to Prevent Insecure Deserialization
To protect your web application from insecure deserialization, it’s crucial never to pass a serialized object manipulated with untrusted input by the user to the deserialize function. The reason is that if you do so, an untrusted user would be able to manipulate the object and can send it directly to the PHP deserialize function.
In case you have to accept serialized objects, here are some tips for stopping insecure deserialization:
Introduce digital signatures and other integrity checks to stop malicious object creation or other data interfering
Run deserialization code in low privilege environments
Keep a log with deserialization exceptions and failures
Execute strict constraints for the deserialization processes before object creation
Limit and check all incoming and outgoing network activity from deserialization containers and servers
Keep tabs on deserialization activities to identify in case there is constant deserialization by a user
Use deserialization methods like JSON, XML, and YAML that are language-agnostic
Some Reports from Hackerone
If you like the blog please comment down below😊
I see you next time :)
Take care and stay safe!
コメント