如果我在一个IN子句中使用SQL参数,那是否能防止SQL注入?

huangapple go评论67阅读模式
英文:

If I use SQL parameters in an IN clause, does that protect it against SQL injection?

问题

以下是翻译好的部分:

这段代码看起来似乎可以防止SQL注入,因为它使用了参数来传递用户输入的代码列表。我了解到,使用SQL参数可以防止SQL注入攻击。参数可能在使用动态SQL语句和不安全的连接时出现问题,但在这里并非如此。

所以我猜这是安全的,然而,我没有找到与IN子句和将字符串参数插入到其中相关的具体信息。是的,我知道还有其他方法可以传递整数数组,但这是一种非常方便的方式。但当然,它必须是安全的,否则我就不会这样做。

谢谢。
英文:

Is the following safe from SQL injection? The user would pass in a comma separated list of codes as a string (Ex. '1', '1,3', '1,2,3', etc). I read that SQL parameters protect against SQL injection.

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

It seems like someone could inject malicious code into @StatusCodes, but what I've read, that's not the case, because using parameters will prevent that. Parameters can fail when using dynamic SQL statements and unsafe concatenation, but that's not what's happening here.

So my guess is that it's safe, however, I wasn't able to find anything specifically related IN clause and a string parameter inserted into the middle. Yes, I know there are other ways to pass in an array of ints, but this is a very convenient way to do it. But it has to be safe, of course, or I won't do this.

Thanks.

答案1

得分: 2

你所寻求的做法不会允许任何 SQL 注入,但也会无法按您期望的方式工作

假设您通过 @StatusCodes 传递一个值,如 1,2,3

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


要解决这个问题,您的选择包括使用表值参数(我个人认为很笨拙)、使用 String_Split() 分隔值在过程内部,或者将值一个接一个地发送到临时/会话/购物车表或类似存储中,用户在选择时使用 JOIN。

老实说,这些选项都不是特别好。如果情况迫使,我可能会使用 String_Split,尽管我需要更熟悉在 ADO.Net 中使用 TVP。

英文:

What you are seeking to do won't allow any sql injection, but it also will not work the way you want.

Say you pass a value like 1,2,3 via @StatusCodes.

This will NOT result in the ActionStatusCode IN (1,2,3) expression you're hoping for. Rather, you have one varchar value, so what you end up with is more like ActionStatusCode IN ('1,2,3'). The type mismatch means this probably won't even execute, and if it does execute it's only looking at 1,2,3 as one contiguous string instead of three separate integers.


To get around this, your options are a Table-Value Parameter (which I personally find awkward), using String_Split() to separate the values inside the procedure, or sending the values one at a time to a temp/session/shopping cart table or similar storage as the user selects them to use with a JOIN.

Honestly, none of these options are particularly great. If it came down to it, I'd probably use String_Split, though I need to get more comfortable using a TVP from ADO.Net.

huangapple
  • 本文由 发表于 2023年4月7日 02:09:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/75952514.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定