sql注入防护的核心是pr合并前强制拦截拼接sql代码。必须用ast-based静态分析(如semgrep)检测executeupdate()等执行函数与参数绑定缺失,ci拒绝未绑定参数的合并;同时自动化校验数据库账号最小权限,并禁用动态执行函数。

因为不卡在代码提交前的SQL注入静态分析,等于把漏洞当功能一起合入主干。
PR合并前必须触发SQL模式扫描
静态分析不是“跑一遍就完事”的附加动作,而是强制拦截点。只要Java文件里出现 executeUpdate()、query.execute() 或 session.createSQLQuery(),就必须检查是否调用了 setParameter() 或等价绑定方法。没绑参数?CI直接拒绝合并。
- 漏掉这个卡点,意味着拼接SQL的代码(如
"SELECT * FROM user WHERE name = '" + name + "'")会顺利进入主干,后续所有测试、部署、WAF都只是补救 - 扫描规则必须基于AST而非正则匹配——否则会误判字符串拼接、日志语句或注释里的SQL片段
- 推荐用Semgrep规则
rule: sql-string-concat,它能识别变量参与字符串拼接后传入执行函数的完整数据流
数据库账号权限校验必须作为流水线原子步骤
即使代码用了参数化查询,高权限数据库账号仍是SQL注入得手后的放大器。权限校验不能靠人工review或文档约定,必须自动化验证。
- 在CI中执行
mysql -e "SHOW GRANTS FOR 'app_user'@'%'",断言输出不含GRANT ALL PRIVILEGES或全集 CRUD 权限 - 禁止使用
sp_executesql、EXECUTE IMMEDIATE等动态执行函数——这些在静态分析中要单独标记为高危模式 - 错误信息回显(如MySQL的详细SQL错误堆栈)必须关闭,否则WAF或应用层过滤失效时,攻击者能直接反推表结构
为什么不能等到渗透测试才查SQL注入?
渗透测试发现的SQL注入,平均修复成本是开发阶段的12倍——因为要回溯上下文、协调多个服务、安排灰度发布窗口,还可能暴露线上数据。
- 静态分析能在IDE里实时标红问题,比如IntelliJ插件检测到
String sql = "SELECT * FROM t WHERE id = " + id;就立刻告警 - CI中SAST扫描耗时通常在30秒–2分钟,远低于一次端到端测试或DAST扫描;拖慢流水线的从来不是SAST,而是没做增量扫描导致全量重跑
- 真正卡住风险的不是工具本身,而是流程:没有PR门禁策略、没有权限校验失败即中断、没有将SAST报告接入Jira自动建缺陷单
最常被忽略的一点:SQL注入防护的有效性不取决于你用了多少层防御,而取决于第一道防线有没有真正生效——也就是代码进主干前,那行拼接SQL的语句是否被拦下来了。其余都是止损,不是预防。











