T-SQL动态枢轴查询和SQL注入保护

T-SQL Dynamic pivot query and SQL Injection protection

当 importing/parsing 平面文件和分隔数据(我们对这些使用 SqlBulkCopy)时,我们最终得到 table 和 DATA_KEY 和 DATA_VAL柱子。 [编辑] 忘了提这个 table 是 .net crl 的工作 table 仅解析各种入站数据。为了将这项工作 table 中的数据加载到生产 tables 中,我们然后使用动态查询来 PIVOT 数据,如下所示:

DECLARE @sqlCommand varchar(MAX)
DECLARE @columnList varchar(max)

SELECT 
    @columnList = STUFF((SELECT DISTINCT',MIN(CASE DATA_KEY WHEN '''+DATA_KEY+''' THEN DATA_VAL END) AS '+ QUOTENAME(DATA_KEY) 
                         FROM PARSED_DATA
                         FOR XML PATH ('')), 1, 1, '')

SET @sqlCommand = 'SELECT ROW_NUMBER() OVER(ORDER BY KEYID,PARENT_POS) AS ROWID,  ' + @columnList + ' FROM PARSED_DATA 

这工作正常,但带来了可能的 SQL 注入问题。显然这是一个连接的字符串,因此 DATA_KEY 和 DATA_VAL 可能会被注入。当我查看 DATA_KEY 字段时,似乎唯一可行的方法是如果攻击者知道这是在 CASE 语句中——也就是说,注入的代码必须正确地结束 CASE 语句或整个查询会失败。同样,如果注入没有正确结束 CASE 语句,DATA_VAL 字段将使整个查询失败。

我说得对吗?还是我错过了一些明显的东西?另外,在 DATA_KEY 用作列名的地方我们容易受到影响吗? QUOTENAME 使该值成为有效的 SQL 标识符;那里可以打针吗?

只是想确保所有基地都被覆盖;欢迎提出意见和建议!

我可以看到一些问题:

  • 您还应该在主元 CASE 表达式上使用 QUOTENAME。使用 '''' 作为第二个参数,得到 '' 作为分隔符
  • FOR XML 应该使用 .value 来转义 XML 个字符
  • STUFF的第三个参数是长度。为确保它始终正确,请使用 @separator 变量
  • 动态SQL应该在nvarchar(max)
  • DISTINCT 在计算字段上的性能可能很慢,首先在派生的 table/subquery
  • 中分组可能更明智
DECLARE @separator nvarchar(10) = ',';

DECLARE @columnList nvarchar(max) = STUFF(
    (SELECT @separator + 'MIN(CASE DATA_KEY WHEN ' + QUOTENAME(DATA_KEY, '''') + ' THEN DATA_VAL END) AS ' + QUOTENAME(DATA_KEY)
     FROM (SELECT DISTINCT DATA_KEY FROM PARSED_DATA) pd
     FOR XML PATH (''), TYPE
).value('text()[1]','nvarchar(max)'), 1, LEN(@separator), '');

你说你正在使用它来生成一个 INSERT 语句,所以你还应该根据 sys.columns

检查列名