百度安全实验室:支付安全不能说的那些事儿(4)
这样一条消息会经过支付平台的签名,攻击者无法直接伪造。但是前面提到,所有商户使用同一个公钥验证来自支付平台的消息,也就是说支付平台发给商户evil的消息若转发给商户alice,签名可以通过验证,仅仅是商户号等参数值不正确。因此,攻击者可以考虑利用evil的支付结果来伪造给alice的支付结果。 攻击者首先发给支付平台一个属于商户Evil的订单消息 {“body”:“商品A&out_trade_no=12345&seller=alice&total_fee=100&trade_status=SUCCESS&z=”,“notify_url”:“http://evil.com/notify”, “out_trade_no”:”12345”,“seller”:“evil”, “total_fee”:“1”, “sign”:“XXXX”}, 支付1元后,http://evil.com/notify会收到支付结果,并且经过了支付平台签名。 {“body”:“商品A&out_trade_no=12345&seller=alice&total_fee=100&trade_status=SUCCESS&z=”, “out_trade_no”:”12345”, “seller”:“evil”, “total_fee”:“1”,“trade_status”:“SUCCESS”, “sign”:“signed by payment platform”}, 攻击者可以将其变换为 {“body”:“商品A”,“out_trade_no”:“12345”,“seller”:“alice”, “total_fee”:“100”, “trade_status”:“SUCCESS”,“z”:“&out_trade_no=12345&seller=evil&total_fee=1&trade_status=SUCCESS”, “sign”:“signed by payment platform”} 然后发送给商户Alice的URL http://seller.com/notify。这些数据具有正确的签名和期望的商家号、订单号、支付金额,将会通过alice验证,从而alice会通过攻击者的订单。 攻击者因此实现了免费(低价)购物。 3、商户验证支付结果时存在逻辑错误 1)签名验证 尽管支付平台提供了服务端SDK,商户后端在实现逻辑时可能并未使用SDK。那么,商户应正确实现签名的验证逻辑,避免相关逻辑错误,如签名不存在时通过签名验证。 2)总金额、商户号的验证 商户在收到支付结果通知,验证完签名后,还应正确处理支付结果中的相关参数。支付金额、商户号都应该被验证。 当支付金额未被验证,攻击者可以支付较低的费用实现购物。支付金额不一致可能是订单消息在签名之前金额被篡改或是攻击者伪造了订单消息(参考不对称密钥泄漏)。 若商户号未被验证,攻击者可以考虑复用另一商户的支付结果,对当前商户进行攻击。攻击发生的条件在于发给不同商户的支付结果使用了同样的私钥签名,同时攻击者注册了自己商户。攻击者生成一个订单,支付给自己的商户后,将支付结果复用。 若商户号和总金额均未被验证,攻击者还可以再次考虑复用另一商户的支付结果对当前商户进行攻击。虽然复用支付结果仍要求发给不同商户的支付结果使用了同样的私钥签名,但攻击者不再需要注册自己的商户,而是利用已泄漏的商户密钥。实现攻击时,攻击者生成一个费用较低的订单,完成支付后复用支付结果。 3)只在客户端验证 在用户完成支付后,支付平台往往既会异步通知商户服务器支付结果,又会同步通知商户客户端支付结果以向用户展示。 然而,支付结果的验证应在服务端完成。仅在客户端验证将容易受到攻击。攻击者可以直接修改客户端逻辑实现免费购物。 总结 本文总结了常见支付平台的支付过程的机制,探讨了其中存在和可能存在的问题,并通过实例展现了商户端和支付平台出现的安全问题。除了本文中探讨的问题,还有许许多多安全隐患在近年得到不断修正。总的来说现在的网上支付还是比较可靠的。在下篇中我们继续对基于MD5的消息签名机制进行讨论,发掘更多的安全问题。 小编,。 (编辑:ASP站长网) |