网站漏洞整改情况报告
上周三凌晨两点,网站安全监测平台突然弹出一条SQL注入告警——目标是漏洞我们刚上线三天的用户反馈接口。当时值班的整改同事以为误报,随手点了忽略。情况第二天早上八点,报告数据库里多了一张名为“backup_2024”的网站奇怪表,里面躺着三万条用户手机号和明文密码。漏洞这事才算真正炸开。整改
漏洞出在反馈接口的情况“查询历史记录”功能上。开发为了赶进度,报告直接把前端传来的网站userId拼进了SQL语句,连基本的漏洞参数化查询都没做。攻击者构造了一个1' OR '1'='1的整改payload,服务器就把整张用户表吐了出来。情况更离谱的报告是,数据库账号权限开的是db_owner——写文件、删表、甚至调用xp_cmdshell都行。这种低级错误出现在一个日活过万的产品里,说实话,我有点想骂人。
整改从发现漏洞的当天下午启动。第一步,立刻关闭反馈接口的外网访问,只允许内网调试IP连。第二步,把数据库账号从db_owner降级为db_datareader和db_datawriter,并且单独建了一个只读账号给查询服务用。第三步,重写那段SQL——全部换成参数化查询,连ORDER BY后面的排序字段都用白名单校验,绝不允许任何字符串拼接。这三步做完,花了不到四个小时。
但真正的麻烦在数据层。攻击者留下的那张backup_2024表虽然被删了,可我们不确定他有没有把数据导出到外部。安全团队做了流量回溯,发现攻击IP在凌晨两点到四点之间向境外某VPS上传了约12MB的压缩包。按每条记录200字节算,大概六万条——比我们发现的还多一倍。这意味着泄露范围可能覆盖了更早的注册用户。法务那边已经开始准备通知模板了。
代码层面的修复其实不难,难的是把类似问题扫干净。我们花了整个周末,用sqlmap和自研的静态扫描工具把全站API跑了一遍。又揪出两个隐患:一个是订单导出接口的startTime参数没做类型检查,另一个是评论区的sort参数直接传给了ORDER BY。这两个虽然没被利用,但跟之前那个漏洞是同一类毛病。统一改掉,顺便把WAF规则从“宽松”调到“严格”,拦截所有带union select和sleep(的请求。
事后复盘,问题根源不在技术,在流程。那个反馈接口上线前只做了功能测试,安全测试被跳过了。开发说“就一个查询,能有什么风险”。这话我听过太多次。现在我们的CI流水线里强制加了一步semgrep扫描,任何拼接SQL的写法直接构建失败。另外,所有数据库账号的权限申请必须走工单,DBA审批,默认只给SELECT。上周五刚拦下一个想申请DROP权限的临时脚本。
如果你也在管网站,别等告警响了才去看日志。花十分钟查一下你们的数据库账号权限,再翻翻代码里有没有f"SELECT * FROM users WHERE id = { user_id}"这种写法。有的话,今晚就改。攻击者不会等你准备好。
(责任编辑:焦点)













