真实SQL注入测试需覆盖GET、POST、Cookie、Header四类注入点,使用布尔/时间盲注payload替代单引号检测,结合数据库类型与上下文闭合方式精准构造,避免WAF拦截,并通过响应差异验证非预期SQL执行。

直接写能触发真实数据库报错或行为偏移的测试用例,比模拟“输入字符串含单引号”这种表面检查有效得多。
测试用例必须覆盖三类典型注入点
只测 GET 参数是远远不够的。真实系统里,注入点常藏在 POST body、Cookie、Header(比如 X-Forwarded-For)甚至 URL path 里。漏掉任意一类,测试就等于没做。
-
GET:构造?id=1' AND SLEEP(1)--,观察响应延迟是否大于 1 秒 -
POST:发送 JSON body{"search": "admin' OR '1'='1"},检查返回数据是否异常增多 -
Cookie:把恶意 payload 放进sessionid=admin'--,看是否绕过登录校验
用布尔/时间盲注 payload 替代简单单引号
现代应用基本都屏蔽了错误回显,只发一个 ' 得不到任何反馈,测试就失效。必须用能引发可观测差异的 payload。
- 布尔型:发两个请求 ——
?q=test' AND 1=1--和?q=test' AND 1=2--,对比 HTTP 状态码或响应长度变化 - 时间型:MySQL 用
SLEEP(2),PostgreSQL 用pg_sleep(2),SQL Server 用WAITFOR DELAY '0:0:2',统一检测响应耗时是否 >1.8 秒 - 别依赖
UNION SELECT:它要求列数匹配、类型兼容,失败率高;盲注更稳定、更贴近真实攻击链路
测试前必须确认数据库类型和上下文闭合方式
同一个 payload,在 MySQL 里可能触发延时,在 PostgreSQL 里直接语法报错,在 Oracle 里根本无反应。不确认目标环境,测试就是乱打枪。
- 先试探:发
?id=1 AND 1=CONVERT(int, @@version)--(SQL Server)、?id=1 AND 1=(SELECT 1 FROM pg_sleep(1))(PostgreSQL),根据响应判断类型 - 再确认闭合:数字型参数用
1 AND 1=1/1 AND 1=2;字符型参数必须带引号闭合,如' OR 1=1--;JSON 字段则要保持双引号合法,如"admin\" OR \"1\"=\"1" - 注意 WAF 干扰:如果所有 payload 都被 403 拦截,先加
--random-agent或换User-Agent头,避免测试被当成扫描器封禁
真正难的不是写出一堆 payload,而是让每个测试用例都能明确回答一个问题:“这个接口在真实攻击下会不会执行非预期 SQL?”——这意味着你得自己解析响应内容、计算耗时、比对长度,而不是只看状态码是否为 200。

















