后台究竟发生了什么使SQLParameter阻止了.NET参数化查询中的SQL Inection攻击?它只是剥离任何可疑角色还是还有更多东西?
当你传递恶意输入时,有没有人检查过看看SQL Server的实际内容?
答案 0 :(得分:70)
基本上,当您使用SQLCommand
执行SQLParameters
时,参数永远不会直接插入到语句中。相反,调用名为sp_executesql
的系统存储过程并给出SQL字符串和参数数组。
当这样使用时,参数被隔离并被视为数据,而不是必须从语句中解析出来(因此可能会改变它),因此参数包含的内容永远不会被“执行”。你只会得到一个很大的错误,参数值在某种程度上是无效的。
答案 1 :(得分:41)
更容易理解,更一般的答案是这样的:
想象一下动态SQL查询:
sqlQuery='SELECT * FROM custTable WHERE User=' + Username + ' AND Pass=' + password
简单的SQL注入只是将用户名放在' OR 1=1--
这将有效地进行SQL查询:
sqlQuery='SELECT * FROM custTable WHERE User='' OR 1=1-- ' AND PASS=' + password
这表示选择其用户名为空(''
)或1=1
的所有客户,这是一个布尔值,等于true。然后,它使用--
注释掉查询的其余部分。因此,这将打印出整个客户表,或者让您随心所欲地做任何事情。
现在,参数化查询的执行方式不同,代码如下:
sqlQuery='SELECT * FROM custTable WHERE User=? AND Pass=?'
parameters.add("User", username)
parameters.add("Pass", password)
其中用户名和密码是指向关联的输入用户名和密码的变量。
现在,您可能会想,这根本不会改变任何事情。当然,您仍然可以在用户名字段中输入类似Nobody OR 1 = 1' - 有效地进行查询:
sqlQuery='SELECT * FROM custTable WHERE User=Nobody OR 1=1'-- AND Pass=?'
这似乎是一个有效的论点。但是,你错了。
参数化查询的工作方式是,SQL查询作为查询发送,数据库确切知道此查询将执行的操作,然后才会将用户名和密码仅作为值插入。这意味着它们不会影响查询,因为数据库已经知道查询将执行的操作。所以在这种情况下,它会查找Nobody OR 1=1'--
的用户名和一个空白密码,这应该是错误的。
这不是一个完整的解决方案,并且仍然需要进行输入验证,因为这不会影响其他问题,例如xss攻击,因为您仍然可以将javascript放入数据库。然后,如果这被读出到页面上,它将显示为普通的javascript,具体取决于任何输出验证。所以最好的办法仍然是使用输入验证,但使用参数化查询或存储过程来阻止任何SQL攻击。
来源:http://www.lavamunky.com/2011/11/why-parameterized-queries-stop-sql.html
答案 2 :(得分:10)
“SqlParameterCollection等参数集合提供类型检查和长度验证。如果使用参数集合,则将输入视为文字值,SQL Server不将其视为可执行代码。使用参数集合的另一个好处是你可以强制执行类型和长度检查。超出范围的值会触发异常。这是深度防御的一个很好的例子。“
答案 3 :(得分:5)
使用参数化查询时,攻击面会减少为使用参数进行修改。
请使用SqlParameters
,但不要忘记溢出,下溢和未经验证的参数。例如,如果方法是“proc buy_book (@price money
)”,则恶意攻击者会尝试欺骗应用程序在@price
设置为0.01
的情况下运行,或尝试让应用程序执行提交导致溢出的东西有趣的东西。 Sql溢出往往不是很有趣(即它们只会导致异常,你不太可能写入相邻的内存)