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

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

缺陷编号:wooyun-2015-0100265

漏洞标题:KingCms最新版越权大礼包

相关厂商:KingCms

漏洞作者: 路人甲

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

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

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

漏洞类型:非授权访问/权限绕过

危害等级:高

自评Rank:15

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

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

Tags标签:

4人收藏 收藏
分享漏洞:


漏洞详情

披露状态:

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

简要描述:

KingCms最新版越权大礼包

详细说明:

朋友的公司想购买kingcms的授权,让我帮忙看下。发现kingcms很长一段时间没更新了,憋了一段时间放出了最新版的k9,官网下下来学习一下。
在wooyun看到了几个漏洞,如:http://wooyun.org/bugs/wooyun-2010-043520
这里的越权大礼包包括删除网站所有会员、重置所有会员密码、修改所有会员用户名。
0x00:先来看看获得相关权限的绕过方法吧
Kingcms使用
$u=new user;
$u->auth_role('XXX');
来验证用户是否具有XXX的权限,关键是user类。
/user/user.class.php,user的构造方法如下

public function __construct(){
$cookie=kc_cookie('userauth');
$cookiePass=substr($cookie,0,32);
$ischeck=true;
$GLOBALS['db']=new db;
$GLOBALS['str']=new str;
$GLOBALS['cache']=new cache;
global $db,$str;
if(empty($cookie) && !empty($_GET['jsoncallback'])
&& !empty($_GET['USERID']) && !empty($_GET['SIGN'])){ //第1处注释:这里很容易使条件成立,执行下面的if语句
$get_userid=$_GET['USERID'];
$get_sign=$_GET['SIGN'];
$sign=md5($get_userid.SITEURL.kc_config('system.salt'));
$userid = $sign==$get_sign ? $get_userid : 0; //第2处注释:这里是唯一的一次简单验证
$ischeck=false; //第3处注释:在下面第4处注释处会用到
}else{
$userid=substr($cookie,32);
}
if(!kc_validate($userid,2)) $userid=0;
if(empty($userid)){
$user=array('userpass'=>'x');
}else{
$user=$db->getRows_one('%s_user','*','userid='.$userid);
if(empty($user)) $user=array('userpass'=>'x');
}

//用户已登录
if (md5($user['userpass'])==$cookiePass || $ischeck==false) {//第4处注释
无关代码


上面代码的第二处注释的地方,要获得需要操作的userid,要计量$sign=md5($get_userid.SITEURL.kc_config('system.salt')); 其中的参数$get_userid是用户输入,SITEURL是当前域名,不包含www等二级域名,[小写],kc_config('system.salt')是系统默认的,定值。这样,这里就可以绕过了。使得$ischeck=false。
在第4处注释处,因为$ischeck=false,所以,用户已登陆,USERID输入10000(kingcms系统的超级管理员id),就获得了管理员的所有权限了。
0x01:下面看看如何删除所有会员
/user/manage.php

/**
* 删除会员
*/
function _delete(){
$u=new user;$u->auth_role('admin');
$userid=kc_post('userid',2,1);
if($u->info['userid']==$userid) kc_tip('不能删除自己!');
$db=new db;
$db->delete('%s_user','userid='.$userid);
kc_log(array('userid'=>$u->info['userid'],'app'=>'user','action'=>'USER_DELETE','cid'=>$userid));
kc_tip('删除成功!','ok','refresh');
}


控制userid,从10001开始,步进为1,遍历就可以把所有会员全部删除了。
过程见下图

删除会员副本.jpg


0x02:下面看看如何重置所有会员密码
/user/manage.php

function _resetpass(){
$u=new user;$u->auth_role('admin');
$userid=kc_post('userid',2,1);
if($userid==$u->info['userid']) kc_tip('要修改自己的密码,请点击“修改密码”!');

$str=new str;
$pwd=$str->random(10);
$db=new db;
$db->update('%s_user',array('userpass'=>md5($pwd)),'userid='.$userid);
kc_log(array('userid'=>$u->info['userid'],'app'=>'user','action'=>'USER_RESETPASS','cid'=>$userid));
kc_tip('成功设置用户密码为:'.$pwd,'ok');
}


控制userid,从10001开始,步进为1,遍历就可以把重置所有会员的密码了。
过程见下图

重置会员密码副本.jpg


0x03:下面看看如何修改所有会员用户名
/user/manage.php

function _rename(){
$u=new user;$u->auth_role('admin');
$userid=kc_post('userid',2,1);

$db=new db;
$rs=$db->getRows_one('%s_user','username','userid='.$userid);
if(empty($rs)) kc_tip('用户名记录已丢失!');

$str=new str;
if(empty($_POST['username'])) kc_tip('请填写用户名!','form');
if($_POST['username']==$rs['username']) kc_tip('新的用户名不能和旧用户名一致!','form');
if ($str->len($_POST['username'])>12) kc_tip('用户名太长,不能超过12字','form');
if(preg_match('/[<>\s\!\@\/\\\|\]\[\}\{\#\$\%\^\&\*\(\)\_\+\=\-]/',$_POST['username'])) kc_tip('用户名不能含有非法字符!','form');
$uname=$db->encode($_POST['username']);
if($db->getRows_one('%s_user','userid',"username='$uname' and userid<>$userid")) kc_tip('当前用户名已经存在!','form');
$array=array('username'=>$_POST['username']);
$db->update('%s_user',$array,'userid='.$userid);
$js="\$.kc_close();alert('成功修改用户名[{$rs['username']}]为[{$_POST['username']}]!');$('#form_publish [name=username]').val('{$_POST['username']}');";
kc_log(array('userid'=>$u->info['userid'],'app'=>'user','action'=>'USER_RENAME','cid'=>$userid));
kc_ajax(array('JS'=>$js));
}


控制userid和POST[‘username’],从10001开始,步进为1,遍历就可以修改所有会员的用户名了。
过程见下图

重命名会员副本.jpg

漏洞证明:

见 详细过程

修复方案:

修改验证方法

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


漏洞回应

厂商回应:

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