当前位置:首页 > 综合

循环漏洞

2019年冬天,循环漏洞我在测试一个电商订单系统时发现了一件怪事。循环漏洞用户把商品加入购物车,循环漏洞点击结算,循环漏洞页面跳转到支付网关,循环漏洞然后——什么都没有发生。循环漏洞订单状态卡在“待支付”,循环漏洞库存扣了,循环漏洞优惠券用了,循环漏洞但钱没付。循环漏洞更诡异的循环漏洞是,用户返回购物车,循环漏洞发现商品还在里面,循环漏洞好像什么都没发生过。循环漏洞

我盯着日志看了两个小时。循环漏洞支付回调接口确实收到了银行的成功通知,但系统在处理回调时抛了一个空指针异常。异常被全局捕获器吞掉了,只留下一行警告日志。订单状态更新失败,库存回滚逻辑没触发,优惠券核销记录也没写进去。整个事务只完成了一半。

这就是循环漏洞的典型样子。它不是那种让程序崩溃的致命错误,而是让系统“假装正常”的沉默故障。用户看到的是页面正常跳转,后台看到的是日志里一行不起眼的警告。没人报警,没人报错,但数据已经烂了。

循环漏洞最喜欢藏在状态机里。我见过一个工单系统,工单从“待处理”流转到“处理中”,再流转到“已完成”。但代码里有个边界条件没处理:如果工单在“处理中”状态下被管理员强制关闭,状态会直接跳到“已关闭”,跳过“已完成”。结果统计报表里,“已完成”工单数永远比实际少一截。运营团队每个月对账都对不上,查了半年没查出原因。后来一个实习生不小心把状态流转图打印出来贴在墙上,有人拿笔把每条路径画了一遍,才发现那条被跳过的边。

更隐蔽的循环漏洞出现在重试逻辑里。某支付系统设计了自动重试:如果扣款请求超时,就隔几秒重试一次,最多三次。听起来很合理。但代码里判断“超时”的条件写错了——它把“连接被拒绝”也当成了超时。于是当支付网关短暂不可用时,系统会疯狂重试,每次重试都生成一笔新订单,库存被扣了三次,用户被扣了三次钱。用户投诉到客服,客服查订单只看到一笔,因为另外两笔的订单号在重试时被覆盖了。这个漏洞跑了整整一周才被一个较真的用户发现,他翻了银行流水,发现同一时间有三笔相同金额的扣款。

循环漏洞的本质是“逻辑闭环缺失”。正常流程应该是一个完整的环:开始、执行、验证、结束、回滚。但代码里总有些路径绕过了验证,或者回滚条件写漏了。这些路径平时不显眼,因为主流程跑得通。但一旦触发边界条件——比如网络抖动、并发冲突、用户误操作——漏洞就露出来了。

我后来养成一个习惯:写任何状态变更代码时,先画一张状态流转图,把所有可能的路径都标出来,包括异常路径。然后问自己:如果这条路径走到一半失败了,系统会回到哪个状态?数据会不会不一致?有没有孤儿记录?这个习惯帮我抓到了至少五个潜在的循环漏洞。

修复循环漏洞往往不需要高深技术。大多数时候,只需要在关键节点加一个断言,或者把“吞异常”改成“记录并告警”。但难点在于发现它们。它们不报错,不崩溃,只是安静地让数据一点点腐烂。等你发现时,可能已经跑了几个月,脏数据已经渗透到报表、对账单、甚至下游系统里了。

所以下次你看到日志里那些被忽略的警告,别急着划过去。点开看看。那行警告背后,可能就藏着一个跑了很久的循环漏洞。

分享到: