我想使用 T-SQL 创建一个存储过程,该过程基于不易受到 SQL 注入攻击的外部数据动态创建一个表

Posted

技术标签:

【中文标题】我想使用 T-SQL 创建一个存储过程,该过程基于不易受到 SQL 注入攻击的外部数据动态创建一个表【英文标题】:I want to create a stored procedure using T-SQL that dynamically creates a table based on outside data that isn't vulnerable to SQL injection 【发布时间】:2014-10-12 18:19:45 【问题描述】:

我有一个表,其中有一列代表我们要创建的表的名称。与另一个表存在外键关系,该表有一列表示所需表的列名(所有数据类型均假定为 nvarchar)。我正在使用存储过程来创建此表。基本上我所做的是从我的表中获取所有相关数据,然后构建一个 SQL 字符串以生成表,最后使用EXEC sp_executesql @CreateTableSQL

@CreateTableSQL 是通过这样的字符串连接生成的:

SET @CreateTableSQL = 'CREATE TABLE ' + @TableName + ' (' + @ColumnString + ')';

这让我很容易受到 SQL 注入的攻击。如果有人要使用 @TableName 的值:

C (t int); DROP TABLE MyTable;--

那么这将丢弃 MyTable(不受欢迎)。

有人可以帮我构建这个 SQL 并让它不受注入攻击吗?非常感谢您的帮助。谢谢!

【问题讨论】:

编写一个函数,将@ColumnString 限制为只允许在表名中使用的字符集。 为什么需要像这样动态创建表呢?一旦你不得不求助于动态 sql 来创建表,这也意味着你必须使用动态 sql 来检索数据。这似乎是一个非常糟糕的表现的秘诀。您可以使用 QUOTENAME 来帮助表名,但您的列仍然是一个挑战。 @SeanLange 问我的 PM,哈哈。 【参考方案1】:

您可以使用QUOTENAME() 函数,它将在变量(表和列名称)周围强制使用方括号[],并且传递给这些变量的任何值都将仅被视为对象名称。

类似......

SET @CreateTableSQL = 'CREATE TABLE ' + QUOTENAME(@TableName) 
                        + ' (' + QUOTENAME(@ColumnString) + ')';

现在,即使有人将值 C (t int); DROP TABLE MyTable;-- 传递给这些变量中的任何一个,整个值 C (t int); DROP TABLE MyTable;-- 仍将被视为对象名称。

【讨论】:

以上是关于我想使用 T-SQL 创建一个存储过程,该过程基于不易受到 SQL 注入攻击的外部数据动态创建一个表的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server T—SQL 存储过程 触发器

有无参数之存储过程

T-SQL 中具有表参数的存储过程

T-SQL存储过程

在T-SQL中使用LIKE与存储过程完全匹配?

T-SQL存储过程 - 无法将输出值分配给变量