为什么使用参数化查询或实体框架会阻止sql注入?

Jos*_*h R 5 c# sql entity-framework sql-injection sql-parametrized-query

我已经很好地掌握了SQL注入.这是一个SQL查询应该是什么样的

SELECT FirstName, LastName 
FROM Customers 
WHERE CustomerId = @valueFromApplication
Run Code Online (Sandbox Code Playgroud)

变成了像这样的查询

SELECT FirstName, LastName 
FROM Customers 
WHERE CustomerId = '' ; DROP DATABASE Foo --
Run Code Online (Sandbox Code Playgroud)

当用户将恶意值插入您的应用程序,网站,客户端等等时......我也知道,攻击者可以尝试发现表的名称并从中获取信息,而不仅仅是删除数据库.

我也知道一些有助于防止这种情况的事情:

  1. 使用带参数的存储过程(SQL Server)
  2. 使用参数化SQL查询
  3. 使用Entity Framework/LINQ to Entities(C#,也许是F#?)

这些事情实际上如何防止SQL注入发生?为什么攻击者不能将相同的恶意值传递给他或她已经使用的任何输入并且具有相同的结果.

Sim*_*ead 9

您的第一个示例是参数化的,不易受SQL注入的影响.

参数化查询不能简单地由服务器替换值(如你可能会做手工更换@varvalue).它们的发送和接收完全按照您发送的方式发送@valueFromApplication.

服务器将解析查询..当它到达变量时,它将查找提供的值.如果该值为'' ; DROP DATABASE Foo --..那么它将成为它使用的.它不会解析它...它只是将它用作文本/数字/它是什么类型.

要添加有关Entity Framework的内容,它在内部使用Parameterised查询,因此它也是SQL注入安全的.


Blo*_*ard 8

参数不是简单地在线替换到SQL中 - 它们是从查询单独发送到SQL Server的.

所以,SQL Server得到类似的东西:

Query:
   SELECT FirstName, LastName FROM Customers WHERE CustomerId = ?
Parameter 1:
   '' ; DROP DATABASE Foo --
Run Code Online (Sandbox Code Playgroud)

因此,它编译一个查询,检查CustomerId实际上等于的客户'' ; DROP DATABASE Foo --.参数值永远不会作为SQL执行.