sql注入黑名单校验基本无效,因正则匹配关键词易被大小写混写、url编码、注释干扰、空白符替换等方式绕过;应优先使用参数化查询,辅以输入白名单校验和waf纵深防御。

SQL注入黑名单校验为什么基本无效
直接说结论:用正则匹配 SELECT、UNION、-- 这类关键词做请求过滤,无法可靠防御 SQL 注入。攻击者绕过方式太多,比如大小写混写(SeLeCt)、编码变形(%20UNION%20SELECT)、注释干扰(/*abc*/UNION/*def*/SELECT)、空格替换为 Tab 或换行符,甚至用 Unicode 零宽字符插入关键词中间。
常见正则黑名单写法及典型绕过示例
很多人写的正则类似:/union\s+select/i 或 /(select|insert|drop|exec|xp_)/i,看似覆盖全,实则漏洞百出:
-
SEL/**/ECT 1 FROM users—— 注释打断关键词,/union\s+select/i匹配失败 -
%u0055%u004e%u0049%u004f%u004e%u0020%u0053%u0045%u004c%u0045%u0043%u0054(Unicode 编码)—— 正则默认不处理 URL 解码,直接漏过 -
id=1;WAITFOR DELAY '0:0:5'--—— 黑名单若没包含WAITFOR或DELAY,就放行 - 用反引号、方括号包裹标识符:
SELECT * FROM `users`—— 大部分简单正则不处理语法结构,只盯“裸词”
真正该做的三件事(比写正则有用得多)
防御 SQL 注入不是靠拦住坏词,而是切断恶意语义的执行路径:
- 所有数据库操作必须使用参数化查询(
PreparedStatement在 Java,pg.query带参数数组在 Node.js,cursor.execute(sql, params)在 Python psycopg2) - 对用户输入做最小权限约束:比如 ID 字段只允许纯数字,就用
/^\d+$/强制校验,而不是模糊匹配“非危险词” - Web 层开启 WAF(如 ModSecurity)并启用 OWASP CRS 规则集 —— 它基于多阶段解析+上下文感知,比单条正则鲁棒得多;但注意:WAF 是纵深防御补充,不能替代参数化
如果非要加正则校验(比如遗留系统临时加固)
至少做到这几点降低误放率:
- 在校验前统一做 URL 解码和空白符归一(把 \t\r\n\u00a0 替换为普通空格)
- 用
/\b(SELECT|UNION|INSERT|UPDATE|DELETE|DROP|EXEC|DECLARE|CAST|CONVERT)\b/i,加上单词边界\b防止匹配到SELECTED这类子串 - 禁用所有注释符号:
/--.*$|/\*[\s\S]*?\*/|#[^\r\n]*/gm,但注意:有些合法 SQL(如存储过程内联注释)也会被误杀 - 永远不单独依赖它 —— 日志中记录所有触发正则的请求,持续观察是否真有攻击,还是只是业务误报
最麻烦的地方往往不在正则怎么写,而在于你不知道输入在进数据库前被中间件、ORM、日志模块、CDN 做过多少次转义或拼接。别迷信字符串扫描,盯住执行点才管用。











