上周帮一个学弟看代码,逻辑漏洞他写了个用户登录功能,靶场逻辑是逻辑漏洞“如果用户名存在且密码正确,就登录成功”。靶场我问他,逻辑漏洞那如果用户名不存在呢?靶场他愣了一下,说“那肯定登录失败啊”。逻辑漏洞我又问,靶场如果用户名不存在但密码字段传了个空字符串呢?逻辑漏洞他打开Postman试了试,发现接口返回了“登录成功”,靶场因为他的逻辑漏洞判断条件写成了 if (user && user.password === input.password),而 user 为 undefined 时整个表达式为假,靶场但后面还有一段“兜底逻辑”把空密码当成了合法凭证。逻辑漏洞这种坑,靶场就是逻辑漏洞逻辑漏洞靶场里最基础的“条件竞争”变种——你以为覆盖了所有分支,其实漏掉了边界情况。
逻辑漏洞跟SQL注入、XSS不一样。那些是技术层面的“脏数据”引发的,逻辑漏洞是业务流程本身写错了。靶场里经常模拟电商场景:用户下单后,系统先扣库存再扣余额。如果扣库存成功但扣余额失败,订单状态卡在“待支付”,库存却没了。攻击者可以反复提交订单,把库存耗光,或者利用退款流程把余额刷回来。我见过一个真实案例,某平台优惠券可以叠加使用,代码里只校验了“优惠券是否属于该用户”,没校验“同一订单只能用一张”。结果有人写脚本,一单用了20张满减券,0元买走一台手机。
靶场里有个经典关卡叫“越权查看订单”。你登录用户A,把请求里的 order_id 改成用户B的订单号,如果系统只判断“订单存在”而不判断“订单属于当前用户”,你就能看到别人的收货地址和手机号。更隐蔽的是“水平越权改密码”:修改密码的接口只验证了旧密码是否正确,没验证当前登录用户是不是目标用户。攻击者抓包,把 user_id 改成管理员的,再用自己的旧密码,就能把管理员密码改了。这种漏洞在靶场里通常标为“高危”,因为利用成本极低,一个Burp Suite改个参数就行。
支付逻辑是重灾区。靶场有个关卡:商品价格是前端传的。你下单时抓包,把 price=100 改成 price=0.01,服务器直接按这个价格扣款。还有“负数攻击”:买10个商品,数量改成-10,总价变成负数,平台反而给你打钱。我试过一个靶场,充值接口没校验金额正负,输入 -100,余额从50变成150。修复方法很简单——服务端重新计算价格,并且校验数量大于0。但很多开发就是懒,觉得前端校验过了就行。
验证码逻辑也容易出问题。靶场里有个“短信轰炸”关卡:发送验证码的接口没有频率限制,手机号参数也没做格式校验。你写个循环,一秒发100条,或者把手机号改成 13800138000,13900139000 这种逗号分隔的,系统一次给多个号码发。更离谱的是“验证码回显”:请求发送验证码,服务器返回的JSON里直接带了 code: "1234"。攻击者不用收短信,直接读响应就行。这种漏洞在靶场里通常放在“信息泄露”分类下,但本质还是逻辑设计缺陷。
靶场练多了会发现,逻辑漏洞的根源就两个:一是信任了不该信任的数据(前端传的价格、用户ID、角色),二是遗漏了不该遗漏的校验(并发、负数、边界值、权限归属)。修复逻辑漏洞没有万能公式,只能靠梳理业务流程,把每个环节的“前提条件”写清楚。比如“扣库存”的前提是“库存大于0”,“改密码”的前提是“当前用户是目标用户”,“用优惠券”的前提是“券未使用且属于该订单”。把这些前提写成代码里的断言,漏洞就少一大半。
我习惯在靶场里把每个关卡的通关思路记下来,不是记payload,是记“开发者当时怎么想的”。比如“越权查看订单”那关,开发者肯定觉得“订单ID是随机的,猜不到”,但攻击者不需要猜,他只要遍历自己订单ID附近的数字就行。这种思维差异,才是逻辑漏洞靶场真正要练的东西——不是找漏洞,是找开发者的思维盲区。