下面的 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 子句和插入中间的字符串参数。是的,我知道还有其他方法可以传递整数数组,但这是一种非常方便的方法。但它必须是安全的,当然,否则我不会这样做。
谢谢。
你正在寻求的意志将防止注射,但它不会不工作你想要的方式。
假设您通过
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>
而不是构建数据表。我可能应该接受它并构建我自己的辅助方法。
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
当然第一个命令不是推荐的解决方案,而是可能容易受到注入攻击的示例。