SQLParameter如何防止SQL注入?
到底什么是在后台,使SQLParameter可以防止在.NET参数化查询中的SQL Inection攻击? 它只是剥离任何可疑的字符或有什么更多的呢?
有没有人在那里检查,当你通过恶意input实际到达SQL Server?
相关: 你可以在SQL FROM语句中使用SQLParameter吗?
基本上,当您使用SQLCommand
执行SQLCommand
,参数不会直接插入到语句中。 而是调用名为sp_executesql
的系统存储过程,并给定SQLstring和参数数组。
当这样使用时,这些参数被隔离并作为数据处理,而不必从语句中parsing出来(因此可能改变它),所以参数包含的内容永远不会被“执行”。 你会得到一个很大的错误,参数值在某些方面是无效的。
一个更容易理解,更普遍的答案是这样的:
想象一下dynamicSQL查询:
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
这就是说select所有的用户名是空白的( ''
)或1=1
,这是一个布尔值,等于true。 然后使用--
将其余的查询注释掉。 因此,这将打印出整个客户表,或让您做任何你想做的事情。
现在参数化的查询以不同的方式执行,代码如下:
sqlQuery='SELECT * FROM custTable WHERE User=? AND Pass=?' parameters.add("User", username) parameters.add("Pass", password)
其中用户名和密码是指向相关的input用户名和密码的variables。
现在,在这一点上,你可能会认为,这根本没有任何改变。 当然,你仍然可以只是把用户名字段像没有人或1 = 1' – 有效地进行查询:
sqlQuery='SELECT * FROM custTable WHERE User=Nobody OR 1=1'-- AND Pass=?'
这似乎是一个有效的论点。 但是,你会错的。
参数化查询的工作方式是将SQL查询作为查询发送,并且数据库确切知道该查询将执行什么操作,只有这样才能将用户名和密码作为值插入。 这意味着它们不会影响查询,因为数据库已经知道查询将执行什么操作。 所以在这种情况下,它会查找一个Nobody OR 1=1'--
的用户名Nobody OR 1=1'--
以及一个空的密码,它应该是错误的。
这不是一个完整的解决scheme,inputvalidation仍然需要完成,因为这不会影响其他问题,如xss攻击,因为您仍然可以将JavaScript放入数据库。 然后,如果这是读出到一个页面上,它会显示为正常的JavaScript,取决于任何输出validation。 所以最好的做法仍然是使用inputvalidation,但使用参数化查询或存储过程来阻止任何SQL攻击。
资料来源: http : //www.lavamunky.com/2011/11/why-parameterized-queries-stop-sql.html
“像SqlParameterCollection这样的参数集合提供了types检查和长度validation,如果使用参数集合,input被视为一个字面值,而SQL Server不会将其视为可执行代码,使用参数集合的另外一个好处是你可以执行types和长度检查,范围之外的值触发exception,这是一个深度防御的好例子。
当使用参数化查询时,攻击面将被减less到使用参数。
请使用SqlParameters
,但不要忘记溢出,下溢和未经validation的参数。 例如,如果方法是“proc buy_book (@price money
)”,那么恶意攻击者就会试图欺骗应用程序运行,将@price
设置为0.01
,或者试图让应用程序执行一些有趣的事情,溢出。 Sql溢出往往不是有趣的(即他们只是引起exception,你不可能写入相邻的内存)