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

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

缺陷编号:wooyun-2015-0102229

漏洞标题:KingCms最新版(k9)越权添加管理员

相关厂商:KingCms

漏洞作者: 路人甲

提交时间:2015-03-19 14:29

修复时间:2015-05-03 14:30

公开时间:2015-05-03 14:30

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

危害等级:中

自评Rank:10

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

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

Tags标签:

4人收藏 收藏
分享漏洞:


漏洞详情

披露状态:

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

简要描述:

KingCms最新版(k9)越权添加管理员

详细说明:

朋友的公司想购买kingcms的授权,让我帮忙看下。发现kingcms很长一段时间没更新了,憋了一段时间放出了最新版的k9,官网下下来学习一下。
在wooyun上看到了几个漏洞,如: WooYun: kingcms最新版sql注入漏洞
这里可越权添加管理员。
问题文件在/user/manage.php
0x00:先来看看获得相关权限的绕过方法吧
Kingcms使用
$u=new user;
$u->auth_role('admin');
来验证用户是否具有admin的权限,先来看看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。
$_GET['SIGN']也即$sign计算过程是这样的

<?php
$str="10000";//10000即POST参数中的USERID
$str.="kingcms.com";//网站域名
$SIGN=md5($str);
?>


在第4处注释处,因为$ischeck=false,所以,用户已登陆,USERID输入10000(kingcms系统的超级管理员id),就获得了管理员的所有权限了。
下面看看添加管理员的代码吧
/user/manage.php

function _edit(){
$u=new user;$u->auth_role('admin');
$userid=kc_post('userid',2,0);
$db=new db;
$str=new str;
if(empty($userid)){
if (empty($_POST['username'])) kc_tip('请填写用户名!','form');
if ($str->len($_POST['username'])>12) kc_tip('用户名太长,不能超过12字','form');
if(preg_match('/[<>\s\!\@\/\\\|\]\[\}\{\#\$\%\^\&\*\(\)\_\+\=\-]/',$_POST['username'])) kc_tip('用户名不能含有非法字符!','form');
$rs=$db->getRows_one('%s_user','userid','username=\''.$db->encode($_POST['username']).'\'');
if(!empty($rs)) kc_tip('您要添加的用户已经存在!','form');
}
if(empty($userid)){
if(empty($_POST['userpass'])) kc_tip('密码不能为空!','form');
}
if(!empty($_POST['username'])){
if (strlen($_POST['userpass'])>30) kc_tip('您的密码太长,不能超过30个字符!','form');
if($_POST['userpass1']<>$_POST['userpass']) kc_tip('两次输入的密码不一致!','form');
}

if(!empty($_POST['rid']) && !kc_validate($_POST['rid'],3)) kc_tip('所属角色参数错误!','form');
$rids=empty($_POST['rid']) ? array() : explode(',',$_POST['rid']);
foreach($rids as $rid){
if(!empty($_POST['role_removedate'.$rid]) && !kc_validate($_POST['role_removedate'.$rid],9)) kc_tip('有效日期格式不正确!','form');
}

if(!empty($_POST['gid']) && !kc_validate($_POST['gid'],3)) kc_tip('所属用户组参数错误!','form');
$gids=empty($_POST['gid']) ? array() : explode(',',$_POST['gid']);
foreach($gids as $gid){
if(!empty($_POST['group_removedate'.$gid]) && !kc_validate($_POST['group_removedate'.$gid],9)) kc_tip('有效日期格式不正确!','form');
}
if($str->len($_POST['name'])>20) kc_tip('真实姓名过长!','form');
if($str->len($_POST['tel'])>30) kc_tip('电话过长!','form');
if($str->len($_POST['email'])>50) kc_tip('邮箱过长!','form');
if(!empty($_POST['email']) && !kc_validate($_POST['email'],5)) kc_tip('邮箱地址格式','form');
if($str->len($_POST['qq'])>12) kc_tip('QQ号码过长!','form');
if($str->len($_POST['address'])>200) kc_tip('通信地址过长!','form');
if($str->len($_POST['qianming'])>250) kc_tip('个性签名过长!','form');
$array=array(
'name'=>$_POST['name'],
'tel'=>$_POST['tel'],
'email'=>$_POST['email'],
'qq'=>$_POST['qq'],
'address'=>$_POST['address'],
'qianming'=>$_POST['qianming'],
);

if(!empty($_POST['userpass'])) $array['userpass']=md5($_POST['userpass']);
if(empty($userid)){
$array['username']=$_POST['username'];
$array['regdate']=TIME;
$array['date']=TIME;
$array['regip']=$str->ip();
$array['ip']=$str->ip();
$userid=$db->insert('%s_user',$array);
kc_log(array('userid'=>$u->info['userid'],'app'=>'user','action'=>'USER_NEW','cid'=>$userid));
}else{
$db->update('%s_user',$array,'userid='.$userid);
$db->delete('%s_user_group_bind','userid='.$userid);
$db->delete('%s_user_role_bind','userid='.$userid);
kc_log(array('userid'=>$u->info['userid'],'app'=>'user','action'=>'USER_EDIT','cid'=>$userid));
}

//更新role和user绑定表信息
$array=array();
foreach($rids as $rid){
$removedate=empty($_POST['role_removedate'.$rid]) ? 0 :str_replace('-','',$_POST['role_removedate'.$rid]);
$array[]=array(
'userid'=>$userid,
'rid'=>$rid,
'removedate'=>$removedate,
);
}
$db->insert('%s_user_role_bind',$array,1);

//更新group和user绑定表信息
$array=array();
foreach($gids as $gid){
$removedate=empty($_POST['group_removedate'.$gid]) ? 0 :str_replace('-','',$_POST['group_removedate'.$gid]);
$array[]=array(
'userid'=>$userid,
'gid'=>$gid,
'removedate'=>$removedate,
);
}
$db->insert('%s_user_group_bind',$array,1);

$s='<ul class="goto">';
$s.='<li><a href="/?_=user">返回用户列表</a></li>';
$s.='<li><a href="javascript:;" onclick="$.kc_close();$(\'.Submit\').removeAttr(\'disabled\');">继续编辑</a></li>';
$s.='<li><a href="/?_=user_edit">+ 添加新用户</a></li>';
$s.='</ul>';
kc_ajax(array(
'TITLE'=>'继续您的操作',
'MAIN'=>$s,
'ID'=>'k_ajax',
'WIDTH'=>370,
'HEIGHT'=>120,
));
}


过程见下图

过程副本.jpg


添加成功后,登录,具有所有的权限哟

添加成功副本.jpg

漏洞证明:

见 详细说明

修复方案:

权限验证

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


漏洞回应

厂商回应:

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