不能。触发器在sql解析完成、权限校验通过后才执行,仅处理已解析的new值,无法拦截改变语句结构的sql注入;它不接收原始sql字符串,既易误杀正常数据(如“o’reilly”),又无法防御参数化绕过或拼接型注入,真正防护应靠应用层参数化查询与最小权限原则。

SQL触发器不能用来拦截SQL注入
直接说结论:SQL触发器(CREATE TRIGGER)无法用于实时拦截或监控SQL注入行为。触发器只在数据变更(INSERT/UPDATE/DELETE)已发生、且语句通过语法校验和权限检查之后才被激活,它对“输入是否含恶意关键字”完全无感知——攻击者在构造 SELECT 或 UNION SELECT 时,根本不会触发任何 DML 类触发器。
为什么有人误以为触发器能防注入
常见误解来源有两类:
- 把“数据库审计日志”功能错当成触发器能力:比如 MySQL 的
general_log或 SQL Server 的Extended Events可记录所有入参,但这是日志层行为,与触发器无关; - 混淆“应用层预处理”和“数据库层响应”:例如在应用中拼接了
"SELECT * FROM users WHERE name = '" + input + "'",哪怕后续在users表上建了BEFORE INSERT触发器,也拦不住前面那条SELECT已经执行完毕。
真正可行的关键字匹配拦截位置
关键字匹配这类规则型防护,只能落在请求进入数据库之前的位置,且必须覆盖所有入口点:
-
Web 应用防火墙(WAF):如阿里云 WAF、腾讯云 WAF,可配置自定义规则匹配
union select、or 1=1等模式,但要注意大小写、注释符(/**/)、URL 编码(%55NION)等绕过手法; -
应用网关 / API 网关:在 Nginx、Kong 或 Spring Cloud Gateway 中编写 Lua 或 Java Filter,对
query string和POST body做正则扫描,命中即403拒绝; - 数据库代理层:如 ProxySQL(MySQL)、pgBouncer(PostgreSQL),可在查询解析阶段做关键字过滤,但需注意性能损耗和误杀风险;
-
ORM 框架钩子:Django 的
django.db.models.signals.pre_save或 SQLAlchemy 的before_execute事件,仅适用于 ORM 生成的语句,对原生 SQL 无效。
关键字匹配本身的风险与局限
单纯依赖字符串匹配关键词是脆弱的防御策略,容易被绕过:
- 大小写混用:
SeLeCt、uNiOn不触发小写规则; - 空格替换:
SELECT/**/1、SELECT%091(Tab)、SELECT+1; - 内联注释:
/*!SELECT*/在 MySQL 中会被执行,但多数 WAF 忽略注释内容; - 编码变形:
%55NION%20SEL%45CT(URL 编码)、\u0055NION(Unicode); - 逻辑等价替换:
1=1→1 LIKE 1、id BETWEEN 1 AND 1。
这些都不是理论漏洞,而是已在真实渗透测试中反复验证过的绕过路径。真正可靠的防护永远是参数化查询 —— 它让关键字匹配从技术上变得多余。











