【发布时间】:2018-02-26 01:22:42
【问题描述】:
我 99% 的时间都在使用静态 SQL,但最近的一个场景让我编写了一个动态 SQL,我想确保在这个 SQL 发布到生产环境之前我没有遗漏任何东西。
表名是前缀、2字母变量和后缀的组合,列名是前缀+2字母变量。
首先,我检查了 @p_param 的长度为 2 个字母并且被“列入白名单”:
IF (LEN(@p_param) = 2 and (@p_param = ‘aa’ or @p_param = ‘bb’ or @p_param = ‘cc’ or @p_param = ‘dd’ or @p_param = ‘aa’)
BEGIN
set @p_table_name = 'table_' + @p_param + '_suffix';
set @sql = 'update ' + QUOTENAME(@p_table_name) + ' set column_name = 2 where id in (1,2,3,4);';
EXEC sp_executesql @sql;
--Here I’m checking the second parameter that I will create the column name with
IF (LEN(@p_column) = 2 and (@p_column = 'ce' or @p_column = 'pt')
BEGIN
Set @column_name = 'column_name_' + @p_column_param;
set @second_sql = 'update ' + QUOTENAME(@p_table_name) + ' set ' +
QUOTENAME(@column_name) + ' = 2 where id in (@p_some_param);';
EXEC sp_executesql @second_sql, N'@p_some_param NVARCHAR(200)', @p_some_param = @p_some_param;
END
END
这个用例安全吗?有什么我应该注意的陷阱吗?
【问题讨论】:
-
我认为您确信 column_name 存在于 @p_table_name 中?同样,您确信@column_name 的数据类型能够插入一个整数,并且您不需要检查它的数据类型?我还要添加一个 'else' 语句:“插入 failed_queries(table, column) 值 (@p_param, @p_column);”
-
是的,所有这些条件都应该满足,如果不满足,那么我可以假设客户发送了不应该发送的东西。
-
我认为检查长度并确保参数在白名单中是多余的,但比抱歉更安全。我认为您的问题可能与该解决方案的长期可支持性有关,而不是您的具体实施;最好(我认为)有一个表,其中 p_param 和 p_column 是字段中的值。换句话说,我认为这会奏效,但我认为应该对其进行重新设计,以便以更标准的方式完成——这应该使其性能更高,并且在一两年内让其他人更容易支持?
-
我认为您可以安全地进行 SQL 注入。但是,在其他方面使用该数据库似乎很烦人,表名和列名基本上没有意义。需要注意的是,如果
@p_some_param是一个列表,那么该查询将不会按您期望的方式工作。 -
请注意,列名和表确实有意义,为了这个问题,我已经更改了它们。我知道@p_some_param 不能按原样工作,我正在使用一个函数来处理这个问题。
标签: sql-server tsql dynamic-sql