用户
搜索
  • TA的每日心情
    擦汗
    2017-11-14 20:49
  • 签到天数: 48 天

    连续签到: 1 天

    [LV.5]常住居民I

    i春秋作家

    i春秋首席男神——小小艾

    Rank: 7Rank: 7Rank: 7

    84

    主题

    288

    帖子

    372

    魔法币
    收听
    0
    粉丝
    20
    注册时间
    2015-11-20

    核心白帽i春秋签约作者积极活跃奖突出贡献

    GeekC0s i春秋作家 i春秋首席男神——小小艾 核心白帽 i春秋签约作者 积极活跃奖 突出贡献 楼主
    发表于 2017-9-10 14:09:39 913481
    原文链接:http://www.htmlsec.com/?p=271
    本文章作者:226safe Team - Poacher

    0x00 前言:
    首先本地搭建环境,我所使用的是Windows PHPstudy集成环境。使用起来非常方便。特别是审计的时候。可以任意切换PHP版本。
    0x01 CMS简介:
    开源免费的PHP内容管理系统,不需要高深专业技术轻松搭建网站,使用简单 灵活方便 稳定快捷,风格切换 想换就换 适应不同需求。
    0x00 正文:
    漏洞所在处:/application/admin/controller/Index.php
    漏洞所在行:即为以下代码的内容
    两个越权以及XSS都在同一个方法内。所以直接贴上整个方法的代码(下文说的行数为本文章所贴代码的行数,并非实际cms漏洞文件的行数)
    [AppleScript] 纯文本查看 复制代码
    <?php
        public function rewrite()
        {
            $this->checkUser();
            $this->checkPermissions(6);
            if(Request::instance()->has('postId','post'))
            {
                //验证输入内容
                $rule = [
                    'biaoti' => 'require',
                    'neirong' => 'require'
                ];
                $msg = [
                    'biaoti.require' => Lang::get('The title must be filled in'),
                    'neirong.require' => Lang::get('Article content must be filled out')
                ];
                $data = [
                    'biaoti' => Request::instance()->post('biaoti'),
                    'neirong' => Request::instance()->post('neirong')
                ];
                $validate = new Validate($rule, $msg);
                if(!$validate->check($data))
                {
                    $this->error($validate->getError());//验证错误输出
                    return false;
                }
                $neirong = str_replace('<img','<img class="img-responsive"',Request::instance()->post('neirong'));
                $guanjianci = str_replace(',',',',Request::instance()->post('guanjianci'));
                $data = ['post_keywords' => htmlspecialchars($guanjianci), 'post_source' => htmlspecialchars(Request::instance()->post('laiyuan')), 'post_content' => $neirong, 'post_title' => htmlspecialchars(Request::instance()->post('biaoti')), 'post_excerpt' => htmlspecialchars(Request::instance()->post('zhaiyao')), 'comment_status' => Request::instance()->post('pinglun'), 'post_modified' => date("Y-m-d H:i:s"), 'post_type' => Request::instance()->post('xingshi'), 'thumbnail' => Request::instance()->post('suolvetu'), 'istop' => Request::instance()->post('zhiding'), 'recommended' => Request::instance()->post('tuijian')];
                Db::name('posts')
                    ->where('id', Request::instance()->post('postId'))
                    ->update($data);
                Db::name('term_relationships')->where('object_id',Request::instance()->post('postId'))->delete();
                // var_dump(Db::name('term_relationships')->getLastsql());exit;
                if(isset($_POST['fenlei']) && is_array($_POST['fenlei']))
                {
                    $data = [];
                    foreach($_POST['fenlei'] as $key => $val)
                    {
                        $data[] = ['object_id' => Request::instance()->post('postId'), 'term_id' => $val];
                    }
                    Db::name('term_relationships')->insertAll($data);
                }
                Hook::add('rewrite_post',$this->plugins);
                $params = [
                    'id' => Request::instance()->post('postId')
                ];
                Hook::listen('rewrite_post',$params,$this->ccc);
                Hook::add('rewrite_post_later',$this->plugins);
                Hook::listen('rewrite_post_later',$params,$this->ccc);
            }
            $classify = Db::name('term_relationships')->field('term_id')->where('object_id',Request::instance()->get('art'))->select();
            $fenlei =$this->getfenlei();
            foreach($fenlei as $key => $val){
                $fenlei[$key]['classify'] = 0;
                foreach($classify as $cval){
                    if($val['id'] == $cval['term_id']){
                        $fenlei[$key]['classify'] = 1;
                        break;
                    }
                }
            }
            $wzid = 0;
            if(Request::instance()->has('postId','post'))
            {
                $wzid = Request::instance()->post('postId');
            }
            elseif(Request::instance()->has('art','get'))
            {
                $wzid = Request::instance()->get('art');
            }
            $data = Db::name('posts')->where('id',$wzid)->select();
            $data[0]['post_content'] = str_replace('<img class="img-responsive"','<img',$data[0]['post_content']);
            $this->assign('data', $data[0]);
            $this->writeAlias($wzid);
            $this->switchEditor();
            $this->assign('backstageMenu', 'neirong');
            $this->assign('option', 'articles');
            $this->assign('fenlei', $fenlei);
            return $this->view();
        }
    我大概讲一下这两个越权所在的地方。
    第一处:在点击编辑文章的时候将文章内容查询出来并且遍历在页面中。
    第二处:点击提交保存时候将修改的文章内容保存。

    首先我们先来看第一处。我们先看代码的第六行(很明显的可以看出来是使用THINKPHP5开发的)。
    这里是先判断是否存在postId请求参数并且请求类型为POST。就是说如果是以POST方式将postId传了过来的话就进入真区间。
    看上述代码得知7-52行是进行的编辑修改操作。由于我们这里先说第一处。第一处的请求是为GET。所以我们需要继续往下走。从第53行开始处理的是正常get请求的一些操作。
    从69行开始看。如果是get方式并且art值存在的话。那么$wzid则被赋值为get传过来的art值。接下来走到73行。我们可以清楚的看到。该行代码的where条件仅是id等于$wzid值即可查询。并没有进行所属用户的权限判断。上面得知我们$wzid的值是可控的。所以我们只要修改art值即可获取其他用户的文章内容。
    以下面为例,test002有一篇文章id为6。
    1.png
    直接将art=4改成art=6
    2.png
    来查看一下所执行的SQL语句。
    3.png

    这样就可以非常明显的看出来了。并没有判断该文章所属用户。

    接下来,我们看第二处。第二处跟第一处原理差不多。所以我也就不多讲了。直接定位到30行代码。
    Db::name('posts')->where('id', Request::instance()->post('postId'))->update($data);
    继续瞄准where条件。条件直接就是id等于传过来的postId值。在我们修改的时候。直接抓包。将POST包里面的postId修改成任意一篇文章的id。即可越权修改。
    4.png
    直接改成我们刚才的那篇文章id为6
    5.png
    修改成功。

    存储型XSS:
    我们看到29行。即为以下代码:
    [AppleScript] 纯文本查看 复制代码
    $data = ['post_keywords' => htmlspecialchars($guanjianci), 'post_source' => htmlspecialchars(Request::instance()->post('laiyuan')), 'post_content' => $neirong, 'post_title' => htmlspecialchars(Request::instance()->post('biaoti')), 'post_excerpt' => htmlspecialchars(Request::instance()->post('zhaiyao')), 'comment_status' => Request::instance()->post('pinglun'), 'post_modified' => date("Y-m-d H:i:s"), 'post_type' => Request::instance()->post('xingshi'), 'thumbnail' => Request::instance()->post('suolvetu'), 'istop' => Request::instance()->post('zhiding'), 'recommended' => Request::instance()->post('tuijian')];
    我们可以看到在这里的。能够给用户看到的参数    该过滤的已经过滤了。正常情况下呢。是不会存在xss了。但是呢。开发者可能忽略了一个地方。就是:'thumbnail' => Request::instance()->post('suolvetu')。这里呢。是获取的图片缩略图内容。如果上传了图片则有值。否则就为空。但是呢。由于前面并没有对该值做限制。所以呢这里我们是可以任意的构造POST参数的。首先我们先定位到POST这个方法来看看。
    [AppleScript] 纯文本查看 复制代码
    <?php
        /**
         * 设置获取获取POST参数
         * [url=home.php?mod=space&uid=65943]@Access[/url] public
         * @param string        $name 变量名
         * @param mixed         $default 默认值
         * @param string|array  $filter 过滤方法
         * [url=home.php?mod=space&uid=126298]@return[/url] mixed
         */
        public function post($name = '', $default = null, $filter = null)
        {
            if (empty($this->post)) {
                $this->post = $_POST;
            }
            if (is_array($name)) {
                $this->param       = [];
                return $this->post = array_merge($this->post, $name);
            }
            return $this->input($this->post, $name, $default, $filter);
        }
    对应这个方法。如果单单传一个参数进来。那么将不会进行过滤的。我们可以看到。$filter默认是等于null的,如果$filter不传的话则为null,所以我们这里可以直接插入xss代码。只要在POST参数插入:&suolvetu="/><script>alert('xss')</script> 即可
    6.png
    我们使用管理员进入后台。看看是否触发。
    7.png
    成功触发鸟。
    8.png

    PS:本着交流分享。如果有好的方法或者思路以及上文讲述不正确的地方欢迎指出。谢谢!

    喜欢兔兔的小小艾!
    喧嚣如梦 i春秋-核心白帽 行动比空谈更具有说服力! 核心白帽 积极活跃奖
    沙发
    发表于 2017-9-10 23:13:12
    学习学习。。。。。
    行动比空谈更具有说服力!
    使用道具 举报 回复
    发表于 2017-9-11 06:05:13
    看着都觉得是
    使用道具 举报 回复
    表哥厉害
    使用道具 举报 回复
    发表于 2017-9-11 09:00:47
    学习一波
    使用道具 举报 回复
    发表于 2017-9-11 09:04:10
    +666666666
    使用道具 举报 回复
    发表于 2017-9-11 10:11:50
    这个NIUBI
    使用道具 举报 回复
    发表于 2017-9-13 10:21:03
    这个可以,学习了
    使用道具 举报 回复
    发表于 2017-9-13 22:41:42
    代码审计,six
    hackerwing.com——余生,请多指教。
    使用道具 举报 回复
    看着都觉得是
    使用道具 举报 回复
    发新帖
    您需要登录后才可以回帖 登录 | 立即注册