SQL注入本质是字符串拼接失控导致语义污染。区分正常请求与恶意注入的关键在于上下文:输入字段的预期类型与实际内容是否冲突、SQL关键字出现位置是否合理、响应行为是否暴露异常执行路径,以及编码还原后的语义判断。
SQL注入检测:如何区分正常请求与恶意注入?
时间:2026-07-22
浏览:583
文章目录
SQL注入的本质,其实不是什么高深的代码执行漏洞,说穿了就是字符串拼接惹的祸——拼接失控,导致SQL的语义被污染了。攻击者通过操控输入,把原本的查询逻辑彻底带偏。举个例子,把用户名写成 ' OR '1'='1 拼到SELECT语句里,条件就恒真了,认证直接绕过。

这个问题其实没那么简单,光靠盯着单个字符或者关键词,是没法直接下定论的。比如用户昵称里写 Robert'; DROP TABLE students; --,这明显是攻击;但如果是 O'Connor,那就是一个再正常不过的英文姓名。同样,1=1 在调试参数里很常见,但要是出现在登录框里,那性质就变了。真正决定性的因素,还是上下文——也就是输入要匹配业务语义和数据类型。
输入字段的预期类型与实际内容是否冲突
数据库字段怎么定义的,前端表单逻辑怎么设计的,这些决定了“什么才算正常”。比如订单号字段声明为 INT,结果收到 1' OR '1'='1,那系统立刻就该报警。而用户名字段允许字母、数字、下划线和单引号,那么 O'Connor 就不该被拦截,它是合法的。
- 数值型参数里出现
'、;、UNION、SELECT这些,基本就可以判定为异常。 - 字符串型参数里连续出现多个SQL逻辑操作符,比如
AND 1=1 OR 2=2,而且没有任何业务意义,那必须重点检查。 - 日期字段传入
1970-01-01' AND SLEEP(5) --,类型和行为双重违规,没跑了。
SQL 关键字出现在非查询上下文中
很多检测规则一看到 SELECT 就报毒,结果误报率居高不下。真正该关注的,不是关键字本身,而是它出现的位置——是不是出现在本不该出现的地方。
GET /searchq=SELECT%20*%20FROM%20users—— 搜索词里含SELECT,这是用户行为,不是注入。POST /login username=admin' UNION SELECT password FROM users--&password=123—— 注意,UNION SELECT出现在 username 参数值里,而且是紧贴在单引号后面,这才是典型的注入特征。Cookie: sessionid=abc123; user_role=admin' AND 1=1 --—— 在 Cookie 的user_role值里拼接逻辑表达式,这完全违背了角色字段的语义。
响应行为暴露异常执行路径
有些请求本身看起来“干干净净”,但服务器怎么回应的,往往会暴露真实执行逻辑。这是绕过静态规则检测的关键突破口。
- 同一个IP对同一个接口连续发送
id=1、id=2、id=3,这是正常浏览;但如果变成id=1、id=1' and 1=1--、id=1' and 1=2--,那就是典型的探测行为。 - 页面返回时间突然暴涨,比如从80ms变成2s,而且伴随着
SLEEP()或WAITFOR这类构造,那基本就是基于时间的盲注。 - 错误信息里直接出现
Unknown column、MySQL server version、ORA-00904这些数据库原生报错,说明错误屏蔽没做好,SQL已经被执行了。
编码与混淆后的语义还原是否合理
攻击者最喜欢搞编码和混淆,URL编码、十六进制、大小写混用、内联注释,花样百出。检测规则必须做轻量级的解码和归一化,然后才能判断语义。
id=1%20UNION%20SELECT%201,2,3→ 解码后是id=1 UNION SELECT 1,2,3,语义清晰,非法。id=1/**/UNION/**/SELECT/**/password/**/FROM/**/users→ 去除注释后,还是完整的联合查询,非法。email=test%40example.com→ 解码后是test@example.com,符合邮箱格式,合法。- 注意:不要盲目全量解码。有些编码比如
%u0027(Unicode)或者'(HTML实体),需要根据上下文决定是否解析。
最后,最容易被忽略的一点是:业务逻辑一变,原本安全的输入可能瞬间变成攻击入口。比如新增一个“按SQL片段搜索”的功能,WHERE name LIKE '%${input}%' 就不再是漏洞,而是设计意图。检测规则必须和当前接口契约保持同步更新,不然要么漏报,要么把新功能当成攻击给误封了。
实用工具推荐
绿化、压缩、噪点和虚拟水印,自由调节做旧程度。
选择画质和输出格式,预览压缩前后的大小。