写在前面:漏洞存在于用户发送站内信的地方,因此,测试时需要注册一个前台的普通用户。
朋友的公司购买了kingcms的授权,最近kingcms官方给我朋友发来了升级包,升级说明当中说已经解决了已知的安全问题,今天再帮朋友测试下。
自从朋友购买,已经经过了9.00.0015,9.00.0016,9.00.0017,现在更新到了9.00.0018,kingcms服务还不错。9.00.0018的更新时间是2015.07.23,见官网http://www.kingcms.com/download/k9/
另:由于kingcms使用的是云后台,安装过程与一般的cms有点不同,复现时安装请参考官方:http://www.focuznet.com/k9/t3012/ (特别是安装的后面部分操作)
既然是绕过补丁,那还是先来回顾一下以前的过滤版本,主要包括9.00.0014及以前,9.00.0015版,9.00.0016-9.00.0018版。我们来具体研究学习一下:
9.00.0014版及以前各版本:
直接获得用户提交的$where参数,没有过滤,直接带入了SQL执行。
9.00.0015版:
由于我已前提交的漏洞已经公开,在9.00.0015版中添加了过滤,打了补丁,这里只把过滤方法拿出来,方便后面对比。
9.00.0016-9.00.0018版:
由于上面的补丁被成功绕过,kingcms又进行了修复更新,具体的补丁是这样的。
可以看到这两次补本的最大不同就是最新版过滤了/**/,只所以过滤/**/,是因为我在9.00.0015版中使用/**/绕过了kingcms使用正则表达式进行防注过滤的补丁,这次提交的漏洞将绕过kingcms的最新补丁进行注入。
注入点:POST /user/pm.php?CMD=post
注入参数:username 问题文件在/user/pm.php
可以看到kingmcs使用preg_split对username进行了处理,我们分析一下这个正则,它的作用是通过空格或逗号把username进行分隔,因此,我们的exp中不能出现空格符和逗号。然后执行了getRows(),跟进
执行了$this->get($sql),去看看$this->get
执行了query(),跟进
在query()中首先执行了$this->safecheck($sql),这个就是过滤方法,也是本次测试中要重点突破的过渡方法。
通过分析代码我们有了以下基本想法:
1、当str_replace把/**/过滤掉以后的语句,不能与$disablesql 正则匹配
2、构造的sql语句能被符合sql的语法规则。
最开始想使用/*/**/*/,当str_replace把中间的/**/去掉以后,正好剩下/**/,这样可以组成类似于(/**/select......这样的语句,不会被\(select|的正则匹配,但是/*/**/*/是错误的sql注释方法,sql语法有错误,因此不能绕过。
然后又想到使用/***/,str_replace('/**/', '', $sql)对/***/无效,而/***/在sql语句中与/**/作用相同,可以起到一个空格的作用,不影响sql语句的正常执行。成功绕过。
这里我们使用time-based injection,又因为不能使用空格和逗号,因此Payload如下:
假时:
真时:
整个注入过程可以使用burpsuite 或者sqlmap 再或者自己写个脚本来跑,在本地进行测试,用户名为admin,密码为f6fdffe48c908deb0f4c3bd36c032e72