当前位置:首页 > 休闲

隐藏漏洞和明显漏洞

去年秋天,隐藏我帮一个做电商的漏洞朋友查系统日志。他的和明平台每天流水几十万,技术团队一直觉得安全做得不错——防火墙、显漏WAF、隐藏定期渗透测试,漏洞该有的和明都有。结果我在一份不起眼的显漏Nginx访问记录里发现,有个IP每隔六小时就来访问一次/api/v1/user/export,隐藏参数里带着一个已经离职三个月的漏洞员工账号ID。这个接口还在正常工作,和明权限校验也没拦住它。显漏朋友愣了半天,隐藏说这个接口半年前就该下线了,漏洞但没人记得删。和明

这就是隐藏漏洞的典型样子:它不在安全扫描器的规则库里,不在代码审计的检查清单上,甚至不在任何人的记忆里。它藏在系统演化的缝隙中——某个临时上线的功能、某次紧急修复留下的后门、某个被遗忘的测试账号。你没法用工具扫出来,因为工具只认识已知的漏洞模式。隐藏漏洞的本质是“逻辑遗忘”,不是技术缺陷。

明显漏洞就完全不同了。比如某次我见到一个后台管理页面,URL直接是/admin,登录框里输入' or 1=1 --就能进去。这种漏洞任何一本安全入门书都会讲,任何一次渗透测试都会报。它之所以还存在,通常不是因为不知道,而是因为“暂时没空改”。技术债务堆到一定程度,明显漏洞就成了房间里的大象——所有人都绕着走,假装它不存在。

这两类漏洞的修复成本差异极大。明显漏洞修起来往往很快:加个参数化查询、改个权限配置、升级一下依赖库。但隐藏漏洞的修复周期可能是它的十倍。你得先找到它,而找到它的前提是你能想到它可能存在。我见过一个团队为了排查一个隐藏漏洞,花了整整两周时间追溯过去八个月的Git提交记录和服务器变更日志。最后发现是某次线上热修复时,运维手动改了一个环境变量,把调试模式打开了,而那个环境变量在代码仓库里根本没有记录。

更麻烦的是,隐藏漏洞往往和业务逻辑纠缠在一起。比如一个优惠券系统,正常逻辑是每个用户只能领一张。但如果你在领取接口里传入一个不存在的用户ID,系统会创建一个临时用户并发放优惠券——这个行为在代码里是合理的,因为当初设计时考虑的是“游客领取”场景。后来游客功能下线了,这段逻辑却留了下来。从技术角度看,它没有SQL注入,没有XSS,权限校验也正常。但从业务角度看,它就是一个可以无限刷券的漏洞。这种漏洞扫描器永远扫不出来,因为扫描器不懂你的业务规则。

我自己的经验是,隐藏漏洞的数量和系统的“年龄”成正比,和团队的文档质量成反比。一个跑了三年以上、经历过多次人员更替、没有完整架构文档的系统,里面藏几十个隐藏漏洞是常态。而明显漏洞的数量则和团队的“忙碌程度”成正比——越忙的团队,越容易把已知问题往后推。

怎么应对?对明显漏洞,靠流程和工具就能压住:强制代码扫描、定期渗透测试、上线前安全检查。对隐藏漏洞,工具基本没用,得靠人。具体做法很土:定期让不熟悉某个模块的工程师去读那个模块的代码,专门找“这段逻辑为什么还在”的答案。或者更直接一点,每次下线一个功能,强制要求同时删除对应的接口、数据库字段和权限配置。听起来简单,但能做到的团队很少。因为删除比添加更让人焦虑——万一以后还要用呢?

那个电商朋友后来把那个导出接口关了,也删了离职员工的账号。但他告诉我,他不敢保证系统里没有第二个、第三个这样的接口。我说对,你不敢保证是正常的。隐藏漏洞的本质就是“你不知道自己不知道”。能做的只有两件事:一是承认它们存在,二是别让明显漏洞消耗掉你所有精力,以至于没空去挖那些藏起来的。

分享到: