2023年冬天,某跨境电商平台的运维老张盯着屏幕上的订单流水,发现凌晨三点到五点之间,总有一批账号在反复提交退款申请。每笔金额不大,几十到几百块,但频率高得离谱。他第一反应是薅羊毛党,封了几个IP,结果第二天照旧。后来查日志才看明白——攻击者根本没碰支付接口,而是钻了优惠券校验的漏洞,用脚本批量注册、领券、下单、退款,一套流程跑得比真人还顺。这就是典型的业务逻辑漏洞,防火墙拦不住,WAF也看不出异常,因为每个请求单独看都“合法”。
Web攻击这件事,很多人脑子里蹦出来的还是SQL注入、XSS弹窗这些老面孔。不能说错,但它们只是冰山一角。真正麻烦的是,攻击面早就从代码层蔓延到了业务层。你写了个优惠券功能,忘了限制同一用户领取次数,这就是漏洞。你做了个密码找回,验证码是四位纯数字,攻击者写个脚本跑一万次就能撞开。这些问题的共同点是:代码本身没毛病,逻辑上出了岔子。
再说个更隐蔽的。去年有个开源CMS爆出漏洞,攻击者可以在文章评论区注入一段JavaScript,这段脚本不偷cookie,也不弹窗,而是悄悄把访问者的浏览器变成挖矿节点。你打开页面,CPU直接飙到100%,风扇呼呼转。这种攻击叫加密劫持,2018年前后特别猖獗,现在虽然少了,但换个马甲照样能玩——比如用WebAssembly跑计算任务,浏览器根本不会弹警告。
防御这事儿,得换个思路。传统做法是堆设备:防火墙、WAF、IDS,一层层往上摞。但业务逻辑漏洞怎么防?WAF看不懂你的优惠券规则。我的观察是,得把安全左移,让开发在写代码的时候就考虑异常场景。比如那个退款漏洞,如果开发当初加一行判断——“同一用户24小时内退款次数不超过3次”——攻击者就得换策略。成本高了,自然就换目标了。
还有个细节容易被忽略:日志。很多团队出了事才翻日志,结果发现只记了访问时间、IP、URL,请求体没存,cookie没存,关键参数也没存。查个屁。我见过一个团队,被薅了半个月才发现,就是因为日志里只有“POST /api/refund 200”,连用户ID都没打。后来他们改了策略,所有敏感接口的请求体和响应码全量落盘,保留30天。再出问题,十分钟定位到攻击者用的哪个账号、哪个参数、什么时间点。
最后说个反直觉的:不是所有攻击都需要防住。有些业务场景下,防的成本远高于被攻击的损失。比如一个内部测试系统,你非要上全套WAF加RASP,没必要。但对外暴露的支付接口,那就得往死里防。安全是个权衡活儿,不是堆得越多越好。老张后来把退款接口加了频率限制,又给优惠券加了设备指纹校验,攻击者试了两天,放弃了。他没买新设备,也没重构系统,就是改了几行代码。有时候,管用的方案往往最简单。