提问人:Abe Miessler 提问时间:2/4/2011 最后编辑:CommunityAbe Miessler 更新时间:8/22/2017 访问量:38836
SQLParameter 如何防止 SQL 注入?
How does SQLParameter prevent SQL Injection?
问:
究竟是什么原因使 SQLParameter 能够防止 .NET 参数化查询中的 SQL Inection 攻击?它只是剥离了任何可疑角色,还是还有更多的东西?
有没有人检查过,当你传递恶意输入时,什么实际上会到达SQL Server?
答:
“SqlParameterCollection 等参数集合提供类型检查和长度验证。如果使用参数集合,则将输入视为文本值,并且 SQL Server 不会将其视为可执行代码。使用参数集合的另一个好处是,可以强制执行类型和长度检查。超出范围的值会触发异常。这是纵深防御的一个很好的例子。
http://msdn.microsoft.com/en-us/library/ff648339.aspx
基本上,当您执行 using 时,参数永远不会直接插入到语句中。相反,调用调用的系统存储过程并为其提供 SQL 字符串和参数数组。SQLCommand
SQLParameters
sp_executesql
这样使用时,参数被隔离并被视为数据,而不必从语句中解析出来(因此可能会更改它),因此参数包含的内容永远不会被“执行”。你只会得到一个很大的错误,即参数值在某种程度上是无效的。
评论
FROM
IN
使用参数化查询时,攻击面将减少到使用参数。
请使用 ,但不要忘记溢出、下溢和未经验证的参数。例如,如果该方法为“proc )”,则恶意攻击者会尝试诱骗应用程序在设置为 的情况下运行,或者尝试通过提交导致溢出的内容来使应用程序执行有趣的操作。Sql 溢出往往不有趣(即它们只会导致异常,您不太可能写入相邻的内存)SqlParameters
buy_book (@price money
@price
0.01
一个更容易理解,更笼统的答案是这样的:
想象一个动态 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'--
不过,这不是一个完整的解决方案,仍然需要进行输入验证,因为这不会影响其他问题,例如 xss 攻击,因为您仍然可以将 javascript 放入数据库中。然后,如果将其读出到页面上,它将将其显示为普通的 javascript,具体取决于任何输出验证。因此,最好的办法仍然是使用输入验证,但使用参数化查询或存储过程来阻止任何 SQL 攻击。
来源:http://www.lavamunky.com/2011/11/why-parameterized-queries-stop-sql.html
评论