SQLParameter 如何防止 SQL 注入?

How does SQLParameter prevent SQL Injection?

提问人:Abe Miessler 提问时间:2/4/2011 最后编辑:CommunityAbe Miessler 更新时间:8/22/2017 访问量:38836

问:

究竟是什么原因使 SQLParameter 能够防止 .NET 参数化查询中的 SQL Inection 攻击?它只是剥离了任何可疑角色,还是还有更多的东西?

有没有人检查过,当你传递恶意输入时,什么实际上会到达SQL Server?

相关新闻: 您可以在 SQL FROM 语句中使用 SQLParameter 吗?

.NET SQL-Server 安全性 XSS

评论


答:

13赞 Dave Brace 2/4/2011 #1

“SqlParameterCollection 等参数集合提供类型检查和长度验证。如果使用参数集合,则将输入视为文本值,并且 SQL Server 不会将其视为可执行代码。使用参数集合的另一个好处是,可以强制执行类型和长度检查。超出范围的值会触发异常。这是纵深防御的一个很好的例子。

http://msdn.microsoft.com/en-us/library/ff648339.aspx

88赞 KeithS 2/4/2011 #2

基本上,当您执行 using 时,参数永远不会直接插入到语句中。相反,调用调用的系统存储过程并为其提供 SQL 字符串和参数数组。SQLCommandSQLParameterssp_executesql

这样使用时,参数被隔离并被视为数据,而不必从语句中解析出来(因此可能会更改它),因此参数包含的内容永远不会被“执行”。你只会得到一个很大的错误,即参数值在某种程度上是无效的。

评论

2赞 OMG Ponies 2/4/2011
如果尝试在 SQL(在本例中为 TSQL)不支持变量的地方使用变量,您也会收到错误。IE:子句,表示子句中逗号分隔列表的单个参数,等等。FROMIN
2赞 Ian 9/6/2017
我不认为这回答了这个问题。可以使用 SQLParameter 类调用存储过程,该类将参数传递给过程,但不调用 sp_executesql。串联 sql 字符串中的参数值会发生什么情况?
6赞 MatthewMartin 2/4/2011 #3

使用参数化查询时,攻击面将减少到使用参数。

请使用 ,但不要忘记溢出、下溢和未经验证的参数。例如,如果该方法为“proc )”,则恶意攻击者会尝试诱骗应用程序在设置为 的情况下运行,或者尝试通过提交导致溢出的内容来使应用程序执行有趣的操作。Sql 溢出往往不有趣(即它们只会导致异常,您不太可能写入相邻的内存)SqlParametersbuy_book (@price money@price0.01

79赞 anaik 5/21/2015 #4

一个更容易理解,更笼统的答案是这样的:

想象一个动态 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

这表示选择用户名为空 () 或 的所有客户,这是一个布尔值,等同于 true。然后,它用于注释掉查询的其余部分。因此,这将打印出整个客户表,或者使您能够对它执行任何您想做的事情。''1=1--

现在,参数化查询以不同的方式执行此操作,其代码如下:

sqlQuery='SELECT * FROM custTable WHERE User=? AND Pass=?' parameters.add("User", username) parameters.add("Pass", password)

其中 username 和 password 是指向关联的输入用户名和密码的变量。

在这一点上,你可能会想,这根本没有改变任何事情。当然,您仍然可以在用户名字段中输入类似 Nobody OR 1=1'--, 的内容,从而有效地进行查询:

sqlQuery='SELECT * FROM custTable WHERE User=Nobody OR 1=1'-- AND Pass=?'

这似乎是一个有效的论点。但是,你错了。

参数化查询的工作方式是,SQL 查询作为查询发送,数据库确切地知道此查询将执行什么操作,只有这样,它才会仅将用户名和密码作为值插入。这意味着它们不会影响查询,因为数据库已经知道查询将执行什么操作。因此,在这种情况下,它将查找用户名和空白密码,这应该是假的。Nobody OR 1=1'--

不过,这不是一个完整的解决方案,仍然需要进行输入验证,因为这不会影响其他问题,例如 攻击,因为您仍然可以将 javascript 放入数据库中。然后,如果将其读出到页面上,它将将其显示为普通的 javascript,具体取决于任何输出验证。因此,最好的办法仍然是使用输入验证,但使用参数化查询或存储过程来阻止任何 SQL 攻击。

来源:http://www.lavamunky.com/2011/11/why-parameterized-queries-stop-sql.html