某cms复现学习

前言
感觉自己还是对php审计有点不懂,遂找了个cms复现了一下几个类型的洞,本人小白一个,大佬请绕道嘻嘻。

正文
小插曲:首先源码拉下来本地搭建的时候死活不行,后来看了index发现,原来判断了install下是否存在install.lock防止重装,而源码拉下来的时候就已经存在install.lock了。
有些是参考的,有的没有查到相关的只能自己硬着头皮找了。

第一处:sqli
进后台随便点点,看下这请求,
GET /tuzicms-master/index.php/Manage/Download/index/id/11 HTTP/1.1
这路由各位师傅们应该都懂了。
在App/Manage/Controller/AdvertController.class.php中


id直接进行了拼接,验证:
image

数据库用户信息:
image

后面发现很多controller中都是用id=$id写的,便全局搜索:
image

发现有20多个,去相关漏洞信息库上搜索了一下,发现也确实有这么多的提交。

第二处getshell
在cnvd上发现:


然后全局搜索:

<pre style="padding: 16px; font: 12.75px / 1.6 Consolas, "Liberation Mono", Menlo, Courier, monospace; color: rgb(51, 51, 51); border-radius: 3px; display: block; margin: 0px; word-break: normal; overflow-wrap: normal; white-space: pre-wrap; background-color: rgb(247, 247, 247); border: 1px solid rgba(0, 0, 0, 0.15); box-sizing: border-box; overflow: auto;">_fe
</pre>


发现是一个设置分页配置信息的:

<pre style="padding: 16px; font: 12.75px / 1.6 Consolas, "Liberation Mono", Menlo, Courier, monospace; color: rgb(51, 51, 51); border-radius: 3px; display: block; margin: 0px; word-break: normal; overflow-wrap: normal; white-space: pre-wrap; background-color: rgb(247, 247, 247); border: 1px solid rgba(0, 0, 0, 0.15); box-sizing: border-box; overflow: auto;">public function do_fenye() {
//**判断是否有限权,显示登录管理员信息
id=_SESSION['id'];
//dump(id); //exit;m=D('Admin');
arr=m->find(id);arr=arr['admin_type']; //dump(arr);
//exit;
if (arr==1){// 如果不是超级管理员限权this->error('你不是超级管理员,没有限权!');
}
//exit;

//定义配置文件的路径
setfile=CONF_PATH."config_fenye.php"; // dump(setfile);
// exit;

//文章模型分页参数
arr=C('PAGE_ARTICLE__HOME');cache_index=array(
'PAGE_ARTICLE__HOME' => $arr,
);

cache_index_post=array( 'PAGE_ARTICLE__HOME' => I('post.PAGE_ARTICLE__HOME'), ); //合并数组cache_index_ok=array_merge(cache_index,cache_index_post);

//产品模型分页参数
arr=C('PAGE_PRODUCT__HOME');cache_group=array(
'PAGE_PRODUCT__HOME' => $arr,
);

cache_group_post=array( 'PAGE_PRODUCT__HOME' => I('post.PAGE_PRODUCT__HOME'), ); //合并数组cache_group_ok=array_merge(cache_group,cache_group_post);

//图片模型分页参数
arr=C('PAGE_PHOTO__HOME');cache_detail=array(
'PAGE_PHOTO__HOME' => $arr,
);

cache_detail_post=array( 'PAGE_PHOTO__HOME' => I('post.PAGE_PHOTO__HOME'), ); //合并数组cache_detail_ok=array_merge(cache_detail,cache_detail_post);

//下载模型分页参数
arr=C('PAGE_DOWNLOAD__HOME');download_detail=array(
'PAGE_DOWNLOAD__HOME' => $arr,
);

download_detail_post=array( 'PAGE_DOWNLOAD__HOME' => I('post.PAGE_DOWNLOAD__HOME'), ); //合并数组download_detail_ok=array_merge(download_detail,download_detail_post);

//将配置文件的结构列出来,然后把要修改的参数用变量代替,执行覆盖操作即可。
settingstr="<?php \n return array(\n"; foreach(c as key=>v){
settingstr.= "\t'".key."'=>".$v.",\n";
}

foreach(cache_index_ok askey=>v){settingstr.= "\n\t'".key."'=>'".v."',\n";
}
foreach(cache_group_ok askey=>v){settingstr.= "\n\t'".key."'=>'".v."',\n";
}
foreach(cache_detail_ok askey=>v){settingstr.= "\n\t'".key."'=>'".v."',\n";
}

foreach(download_detail_ok askey=>v){settingstr.= "\n\t'".key."'=>'".v."',\n";
}

$settingstr.="\n);\n?>\n";

// dump($settingstr);
// exit;

if (file_put_contents(setfile,settingstr)){//通过file_put_contents保存setting.config.php文件
this->success('修改成功'); }else {this->error('修改失败,请修改要更改文件的权限!');
}

}
</pre>

可以看到后面存在了很多拼接,通过setfile=CONF_PATH."config_fenye.php";发现配置文件为 [![image](https://upload-images.jianshu.io/upload_images/27712517-db58c00eb7e32de3.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)](https://xzfile.aliyuncs.com/media/upload/picture/20220201150632-7c190fb2-832d-1.png) 看第一个配置: [![image](https://upload-images.jianshu.io/upload_images/27712517-9b8b7d23eb1404ad.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)](https://xzfile.aliyuncs.com/media/upload/picture/20220201150730-9f2b5334-832d-1.png) 实际上就是post一个 PAGE_ARTICLE__HOME, 通过C()获取的arr被array_merge覆盖了
再看I():


获取传递的变量,其中有个$filter,没有指定一般是默认,
image

搜索一下:
image

这两个htmlspecialchars,strip_tags对'的效果:
image

因此可以闭合来写shell:
image

image

第三处任意文件删除
后台delSqlFiles():


直接拼接,没什么好说的
image

第四处前台反射xss
payload:
GET index.php/article/group/id/2/" onmouseover=alert(/xss/) /


一般这种大概流程就是输入-数据库-返回-调用模板-解析-返回前台(理解比较浅显),然后调试跟踪到返回url赋值的地方:
image

前面是APP拼接,值已经是:
image

再往回走发现,APP在这里定义:
image

那往回看PHP_FILE

<pre style="padding: 16px; font: 12.75px / 1.6 Consolas, "Liberation Mono", Menlo, Courier, monospace; color: rgb(51, 51, 51); border-radius: 3px; display: block; margin: 0px; word-break: normal; overflow-wrap: normal; white-space: pre-wrap; background-color: rgb(247, 247, 247); border: 1px solid rgba(0, 0, 0, 0.15); box-sizing: border-box; overflow: auto;">if(!defined('APP')){
urlMode = C('URL_MODEL'); if(urlMode == URL_COMPAT ){// 兼容模式判断
define('PHP_FILE',PHP_FILE.'?'.varPath.'='); }elseif(urlMode == URL_REWRITE ) {
url = dirname(_PHP_FILE_); if(url == '/' || url == '\\')url = '';
define('PHP_FILE',$url);
}else {
define('PHP_FILE',PHP_FILE);
}
</pre>

又是通过PHP_FILE定义
再往回走,


发现直接通过_SERVER['SCRIPT_NAME']来定义 而一开始 [![image](https://upload-images.jianshu.io/upload_images/27712517-c67d109b83917649.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)](https://xzfile.aliyuncs.com/media/upload/picture/20220202104253-d201492c-83d1-1.png) SCRIPT_NAME的就已经包含payload了,百度搜索了一波,发现 [_SERVER[SCRIPT_NAME]变量可值注入恶意代码](https://www.freebuf.com/articles/web/166263.html "$_SERVER[SCRIPT_NAME]变量可值注入恶意代码")
这个xss大概分析了一下,感谢,又学到了。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容