我们正在尝试更新我们的经典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注入保护的最佳方法是什么?
答案 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个选项。
使用function that converts lists tables并加入其中。所以你会有类似的东西。
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中编写转义字符串函数并转义关键字。
答案 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%