在线支付流程安全分析与支付漏洞总结
前言
大家对支付漏洞的理解通常都是篡改价格,已有的对支付漏洞的总结也是对现有的一些案例的经验式归类,没有上升到对在线支付流程深入分析的一个层面。这里尝试从分析在线支付流程,在线支付厂商的接入方式开始,深入业务分析整个在线交易流程中容易出现的安全问题。
支付宝/在线支付流程
支付宝即时到账接口开发流程
在线支付从功能上来说是通过支付宝的支付渠道,付款者直接汇款给另一个拥有支付宝账号的收款者。整个流程说明如下:引用自支付宝文档。
(1)构造请求数据
商户根据支付宝提供的接口规则,通过程序生成得到签名结果及要传输给支付宝的数据集合。
(2)发送请求数据
把构造完成的数据集合,通过页面链接跳转或表单提交的方式传递给支付宝。
(3)支付宝对请求数据进行处理
支付宝得到这些集合后,会先进行安全校验等验证,一系列验证通过后便会处理这次发送过来的数据请求。
(4)返回处理的结果数据
对于处理完成的交易,支付宝会以两种方式把数据反馈给商户网站。
程序上自动进行重新构造URL地址链接,在用户当前页面上通过自动跳转的方式跳回商户在请求时设定好的页面路径地址(参数return_url,如果商户没有设定,则不会进行该操作)
支付宝服务器主动发起通知,调用商户在请求时设定好的页面路径(参数notify_url,如果商户没有设定,则不会进行该操作)。
(5)对获取的返回结果数据进行处理
商户在同步通知处理页面(参数return_url指定页面文件)或服务器异步通知页面(参数notify_url指定页面文件)获取支付宝返回的结果数据后,可以结合自身网站的业务逻辑进行数据处理(如:订单更新、自动充值到会员账号中等)。
业务思考
通过这个流程可以知道。应用端做的两个重要步骤,一个是拼接支付的请求,返回给用户浏览器,用户浏览器请求支付宝接口,进入支付流程,整个支付的环节是和支付宝端交互,支付完成之后,支付宝通过通知接口给应用发送支付成功的通知。应用通过支付宝的通知信息来判断支付是否成功。
风险分析
首先第二步,发送请求数据。这一步虽然是在用户的浏览器端完成的。但是支付接口都有强制的签名来保证完整性,所以这里数据是无法篡改的,在签名key不泄露的情况下。所以通常见到的支付漏洞都是第一步,应用构造请求数据的时候出现的缺陷。
对于交易这一业务功能来讲,应用只需要用户提供商品id和商品数量就可以满足支付所需要的所有数据了。这个地方容易出现的问题主要有以下几种:
1,直接把订单的总金额从客户端获取,放在了构造的请求交易数据中。
2,虽然只传递商品id和数量,但是数量没有做白名单限制,造成可以输入负数或者大数造成计算溢出,导致最终计算的订单金额出现错误。
3,除了商品数量和商品id,还有其他参与订单金额计算的参数从客户端获取,比如运费等
第三步和第四步是支付宝进行的处理,所以也不存在问题。第五步,支付宝通知应用用户付款成功,这里支付宝设计了notify_id供应用来验证通知信息是否是有效的。但是一般很少见人用,因为这一步数据也是有签名的。只要应用对支付宝的通知信息进行签名验证就可以。但是这个验证是应用自己来控制的,并不像第二步是支付宝控制的进行签名验证,所以一旦应用没有对支付宝通知信息进行签名验证就会导致伪造支付宝的通知信息,欺骗应用支付成功的漏洞。这种类型的问题看到的案例比较少。比如我是如何1元再购特斯拉的。这种类型的问题应该也比较常见,可能是对这个逻辑的测试还不够关注。
所以通过分析整个在线支付的流程可以看到,容易出现支付漏洞的有两个点,一个是构造支付请求的阶段,一个是对返回的结果数据进行处理的阶段。没有对签名进行验证,会存在请求伪造和重放攻击。这里分析的是一个典型的支付流程,此外还有一些比较复杂的交易设计,比如设计了可以修改订单的功能等,随着功能的增加也会引入一些安全问题。
安全的设计方案:
只从客户端获取商品id和数量,对数量范围进行限制。对接受支付宝通知的接口对通知信息进行签名验证,对支付金额和订单金额进行对比以及验证支付订单号避免重放攻击。只要考虑到这几个问题,就可以设计一个比较安全的支付流程。
支付宝提供的验证方式
notifyid
total_fee
sign
order_no 防重放