如何防止动态SQL存储过程发生注入攻击?

星明大大_4485

星明大大_4485

2026-08-20

970人浏览

原创

sp_executesql仅防值注入,动态对象名须用quotename()安全包装并配合白名单校验;排序方向等非值参数必须严格枚举控制;执行上下文需最小权限,禁用元数据动态拼接与无效过滤。

如何防止动态sql存储过程发生注入攻击?

sp_executesql 不能防止动态列名、表名或排序方向的注入——它只保护值参数。真正安全的动态 SQL 存储过程,必须把「语法结构」和「数据值」彻底分开处理。

用 QUOTENAME() 处理对象名(表名、列名、schema)

表名、列名、排序字段这些属于 T-SQL 语法的一部分,无法用参数占位符替代,硬拼接就等于开门揖盗。QUOTENAME() 是唯一被 SQL Server 官方认可的安全包装函数,它会自动转义并加双方括号,比如 QUOTENAME('user; drop table x --') 返回 [user; drop table x --],让非法字符失去语法意义。

常见错误是只对输入做简单替换(如把单引号替换成两个单引号),这在 unicode 同形字、嵌套注释等绕过手法面前完全失效。

  • 只允许传入纯标识符字符串,不带任何空格、点号、括号;否则 QUOTENAME() 仍可能被滥用
  • 如果列名来自用户选择下拉框,建议用白名单映射(如 @sortcol = 'name' → 实际用 CASE @sortcol WHEN 'name' THEN 'FirstName' END)
  • QUOTENAME(@schemaname) + QUOTENAME(@tablename) 必须成对出现,缺一不可

排序方向(ASC/DESC)必须白名单校验

直接拼接 @direction 到 ORDER BY ... ' + @direction 是高危操作。SQL Server 不允许参数化排序方向,但也不意味着只能放任拼接。

正确做法是用 CASE 表达式控制输出,把用户输入限制为严格枚举值:

DECLARE @sortdir NVARCHAR(4) = UPPER(@sortdir_input);
IF @sortdir NOT IN ('ASC', 'DESC') SET @sortdir = 'ASC';
-- 然后在动态 SQL 中:
... ORDER BY ' + @sortcol + ' ' + @sortdir

注意:@sortdir 本身不能进 sp_executesql 参数列表,但必须在拼接前完成校验,且不允许空格、制表符、unicode 全角字符混入。

Aha
Aha

一款面向网红营销的AI智能体平台,可辅助品牌进行达人发现、营销策划和社交媒体内容相关工作。

下载

避免执行计划污染和权限越权

每次拼接不同字符串,都会生成新执行计划,不仅浪费 CPU,还会掩盖真实注入行为——因为慢查询日志里全是“唯一语句”,看不出攻击模式。

更危险的是权限模型错位:即使调用者只有 SELECT 权限,只要存储过程用 EXECUTE AS OWNER 或以 db_owner 身份运行,注入语句就能以高权限执行。

  • 存储过程应使用最小权限上下文,例如 EXECUTE AS 'app_reader',且该用户仅拥有目标表的 SELECT
  • 禁用 CREATE TABLE、DROP、EXEC 等 DDL/DCL 权限,哪怕只是临时表
  • 避免用 sys.tables 或 sys.columns 动态查元数据后再拼接——这等于把数据库结构暴露给攻击面

别信“过滤单引号”或“替换分号”这类土办法

正则替换 ' → ''、删掉 ;、过滤 UNION 关键字……这些在真实攻击中基本无效。攻击者早就不靠明文分号了,改用 WAITFOR DELAY '0:0:5' 盲注,或用 /*/**/UNION SELECT 绕过关键字检测。

真正能落地的防线只有两条:QUOTENAME() 包裹所有对象名 + 白名单约束所有非值类动态片段(排序方向、join 类型、聚合函数名等)。其他都是幻觉。

最常被忽略的一点:前端传来的 @tablename 可能是 users] ; DROP TABLE logs --,而 QUOTENAME() 对这种已闭合方括号的字符串无能为力——所以必须先做长度截断(如 SUBSTRING(@input, 1, 128))再 QUOTENAME()。

相关文章

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

4423

8

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

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

2023.10.27

931

4

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

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

2024.02.23

1169

5

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

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

2024.03.06

6361

10

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

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

2024.03.06

3163

4

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

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

2024.04.07

6320

11

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

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

2024.04.29

8621

6

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

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

2024.04.29

1170

5

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

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

2024.04.29

1032

5

热门下载

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

精品课程

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

共6课时 | 54.7万人学习

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

共89课时 | 133.9万人学习