如果我在 IN 子句中使用 SQL 参数,是否可以防止 SQL 注入?

问题描述 投票:0回答:2

下面的 SQL 注入是安全的吗?用户将以逗号分隔的代码列表作为字符串传递(例如,

'1'
'1,3'
'1,2,3'
等)。我读到 SQL 参数可以防止 SQL 注入。

CREATE PROCEDURE CurrentActions   
    @StatusCodes nvarchar(100)   -- 0 = Active, 1 = Completed, 2 = On Hold
AS   
    SELECT ActionId, ActionName, ActionStatusCode, Comments  
    FROM Action
    WHERE ActionStatusCode IN (@StatusCodes)
GO

似乎有人可以将恶意代码注入

@StatusCodes
,但据我所知,情况并非如此,因为使用参数可以防止这种情况发生。使用动态 SQL 语句和不安全的串联时,参数可能会失败,但这不是这里发生的情况。

所以我的猜测是它是安全的,但是,我找不到任何特别相关的 IN 子句和插入中间的字符串参数。是的,我知道还有其他方法可以传递整数数组,但这是一种非常方便的方法。但它必须是安全的,当然,否则我不会这样做。

谢谢。

sql sql-server stored-procedures sql-injection
2个回答
0
投票

你正在寻求的意志将防止注射,但它不会不工作你想要的方式。

假设您通过

1,2,3
传递一个像
@StatusCodes
这样的值。

这将 NOT 导致您希望的

ActionStatusCode IN (1,2,3)
表达。相反,您有 一个 varchar 值,所以您最终得到的更像是
ActionStatusCode IN ('1,2,3')
。类型不匹配意味着这可能甚至不会执行,如果它确实执行它只是将
1,2,3
视为一个连续的字符串而不是三个单独的整数。


为了解决这个问题,您的选择是表值参数(我个人觉得很尴尬),使用

String_Split()
在过程中分隔值,或者一次将一个值发送到临时/会话/购物车表或类似存储,因为用户选择它们与 JOIN 一起使用。

老实说,这些选项中没有一个特别好。如果它归结为它,我可能会使用 String_Split

,尽管我很想看到 ADO.Net 中内置的东西可以更容易地通过 TVP 发送原始 
IEnumerable<T>
 而不是构建数据表。我可能应该接受它并构建我自己的辅助方法。


-1
投票
如您所描述的那样有效的是:

CREATE PROCEDURE CurrentActions @StatusCodes nvarchar(100) -- 0 = Active, 1 = Completed, 2 = On Hold AS DECLARE @sql nvarchar(max) SET @sql = 'SELECT ActionId, ActionName, ActionStatusCode, Comments FROM Action WHERE ActionStatusCode IN (' + @StatusCodes + ')' EXEC sp_executesql @sql GO
你写的程序刚结束

将 nvarchar 值 '0,1' 转换为数据时转换失败 输入 int.

http://sqlfiddle.com/#!18/f6e74/6

当然第一个命令不是推荐的解决方案,而是可能容易受到注入攻击的示例。

© www.soinside.com 2019 - 2024. All rights reserved.