zoukankan      html  css  js  c++  java
  • 支付安全的思考

    最近公司遭到黑客的两次攻击造成不小的损失,刚好没什么事就来记录分析一下怎么避免或者减小攻击造成的损失。首先来介绍下公司的业务吧,公司主要是做电话充值卡,加油卡充值等方面的业务,算是华南地区最大的充值中间商,日流水在1亿左右。

    第一次被黑可以说是技术经验不足,不够小心导致的。黑客伪造了一条支付请求,把请求中的支付的金额改成1分钱,购买的充值卡是100元的,当支付1分钱后微信后台回调我司服务器接口,程序验证的时候发现客户端请求的金额和实际支付的金额是一致的,都是1分钱,并没有验证和购买的物品的金额100元是否一致,于是认为支付成功了。这样就导致黑客可以使用1分钱购买100元的充值卡,给公司造成了6万多元的损失。这次可以说是程序开发人员不下心导致的,没有仔细校验数据,这种错误是完全可以避免的。相比上一次,第二次的攻击就高明了许多。首先是时间的选择上,攻击是在凌晨开始的,20分钟后值班的客服发现订单数据异常,报给了运维,但运维以偶尔充值异常为由就没有重视,之后报告给了商务,最后才通知的技术,技术查看数据后才发现问题并让运维关闭了该支付接口。这次使用的是溢出攻击,很难防范。假如黑客账户里有10元钱,然后他会把100元的充值卡加入购物车,然后请求购买,服务器收到请求后进行判断(10-100 <0)返回购买失败,然后再增加充值卡到购物车,购买,服务器判断(10-200 < 0),返回失败,.....,经过不停的购买,购物车里商品的金额溢出了,变成了一个负数,然后服务器在判断时拿用户的金额减去一个负数结果就大于0了,于是服务器判断此次支付成功。这样导致黑客不需要支付任何金额就可以购买100元的充值卡,在持续9个小时的攻击中给公司造成了87万余元的损失。

    经过这两次的攻击我在想一个问题,我们公司做了近10年的充值业务,从未发生过如此严重的事故,为什么一到微信支付上或者说是互联网上就出现如此重大的问题,我想主要是以下几个方面的原因:

    1.之前和银行的充值接口使用范围非常小。如果只有我们一家公司使用的话去专门来找漏洞是不划算的,不具有普遍适用性。而微信有十几亿用户,上面的商户也很多,开发出来的工具可以多次使用,更能吸引黑客的注意力;

    2.银行接口的开发文档少。除非内部的开发人员其他人很难拿到开发说明文档,而微信的文档非常齐全,只要在微信上注册一个开发者账号就可以拿到详细的接口说明;

    3.银行的接口的数据验证非常复杂。银行客户端发来的数据和回调有很复杂的验证过程,只要按照它的要求进行数据验证就可以保证不会出现欺骗的问题;

    4.麻痹心理。因为已经做了很多年的充值,很多人以为微信上的支付跟以前银行的一样,不会出现什么问题,没有重视;

    5.攻击银行的后果很严重,参考许霆案

    那么应该预防这种攻击呢?我想可以有以下几种方法:

    1.支付成功回调的数据进行详细的验证。首先当然是签名验证,保证数据不是伪造的。其次要把请求购买的数据和支付成功后回调的数据进行详细的验证。如果数据不一致,要有合理的解释。比如物品打折时就会造成购买物品的金额和支付的金额不一致,支付金额会少一些,要把支付金额和数据库里物品的金额进行对比。这样的话,第一次那种攻击就不会出现了。

    2.先扣钱再发货。这是我在做一款网游里物品购买时学到的。当时有人反馈买游戏中的某种装备可以在钱不够时买到,我们经过复查代码发现确实可能出现。因为那段程序是先检查等级之类是否符合购买条件,符合的话,就把商品给玩家,然后再去扣游戏币,这样即使游戏币扣除失败了你的商品已经发给用户了,从svn的提交记录来看这段代码已经存在一个月了。这就给我们一个启示,凡是买东西,先扣钱,再发商品。如果商品发了,钱没扣,用户是不会说话的,但如果商品没发钱扣了,用户一定会第一时间反馈问题。办法虽然龌蹉了点但绝对有效。

    3.创建限额程序。当黑客已经成功的找到了漏洞并进行盗窃时怎样来尽可能的减小损失是当务之急。在第一次攻击后我们就做了一个限制交易总量的程序(LDQ),依据是某个渠道的交易额是基本稳定在一个范围的,不会出现大幅度的变化。如果一个渠道每天的交易总量在50-100万,那么就可以配置150万作为报警点,总量达到200万时直接拒绝交易。处理的流程是当支付请求到来时,会先通过MsgSrv【一个消息的转发服务】向LDQ询问是否可以交易,如果可以继续交易,如果返回失败就取消这笔订单。当然如果确实是正常的交易额增加,可以手动解除限制或者调高限额。

    4.限制单笔交易量。对单笔的购买物品数量和交易额进行限制,这样可以避免溢出。当然程序中最好使用unsigned类型定义,如果是C/C++的话。最大限度的控制出现错误的可能。

    5.建立数据分析机制。要有一个程序,不停的扫描交易过的或者未交易的订单,发现问题及时预警。当然可以使用从数据库减轻主库的压力。

    6.建立合理的反馈机制。很多时候出现问题,技术是最后一个知道问题的。这就很奇怪,因为其他人即使知道有这件事也不知道是不是bug。比如我们这次被黑客攻击,客服发现异常的订单,反馈给运维,运维找商务,商务才找到技术,已经9个小时过去了。如果能提早把问题反映给技术是可以减少很多损失的。

    其实说了这么多最重要的还是人,只要开发人员有足够的经验并且细心,建立合适的监控是完全可以做到安全的。

  • 相关阅读:
    HTML5中input输入框的种类
    perl mojo 编码
    perl encode_utf8 decode_utf8
    perl mojo use utf8 和no utf8
    perl unload oracle gbk
    perl unload Oracle utf8 数据库
    perl socket 返回发送成功数据的长度
    perl socket 客户端发送消息
    验证码识别(Tess4J初体验)
    Uploadify 3.2 参数属性、事件、方法函数详解
  • 原文地址:https://www.cnblogs.com/benjaming/p/8432380.html
Copyright © 2011-2022 走看看