动态SQL-搜索查询-可变数量的关键字

时间:2020-03-06 14:56:59  来源:igfitidea点击:

我们正在尝试更新我们经典的asp搜索引擎,以保护它免受SQL注入。我们具有VB 6函数,该函数通过基于各种搜索参数将查询串联在一起来动态构建查询。我们已使用除关键字之外的所有参数的动态sql将其转换为存储过程。

关键字的问题是用户提供了数量可变的单词,我们希望为每个关键字搜索几列。由于我们无法为每个关键字创建单独的参数,因此如何构建安全的查询?

例子:

@CustomerId AS INT
@Keywords AS NVARCHAR(MAX)

@sql = 'SELECT event_name FROM calendar WHERE customer_id = @CustomerId '

--(loop through each keyword passed in and concatenate)

@sql = @sql + 'AND (event_name LIKE ''%' + @Keywords + '%'' OR event_details LIKE ''%' + @Keywords + '%'')'

EXEC sp_executesql @sql N'@CustomerId INT, @CustomerId = @CustomerId

处理此问题并保持免受SQL注入的保护的最佳方法是什么?

解决方案

我们可能不希望听到此消息,但最好还是先对代码动态地构造SQL查询,然后再对数据库进行发布。如果在SQL字符串中使用参数占位符,则可以防止SQL注入攻击。

例子:

string sql  = "SELECT Name, Title FROM Staff WHERE UserName=@UserId";
using (SqlCommand cmd = new SqlCommand(sql))
{
  cmd.Parameters.Add("@UserId", SqlType.VarChar).Value = "smithj";

我们可以根据需要查询的列集来构建SQL字符串,然后在字符串完成后添加参数值。这样做有点麻烦,但是我认为这比拥有真正复杂的TSQL要容易得多,因为TSQL会挑剔可能的输入的许多可能排列。

我们在这里有3个选择。

  • 使用转换列表表并将其联接的函数。因此,我们将拥有类似的东西。
SELECT * 
FROM calendar c
   JOIN dbo.fnListToTable(@Keywords) k 
       ON c.keyword = k.keyword
  • 具有一组固定的参数,并且最多只允许搜索N个关键字
CREATE PROC spTest
@Keyword1 varchar(100),
@Keyword2 varchar(100),
....
  • 在TSQL中编写转义的字符串函数并转义关键字。

  • 除非我们需要它,否则我们可以简单地删除[a-zA-Z]中不存在的任何字符-大多数这些内容都不会出现在搜索中,并且我们不应该那样被注入,也不必担心关键字或者类似的东西。但是,如果允许使用引号,则需要格外小心。
  • 与sambo99的#1相似,我们可以将关键字插入临时表或者表变量中并联接到它(即使使用通配符)也没有注入的危险:

这并不是真正的动态:

SELECT DISTINCT event_name
FROM calendar
INNER JOIN #keywords
    ON event_name LIKE '%' + #keywords.keyword + '%'
    OR event_description LIKE '%' + #keywords.keyword + '%'
  • 实际上,我们可以生成带有大量参数的SP,而无需手动对其进行编码(根据对搜索编码的偏好,将默认值设置为''或者NULL)。如果发现需要更多参数,则增加它生成的参数数量将很简单。
  • 我们可以将搜索移至数据库外部的全文索引(如Lucene),然后使用Lucene结果提取匹配的数据库行。

我们可以尝试以下方法:

SELECT * FROM [tablename] WHERE LIKE % +keyword%