上个季度我们做了一次全站安全扫描,网站结果不太好看。高危一个基于Spring Boot的漏洞电商后台,用户登录接口能被SQL注入直接绕过验证,整改攻击者用一段构造好的报告payload就能拿到管理员权限。这不是网站理论风险,是高危真实可复现的漏洞。更麻烦的漏洞是,这个接口还在公网上暴露着,整改每天有上万次请求打进来。报告
问题出在哪儿?网站开发团队用了JPA做ORM,按理说能防住大部分注入。高危但有个查询用了原生SQL拼接,漏洞代码大概是整改这样的:String sql = "SELECT * FROM users WHERE username = '" + username + "'";。这种写法在十年前就该被淘汰了,报告可它偏偏出现在核心业务里。我翻了下提交记录,这段代码是两年前一个实习生写的,后来没人动过。
修复方案其实不复杂。把原生SQL改成参数化查询,用PreparedStatement或者JPA的@Query注解。但改完之后得验证,不能光看代码觉得没问题就完了。我们搭了个测试环境,用sqlmap跑了一遍,确认注入点确实堵住了。然后又把WAF规则更新了一下,加了针对这个接口的异常检测。三层防护,心里才踏实点。
另一个高危漏洞是文件上传。用户头像上传功能没做类型校验,直接拿MultipartFile存到磁盘上。有人传了个.jsp文件,访问之后服务器直接执行了。这个更吓人,等于把shell送到攻击者手里。修复的时候加了白名单校验,只允许jpg、png、gif,而且文件存到非Web目录,通过一个Servlet来读取。这样即使传了恶意文件,也执行不了。
还有个XSS漏洞,在商品评论里。用户输入的内容直接回显到页面上,没转义。有人留了条评论,里面夹了<script>标签,每个看评论的人都会中招。这个修复起来快,前端用textContent代替innerHTML,后端输出的时候做HTML实体编码。但得注意,富文本编辑器的场景不能一刀切,得用白名单过滤标签。我们用的是OWASP的Java HTML Sanitizer,配置起来稍微麻烦点,但比手写正则靠谱。
整改过程中有个细节值得说。扫描报告里列了二十多个漏洞,但真正高危的就这三个。有些中低危的,比如Cookie没加HttpOnly、错误页面泄露堆栈信息,顺手就改了。但没必要为了追求“零漏洞”把整个系统重构一遍。资源有限,优先解决能直接导致数据泄露或服务器沦陷的问题。
上线之前我们做了回归测试,重点测了登录、上传、评论这三个功能。又用Burp Suite跑了一遍主动扫描,确认没有新的问题引入。监控那边加了告警,一旦有异常SQL或文件上传请求,企业微信立刻收到通知。运维同事还写了个脚本,每天凌晨自动跑一次漏洞扫描,结果发到安全群里。
说点个人看法。很多团队把安全当成一次性的任务,扫完修完就完了。但漏洞是动态的,今天修好了,明天新代码可能又引入新的。我们现在的做法是,每次发版前必须过一遍SAST工具,关键接口手动测一遍。成本不高,但能挡住大部分低级问题。安全这事,靠的不是某个神器,是持续的习惯。
最后提一句,那个SQL注入的接口,修复后我盯着日志看了三天。没有异常请求了,但谁知道呢,攻击者可能只是换了个目标。保持警惕吧。