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

时间:2008-09-30 21:42:41

标签: sql sql-injection dynamic-sql

我们正在尝试更新我们的经典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注入保护的最佳方法是什么?

4 个答案:

答案 0 :(得分:3)

您可能不喜欢听到这个消息,但是在针对数据库发布之前,回过头来动态构建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会释放许多可能的输入排列。

答案 1 :(得分:1)

这里有3个选项。

  1. 使用function that converts lists tables并加入其中。所以你会有类似的东西。

    SELECT * 
    FROM calendar c
       JOIN dbo.fnListToTable(@Keywords) k 
           ON c.keyword = k.keyword  
    
  2. 拥有一组固定的参数,并且只允许搜索最多N个关键字

    CREATE PROC spTest
    @Keyword1 varchar(100),
    @Keyword2 varchar(100),
    .... 
    
  3. 在TSQL中编写转义字符串函数并转义关键字。

答案 2 :(得分:0)

  • 除非你需要它,否则你可以简单地删除任何不在[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结果来提取匹配的数据库行。

答案 3 :(得分:0)

你可以试试这个:

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