怎样在SQL Server中利用触发器拦截包含敏感词的文本内容?

冬浩君_7424

冬浩君_7424

2026-10-09

737人浏览

原创

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

怎样在sql server中利用触发器拦截包含敏感词的文本内容?

不能拦截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,密钥管理必须由应用层完成。触发器连当前连接用户是谁都不知道,怎么可能安全选密钥。

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
数据分析工具有哪些
数据分析工具有哪些

数据分析工具有Excel、SQL、Python、R、Tableau、Power BI、SAS、SPSS和MATLAB等。详细介绍:1、Excel,具有强大的计算和数据处理功能;2、SQL,可以进行数据查询、过滤、排序、聚合等操作;3、Python,拥有丰富的数据分析库;4、R,拥有丰富的统计分析库和图形库;5、Tableau,提供了直观易用的用户界面等等。

2023.10.12

4103

8

SQL中distinct的用法
SQL中distinct的用法

SQL中distinct的语法是“SELECT DISTINCT column1, column2,...,FROM table_name;”。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2023.10.27

871

4

SQL中months_between使用方法
SQL中months_between使用方法

在SQL中,MONTHS_BETWEEN 是一个常见的函数,用于计算两个日期之间的月份差。想了解更多SQL的相关内容,可以阅读本专题下面的文章。

2024.02.23

1069

5

SQL出现5120错误解决方法
SQL出现5120错误解决方法

SQL Server错误5120是由于没有足够的权限来访问或操作指定的数据库或文件引起的。想了解更多sql错误的相关内容,可以阅读本专题下面的文章。

2024.03.06

5981

10

sql procedure语法错误解决方法
sql procedure语法错误解决方法

sql procedure语法错误解决办法:1、仔细检查错误消息;2、检查语法规则;3、检查括号和引号;4、检查变量和参数;5、检查关键字和函数;6、逐步调试;7、参考文档和示例。想了解更多语法错误的相关内容,可以阅读本专题下面的文章。

2024.03.06

2883

4

oracle数据库运行sql方法
oracle数据库运行sql方法

运行sql步骤包括:打开sql plus工具并连接到数据库。在提示符下输入sql语句。按enter键运行该语句。查看结果,错误消息或退出sql plus。想了解更多oracle数据库的相关内容,可以阅读本专题下面的文章。

2024.04.07

5960

11

sql中where的含义
sql中where的含义

sql中where子句用于从表中过滤数据,它基于指定条件选择特定的行。想了解更多where的相关内容,可以阅读本专题下面的文章。

2024.04.29

7961

6

sql中删除表的语句是什么
sql中删除表的语句是什么

sql中用于删除表的语句是drop table。语法为drop table table_name;该语句将永久删除指定表的表和数据。想了解更多sql的相关内容,可以阅读本专题下面的文章。

2024.04.29

1090

5

sql中删除一列的命令是什么
sql中删除一列的命令是什么

在sql中,使用alter table语句可以删除一列,语法为:alter table table_name drop column column_name。想了解更多sql的相关内容,可以阅读本专题下面的文章。

2024.04.29

952

5

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
热门推荐
/
最新课程
phpStudy极速入门视频教程
phpStudy极速入门视频教程

共6课时 | 54.6万人学习

独孤九贱(4)_PHP视频教程
独孤九贱(4)_PHP视频教程

共89课时 | 133.4万人学习