一个漏洞
凌晨三点,个漏洞我盯着屏幕上的个漏洞报错日志,咖啡杯沿结了一圈褐色的个漏洞渍。
那个漏洞其实很小——小到如果换成白天,个漏洞我大概会直接忽略它。个漏洞某个函数在处理用户输入时,个漏洞少了一道转义。个漏洞就少那么一个斜杠。个漏洞但偏偏这个函数是个漏洞给登录模块用的。偏偏它接收的个漏洞参数会直接拼进SQL查询里。
我试着构造了一个最简单的个漏洞payload:一个单引号,后面跟个恒真条件。个漏洞页面居然真的个漏洞把后台管理员表的前十条记录吐了出来。那一刻,个漏洞我后背发凉——不是个漏洞怕,是那种发现秘密时特有的战栗。就像小时候在邻居家墙缝里摸到一把生锈的钥匙,不知道能开哪扇门,但知道它一定开某扇门。
这个漏洞是怎么进来的?我翻了提交记录。三个月前,有个实习生为了赶进度,把原本的参数化查询改成了字符串拼接。他还在代码注释里写了句“这样写比较快”。没人review,测试环境数据量小,跑起来一切正常。就这么上线了。三个月,每天几千次登录请求,居然没人发现异常。
我试着往深处想。如果攻击者不只是SELECT,而是UNION SELECT,甚至直接DROP TABLE呢?我们的备份策略是每天凌晨两点全量备份。但恢复一个5TB的数据库需要多久?没人试过。我翻了运维手册,上面写着“预计恢复时间不超过4小时”。但写这行字的人,三个月前离职了。
更让我不舒服的是,这个漏洞的存在本身,就是整个开发流程的缩影。我们追求敏捷,两周一个迭代。代码评审形同虚设,因为“大家都忙”。安全测试外包给第三方,他们每季度来一次,跑一遍自动扫描工具,输出一份PDF报告,然后我们把它归档。没人真正读过那些报告,除了安全负责人——但他上个月刚被调去负责另一个项目。
我修好了那个漏洞。三行代码的事,参数化查询,加上输入校验。提交PR,合并,部署。整个过程不到二十分钟。但我知道,这只是个开始。代码库里肯定还有类似的洞,藏在我没注意到的角落,藏在某个赶进度的深夜,藏在某句“这样写比较快”的注释后面。
第二天早上,我把这个漏洞写成了复盘报告。邮件发出去后,产品经理回了句“收到”,测试同事回了句“辛苦”,技术总监没回。下午的站会上,没人提起这件事。就像它从未存在过。
我盯着屏幕上那个绿色的“已修复”标签,突然觉得,真正的漏洞从来不在代码里。它藏在每个“下次再说”的会议里,藏在每个“先上线再补”的承诺里,藏在每个“应该没事”的侥幸里。代码漏洞可以修,但这些洞,我不知道怎么打补丁。









