0x01 前言
查资料的时候,偶然间看到这样一个漏洞,在一个提交表单的地方,插入SQL语句,便可以进行报错注入。看着有点像二次注入,对于这样类型的注入,我个人遇到的还是比较少的,再加上一般这种地方多数会尝试XSS,所以进行了分析,看看漏洞到底是如何产生的。
0x02 环境搭建
1、首先准备phpstudy,这里使用的是2016版本的,php版本为5.6.27
2、下载cms源码
cms下载地址:
http://www.lmxcms.com/file/d/down/xitong/20210628/202106281714266126.zip
3、访问http://192.168.150.8/install/进行安装
4、输入相应信息即可。
注意:需要提前创建好数据库
0x03 漏洞复现
1、访问http://192.168.150.8/admin.php?m=Login,输入账号密码进入后台
2、在采集管理功能处点击创建节点
3、payload如下:
1' and updatexml(0,concat(0x7e,database()),1) and '
4、经测试节点名字和备注均能够触发漏洞
1)备注功能点触发
2)节点名字功能点触发
0x04 漏洞分析
1、因为漏洞是sql注入,所以首先可以使用数据库语句监控工具进行监控执行的语句。这里我使用的是seay自带的数据库监控工具。
2、输入账号密码,点击下断
3、发送sql注入的数据包后,点击更新
4、可以看到是一个插入数据库的语句
INSERT INTO lmx_cj(name,mid,content) VALUES('11111111111111111111111','1','1' and updatexml(0,concat(0x7e,database()),1) and '')
5、后面的数据包中可以看到是进行了查询
6、这里很明显就是一个插入数据库的功能,将数据插入到lmx_cj表中,因为updatexml函数导致了报错。查看这个数据表,里面是没有数据的。
7、插入正常的字符串,里面成功添加了数据。
8、那么下面开始代码分析,从数据包中很明显可以看到访问的路径为admin.php?&m=Acquisi&a=add。分析过MVP框架的代码便可以很明显看出一个是对应的文件Acquisi,里面调用了add函数。
先来查看一下admin.php文件,里面包含了/inc/config.inc.php和/inc/run.inc.php两个文件。
9、分别打开2个文件查看,跟文件名上表示的一样,一个是配置,一个是路由
10、其中有一个地方值得注意一下,action即方法是放在根目录下或者extend/目录下的c文件夹中,同理model即模块是放在m文件夹中。
然后就是执行问题了,这里可以看到区分了伪静态和单入口,大体意思其实跟tp框架的很像,一者是/模板/方法/参数名/参数值,一者是/?m=模板&a=方法
看最后面
eval('$action=new '.$m.$extendEnt.'();');
这里就是可以定位到漏洞文件所在的地方,很明显传入的m的值为Acquisi,所以这个请求对应的类为AcquisiAction()
11、在/c/admin/AcquisiAction.class.php找到了它
12、在add方法中可以看到,其实就是检测了是不是有从post请求中传入add,并且在data中的name对应的值不为空。其中存在几个函数分别是d()、p()、add()
13、定位一下d()方法,使用foreach函数,数组键分别赋值,看前面可以知道fieldCj就是一个name,mid,content的数组;$type这里有一个很重要的(int)类型强制转换,$is_int为传入的数组mid,并且$v为mid时,将其进行强制转换,也就是post包中传入的mid固定为整型。
14、再看一下p()方法,$type=1,$_POST传入的数据赋值给$data;因为前面只传入了一个1,所以$pe、$sql、$mysql均为false;下面在代码注释中进行说明。
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); //首尾去空后赋值给数组newdata[]
}
}
}
return $newdata;
}
15、前面对数据处理完之后,调用了这个类的modle中的add()方法
$this->model->add($data);
所以我们需要在m文件夹中寻找Acquisi的model文件
16、打开一看,第一个函数add就是我们需要的
17、右键,选择定位函数(其实使用phpstorm快一点,奈何我这个是虚拟机,没有那个条件装那么大的软件)
18、很幸运,只有一个,不用进行筛选了
19、调用了一个新函数addDB,从字面上的意思理解是添加到数据库,继续定位函数
20、找到函数之后进行分析,首先将数据进行键值分离,然后存入到数组field[]和value[]中,关于implode()函数的用法,我百度了一下,可以理解为使用逗号将数组中的每个值进行连接。然后,就放入到sql语句中了。
21、然后是执行query函数,将sql语句直接执行,如果没有返回结果就将错误信息返回。
22、总结一下利用链
首先从admin.php文件 -> 再到/inc/run.inc.php文件 -> 然后调用了传入的m参数值AcquisiAction类 -> AcquisiAction类中的add() -> 对数据经过一些处理,调用了d()、p()函数 -> 调用AcquisiAction类对应的Model中的add方法 -> 调用addModel() -> 调用addDB() -> 在addDB方法中进行了数组的转换就直接放入到sql语句中 ->调用了query()方法,执行了sql语句,然后如果执行结果为空,则将错误打印出来。
23、分析之后我发现一个有意思的东西,既然没有经过任何过滤,那么是不是存在存储型XSS漏洞呢,试了一下,确实存在。
两个参数均存在。
0x05 总结
分析完一条完整的利用链了,漏洞利用那么简单,但是实际分析确实还是有一点难的,当然如果有PHPstrom可能会好一些,函数之间的跳转会方便点,并且可以通过截断数据进行debug调试,也比这样轻松。但是总的来说还是成功分析完了,这里其实有一些地方的分析还是存在不足之处的,也希望大家体谅小白对代码的熟练度还不够。
小彩蛋:
因为页面会直接返回错误语句,那么这里不就也存在XSS漏洞了?let me try try~
首先单引号让数据报错,然后后面插入xss payload
'<img src=1 onerror=alert(1)>
然后,在位置2它出现了~
查看了一下,位置1没有触发是因为<不见了
那么尝试一下闭合,成功触发。
')<img src=1 onerror=alert(1)>'