不能直接防住线上攻击,但能暴露代码中字符串拼接SQL的硬伤;覆盖' OR '1'='1等用例可在CI阶段拦截漏洞提交,需在生产一致环境下测试全链路并验证数据库是否真实执行。

单元测试里写SQL注入用例,真能防住线上攻击?
不能直接防住,但能暴露代码里「拼接SQL」的硬伤。只要测试覆盖了 ' OR '1'='1、admin' --、1; DROP TABLE users; 这类输入,就能在CI阶段卡住带漏洞的提交——比等渗透测试或线上被黑早得多。
哪些SQL场景必须测?重点看这三类代码
不是所有SQL都要测注入,但以下位置一旦出错,基本等于裸奔:
-
String query = "SELECT * FROM user WHERE name = '" + name + "'";—— 字符串拼接SQL,必测 -
executeUpdate("DELETE FROM log WHERE id IN (" + ids + ")");—— 动态IN列表,容易忽略括号闭合和类型校验 - MyBatis 的
${}语法(如ORDER BY ${sortField}),它不走预编译,参数直插,必须单独验证
测试时怎么构造有效用例?别只跑一个单引号
单测不是摆设,得让SQL执行失败或抛异常,才算真正拦截了注入。关键点:
- 用
' OR '1'='1测逻辑绕过:比如登录接口返回了非空用户,说明没拦住 - 用
admin' UNION SELECT password FROM users--测联合查询:看是否报错或返回额外字段 - 用
1'; WAITFOR DELAY '0:0:5'--(SQL Server)或1' AND SLEEP(5)--(MySQL)测时间盲注:响应延迟超阈值就告警 - 必须验证数据库层是否真的没执行——查日志或 mock
Connection,不能只看HTTP状态码
为什么很多团队写了也白写?两个典型坑
测了但没效果,往往栽在这两处:
- 测试数据用的是内存数据库(如 H2),而它默认关闭了某些错误提示,导致
UNION注入不报错,误判“安全” - 只测了 DAO 层,没测 Controller → Service → DAO 的完整链路,中间某层做了字符串替换(比如把单引号替换成两个单引号),但替换逻辑有漏洞,测试却没覆盖到边界情况
真正起作用的注入测试,得在和生产一致的驱动、方言、错误模式下运行,且覆盖从入口参数到最终SQL生成的全路径。

















