理解这个漏洞呢,首先要了解一下在线支付的流程,这里引用一下云网官方的流程图:
正常的在线支付过程呢,是从第一步到第六步!
而这个漏洞所出现的地方就是在第二步,然后绕过了第三步和第四步、第五步,而直接把返回信息提交给了支付成功返回页面!
我们在动画里也只是看到了!它只有一个提交页面和网站上的一个支付成功页面,根本没有通过网关进行支付操作,所以钱也就没进入到银行里,这里也就不存在什么影响银行安全什么了,纯粹是骗人的了!
为什么会这样呢!问题出在云网提供给商户的支付接口文件上,让我们来看看这两个云网提供给商户的接口文件:
〈%
’*******************************************
’文件名:SendOrder.asp
’主要功能:该示范程序主要完成将商户订单信息提交至云网支付网关的功能
’版本:v1.6(Build2005-05-24)
’描述:假设商户的订单系统都已完成,本页面主要是帮助商户按照云网支付网关要求的格式将订单信息提交至云网支付@网的支付接口,进行支付操作
’版权所有:北京云网无限网络技术有限公司
’*******************************************
’---订单信息---
Dim c_mid ’商户编号,在申请商户成功后即可获得,可以在申请商户成功的邮件中获取该编号
Dim c_order ’商户网站生成的订单号,不能重复
Dim c_name ’商户订单中的收货人姓名
Dim c_address ’商户订单中的收货人地址
Dim c_tel ’商户订单中的收货人电话
Dim c_post ’商户订单中的收货人邮编
Dim c_email ’商户订单中的收货人Email
Dim c_orderamount ’商户订单总金额
Dim c_ymd ’商户订单的产生日期,格式为"yyyymmdd",如20050102
Dim c_moneytype ’支付币种,0为人民币
Dim c_retflag ’商户订单支付成功后是否需要返回商户指定的文件,0:不用返回 1:需要返回
Dim c_paygate ’如果在商户网站选择银行则设置该值,具体值可参见《云网支付@网技术接口手册》附录一;如果来云网支付@网选择银行此项为空值。
Dim c_returl ’如果c_retflag为1时,该值代表支付成功后返回的文件的路径
Dim c_memo1 ’商户需要在支付结果通知中转发的商户参数一
Dim c_memo2 ’商户需要在支付结果通知中转发的商户参数二
Dim c_signstr ’商户对订单信息进行MD5签名后的字符串
Dim c_pass ’支付密钥,请登录商户管理后台,在帐户信息-〉基本信息-〉安全信息中的支付密钥项
Dim notifytype ’0普通通知方式/1服务器通知方式,空值为普通通知方式
Dim c_language ’对启用了国际卡支付时,可使用该值定义消费者在银行支付时的页面语种,值为:0银行页面显示为中文/1银行页面显示为英文
c_mid = "000103"
c_order = "12345"
c_name = "张三"
c_address = "北京市朝阳区XX"
c_tel = "010-12345678"
c_post = "100001"
c_email = "zhangsan@test.com"
c_orderamount = "0.01"
c_ymd = "20050102"
c_moneytype = "0"
c_retflag = "1"
c_paygate = ""
c_returl = "http:// www.2cto.com /xxx/xxx.asp" ’该地址为商户接收云网支付结果通知的页面,请提交完整文件名
c_memo1 = "ABCDE"
c_memo2 = "12345"
c_pass = "Test"
notifytype = "0"
c_language = "0"
srcStr = c_mid & c_order & c_orderamount & c_ymd & c_moneytype & c_retflag &
c_returl & c_paygate & c_memo1 & c_memo2 & notifytype & c_language & c_pass
’说明:如果您想指定支付方式(c_paygate)的值时,需要先让用户选择支付方式,然后再根据用户选择的结果在这里进行MD5加密,也就是说,此时,本页面应该拆分为两个页面,分为两个步骤完成。
’---对订单信息进行MD5加密
c_signstr = MD5(srcStr)
%〉
〈table width="85%" border="0" align="center" cellpadding="0" cellspacing="0"〉
〈tr〉
〈td align="center"〉
〈form name="payForm1" action="https://www.cncard.net/purchase/getorder.asp" method="POST"〉
〈input type="hidden" name="c_mid" value="〈%=c_mid%〉"〉
〈input type="hidden" name="c_order" value="〈%=c_order%〉"〉
〈input type="hidden" name="c_name" value="〈%=c_name%〉"〉
〈input type="hidden" name="c_address" value="〈%=c_address%〉"〉
〈input type="hidden" name="c_tel" value="〈%=c_tel%〉"〉
〈input type="hidden" name="c_post" value="〈%=c_post%〉"〉
〈input type="hidden" name="c_email" value="〈%=c_email%〉"〉
〈input type="hidden" name="c_orderamount" value="〈%=c_orderamount%〉"〉
〈input type="hidden" name="c_ymd" value="〈%=c_ymd%〉"〉
〈input type="hidden" name="c_moneytype" value="〈%=c_moneytype%〉"〉
〈input type="hidden" name="c_retflag" value="〈%=c_retflag%〉"〉
〈input type="hidden" name="c_paygate" value="〈%=c_paygate%〉"〉
〈input type="hidden" name="c_returl" value="〈%=c_returl%〉"〉
〈input type="hidden" name="c_memo1" value="〈%=c_memo1%〉"〉
〈input type="hidden" name="c_memo2" value="〈%=c_memo2%〉"〉
〈input type="hidden" name="c_language" value="〈%=c_language%〉"〉
〈input type="hidden" name="notifytype" value="〈%=notifytype%〉"〉
〈input type="hidden" name="c_signstr" value="〈%=c_signstr%〉"〉
〈input type="submit" name="submit" value="点击-〉 云网支付@网"〉
〈/form〉
〈/td〉
〈/tr〉
〈/table〉
这个是向云网网关提交订单信息的页面中的一些关键的代码!注意下他这个变量:c_signstr,
以及他的生成方式,是订单的几个信息连接后再md5加密后生成验证签名的!而这个签名是一个关键
但是从下面的提交表单可以看到,他们都是以明文的方式来提交的!当然要用明文了,如果加密的话,在后面就该出问题了!
下面我们来看订单成功后获取银行返回的成功信息的页面代码:
〈%
’*******************************************
’文件名:GetPayNotIFy.asp
’主要功能:该示范程序主要完成接收云网支付网关支付通知信息,验证信息有效性,判断支付结果功能
’版本:v1.6(Build2005-05-24)
’说明:
’ 1.本页面请不要使用诸如response.redirect等页面转向的语句
’ 2.请直接将订单处理结果以HTML代码的形式输出在本页,云网支付网关会采用技术手段获取您的输出结果
’ 3.本页面如果含有图片、样式或链接,请将路径或地址包括域名,比如〈img src="/pic/15/a2005-12-21-580a.gif"〉
’版权所有:北京云网无限网络技术有限公司
’*******************************************
’---获取云网支付网关向商户发送的支付通知信息(以下简称为通知信息)
c_mid = request("c_mid") ’商户编号,在申请商户成功后即可获得,可以在申请商户成功的邮件中获取该编号
c_order = request("c_order") ’商户提供的订单号
c_orderamount = request("c_orderamount") ’商户提供的订单总金额,以元为单位,小数点后保留两位,如:13.05
c_ymd = request("c_ymd") ’商户传输过来的订单产生日期,格式为"yyyymmdd",如20050102
c_transnum = request("c_transnum") ’云网支付网关提供的该笔订单的交易流水号,供日后查询、核对使用;
c_succmark = request("c_succmark") ’交易成功标志,Y-成功 N-失败
c_moneytype = request("c_moneytype") ’支付币种,0为人民币
c_cause = request("c_cause") ’如果订单支付失败,则该值代表失败原因
c_memo1 = request("c_memo1") ’商户提供的需要在支付结果通知中转发的商户参数一
c_memo2 = request("c_memo2") ’商户提供的需要在支付结果通知中转发的商户参数二
c_signstr = request("c_signstr") ’云网支付网关对已上信息进行MD5加密后的字符串
’---校验信息完整性---
IF c_mid="" or c_order="" or c_orderamount="" or c_ymd="" or c_moneytype="" or
c_transnum="" or c_succmark="" or c_signstr="" THEN
response.write "支付信息有误"
response.end
END IF
’---将获得的通知信息拼成字符串,作为准备进行MD5加密的源串,需要注意的是,在拼串时,先后顺序不能改变
Dim c_pass ’商户的支付密钥,登录商户管理后台(https://www.cncard.net/admin/),在管理首页可找到该值
c_pass = "Test"
srcStr = c_mid & c_order & c_orderamount & c_ymd & c_transnum & c_succmark
& c_moneytype & c_memo1 & c_memo2 & c_pass
’---对支付通知信息进行MD5加密
r_signstr = MD5(srcStr)
’---校验商户网站对通知信息的MD5加密的结果和云网支付网关提供的MD5加密结果是否一致
IF r_signstr〈〉c_signstr THEN
response.write "签名验证失败"
response.end
END IF
’---校验商户编号
Dim MerchantID ’商户自己的编号
IF MerchantID〈〉c_mid THEN
response.write "提交的商户编号有误"
response.end
END IF
’---校验商户订单系统中是否有通知信息返回的订单信息
Dim conn ’商户系统的数据链接
sql="select top 1 数据列 from 商户的订单表 where 商户订单号="& c_order
set rs=server.CreateObject("adodb.recordset")
rs.open sql,conn
IF rs.eof THEN
response.write "未找到该订单信息"
response.end
END IF
’---校验商户订单系统中记录的订单金额和云网支付网关通知信息中的金额是否一致
Dim r_orderamount ’商户自己系统记录的订单金额
r_orderamount=rs("订单金额") ’商户从自己订单系统获取该值
IF ccur(r_orderamount)〈〉ccur(c_orderamount) THEN
response.write "支付金额有误"
response.end
END IF
’---校验商户订单系统中记录的订单生成日期和云网支付网关通知信息中的订单生成日期是否一致
Dim r_ymd ’商户自己系统记录的订单生成日期
r_ymd=rs("订单生成日期") ’商户从自己订单系统获取该值
IF r_ymd〈〉c_ymd THEN
response.write "订单时间有误"
response.end
END IF
’---校验商户系统中记录的需要在支付结果通知中转发的参数和云网支付网关通知信息中提供的参数是否一致
Dim r_memo1 ’商户自己系统记录的需要在支付结果通知中转发的参数一
r_memo1 = rs("转发参数一")
Dim r_memo2 ’商户自己系统记录的需要在支付结果通知中转发的参二
r_memo2 = rs("转发参数二")
IF r_memo1〈〉c_memo1 or r_memo2〈〉c_memo2 THEN
response.write "参数提交有误"
response.end
END IF
’---校验返回的支付结果的格式是否正确
IF c_succmark〈〉"Y" and c_succmark〈〉"N" THEN
response.write "参数提交有误"
response.end
END IF
’---根据返回的支付结果,商户进行自己的发货等操作
IF c_succmark="Y" THEN
’根据商户自己商务规则,进行发货等系列操作
END IF
%〉
我们可以看到他的验证签名的方式,是将银行反馈过来的信息链接后和在提交页面提交的信息,
先看签名是如何验证的:
’---将获得的通知信息拼成字符串,作为准备进行MD5加密的源串,需要注意的是,在拼串时,先后顺序不能改变
Dim c_pass ’商户的支付密钥,登录商户管理后台(https://www.cncard.net/admin/),在管理首页可找到该值
c_pass = "Test"
srcStr = c_mid & c_order & c_orderamount & c_ymd & c_transnum
& c_succmark & c_moneytype & c_memo1 & c_memo2 & c_pass
’---对支付通知信息进行MD5加密
r_signstr = MD5(srcStr)
’---校验商户网站对通知信息的MD5加密的结果和云网支付网关提供的MD5加密结果是否一致
IF r_signstr〈〉c_signstr THEN
response.write "签名验证失败"
response.end
END IF
是通过提交的这些信息加密后来验证的,而商户的支付密钥,我们可以在提交页面获取到!而这里他程序需要添加上去的!
我们就不需要了,我们需要的只是让r_signstr等于c_signstr 就可以搞定它了!欺骗方法我就不说了!
至于其他的欺骗,不存在加密了,全部明文的了!很容易就过去了!
ps:这个作者当时还发了一个别的也是在线支付漏洞的动画,我看都没有看就删了.你信这个动画吗?反正我是不信!
作者 http://neeao.com/archives/92/