朋友的公司购买了kingcms的授权,最近kingcms官方给我朋友发来了升级包,升级说明当中说已经解决了已知的安全问题,今天再帮朋友测试下。
自从朋友购买,已经经过了9.00.0015,9.00.0016,9.00.0017,现在更新到了9.00.0018,在线升级的话可以升级到9.00.0019了,kingcms服务还不错。9.00.0018的更新时间是2015.07.23,9.00.0019的更新应该是最近几天的事情。见官网http://**.**.**.**/download/k9/
版本信息
另:由于kingcms使用的是云后台,安装过程与一般的cms有点不同,复现时安装请参考官方:http://**.**.**.**/k9/t3012/ (特别是安装的后面部分操作)
既然是绕过补丁,那还是先来回顾一下以前的版本是如何过滤的,主要包括9.00.0014及以前,9.00.0015版,9.00.0016-9.00.0018版。我们来具体研究学习一下:
9.00.0014版及以前各版本:
直接获得用户提交的参数,没有过滤,直接带入了SQL执行。
9.00.0015版:
由于我已前提交的漏洞已经公开,在9.00.0015版中添加了过滤,打了补丁,这里只把过滤方法拿出来,方便后面对比。之前的绕过防注可以看这里http://**.**.**.**/bugs/wooyun-2015-0100601
9.00.0016-9.00.0019版:由于上面的补丁被成功绕过,kingcms又进行了修复更新,具体的补丁是这样的。
可以看到这两次补丁的最大不同就是最新版过滤了/**/,只所以过滤/**/,是因为我在9.00.0015版中使用/**/绕过了kingcms使用正则表达式进行防注过滤的补丁,这次提交的漏洞将绕过kingcms的最新补丁进行注入。
注入点:GET
这个注入点比较奇怪,因为数据库执行的语句全部都由用户输入,但是经过了base64编码,base64_decode后就可以绕过第一层的过滤了。
注入参数:data_one,data,count,newid,getdir,getfile
下面以data为例进行说明
问题文件在/api/conn.php
首先要绕过上面代码中的权限判断,其实就是计算出$sign1,然后使$_GET[‘SIGN’]与之相等即可。来看看$sign1是如何计算出来的
参与计算的参数只有kc_config('system.salt')不是用户输入的,但是kingcms的这个参数是空,此因所有参与计算的参数都是用户输入的,按上面的算法简单计算一下就知道$sign1了,然后输入的$_GET[‘SIGN’]等于$sign1即可绕过权限判断。
然后执行下面的代码
又执行了下面的代码
在这个函数里执行了safecheck($sql),就是上面我们分析的防注方法
通过分析代码我们有了以下基本想法:
1、当str_replace把/**/过滤掉以后的语句,不能与$disablesql 正则匹配
2、构造的sql语句能被符合sql的语法规则。
最开始想使用/*/**/*/,当str_replace把中间的/**/去掉以后,正好剩下/**/,这样可以组成类似于(/**/select......这样的语句,不会被\(select|的正则匹配,但是/*/**/*/是错误的sql注释方法,sql语法有错误,因此不能绕过。
然后又想到使用/***/,str_replace('/**/', '', $sql)对/***/无效,而/***/在sql语句中与/**/作用相同,可以起到一个空格的作用,不影响sql语句的正常执行。成功绕过。
提交的payload要经过base64_decode处理,因此在提交前先base64_encode一下就可以了。
Kingcms可以报错,因此
编码前Payload:
编码后Payload:
注入成功,见下图