sql server中可用instead of触发器在insert/update前匹配敏感词并回滚,但无法拦截sql注入;需用表驱动+大小写归一化匹配,避免like全模糊查询及绕过风险,仅作补丁而非可靠防护。

不能拦截SQL注入,但能对INSERT/UPDATE时的字段值做敏感词匹配并阻止写入——前提是字段内容已进入DML流程,且你接受误杀和绕过风险。
BEFORE触发器在SQL Server里不存在,得用INSTEAD OF
SQL Server 没有 BEFORE INSERT 触发器,只有 INSTEAD OF INSERT 和 INSTEAD OF UPDATE。这意味着:你不能“先校验再插入”,而是必须自己重写插入逻辑。一旦发现敏感词,就直接 ROLLBACK 并 RAISERROR,不执行原语句。
常见错误是误用 AFTER INSERT —— 那时候数据已经落库,再抛错也晚了,只能靠后续清理,不是“拦截”。
-
INSTEAD OF触发器里必须显式处理INSERTED表的所有列,漏掉一列就会导致该列写入NULL - 不能在触发器里再对同一张表做
INSERT或UPDATE,否则报错Cannot modify table 'X' in this context - 触发器中调用
CHARINDEX()或PATINDEX()匹配敏感词比正则更稳定(SQL Server 原生LIKE不支持多模式或大小写无关全局匹配)
敏感词匹配别硬编码,用表驱动 + 大小写归一化
把敏感词存在一张 sensitive_words 表里,而不是写死在触发器 SQL 中。每次匹配前先把 NEW.content 转成小写(LOWER(INSERTED.content)),再跟 LOWER(word) 对比——否则 'Admin' 就会绕过 'admin' 规则。
别用 SELECT ... INTO @var 去查是否存在命中,容易因无结果返回而让 @var 为 NULL,判断失效。改用:
IF EXISTS (
SELECT 1 FROM sensitive_words
WHERE LOWER(INSERTED.content) LIKE '%' + LOWER(word) + '%'
)
BEGIN
RAISERROR('内容含敏感词', 16, 1);
ROLLBACK;
RETURN;
END
- 避免用
LIKE '%xxx%'匹配长文本,性能差;如字段超 200 字符,建议只检查前 100 字 - 别对
TEXT或NTEXT类型字段用LIKE,SQL Server 2016+ 已弃用,改用NVARCHAR(MAX) - 敏感词表加索引没用——
LIKE '%...%'无法走索引,纯内存扫描
绕过太容易,别当真防护手段
触发器只拦得住直接向这张表的 INSERT 或 UPDATE。以下操作完全绕过:
- 攻击者用
INSERT INTO logs SELECT password FROM users—— 触发器在logs表上?那跟users无关 - 通过视图插入:
CREATE VIEW safe_view AS SELECT title, content FROM posts,再对视图建INSTEAD OF触发器,但业务代码若直连表就无效 - 用
BULK INSERT或bcp导入,除非显式启用触发器(WITH (FIRE_TRIGGERS)),否则默认不触发 - 高权限账号直接执行
EXEC sp_executesql N'UPDATE posts SET content = ''union select 1''';,触发器照样运行,但内容早已污染
真正要防,得在应用层统一过滤,或在网关、WAF 层做请求体扫描。触发器只是最后一道“自欺欺人”的补丁,上线前务必确认所有写入路径都经过它——这几乎不可能。
加密或脱敏?触发器里别干这事
想在触发器里调用 ENCRYPTBYKEY()?先确保密钥已打开:OPEN SYMMETRIC KEY xxx DECRYPTION BY CERTIFICATE yyy。但问题在于:触发器无法感知租户、用户身份,所有行都用同一密钥,等于裸奔。
更现实的做法是只打标:
- 加一列
is_flagged BIT DEFAULT 0,命中敏感词时设为1 - 往审计表插记录:
INSERT INTO audit_log (table_name, row_id, reason) VALUES ('posts', INSERTED.id, 'sensitive_word') - 禁止在触发器里调用
CONVERT(VARCHAR, ENCRYPTBYKEY(...))存进NVARCHAR字段——二进制被转成乱码,解密失败
字段类型必须是 VARBINARY,密钥管理必须由应用层完成。触发器连当前连接用户是谁都不知道,怎么可能安全选密钥。










