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

Posted

技术标签:

【中文标题】为啥使用参数化查询或实体框架会阻止 sql 注入?【英文标题】:Why does using parameterized queries or entity framework prevent sql injection?为什么使用参数化查询或实体框架会阻止 sql 注入? 【发布时间】:2014-06-08 23:52:08 【问题描述】:

我已经很好地掌握了 SQL 注入。当一个 SQL 查询应该类似于

SELECT FirstName, LastName 
FROM Customers 
WHERE CustomerId = @valueFromApplication

变成类似的查询

SELECT FirstName, LastName 
FROM Customers 
WHERE CustomerId = '' ; DROP DATABASE Foo --

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

我还知道一些有助于防止这种情况发生的事情是:

    使用带参数的存储过程 (SQL Server) 使用参数化 SQL 查询 使用实体框架/LINQ to Entities(C#,也许是 F#?)

这些东西实际上是如何防止 SQL 注入发生的?为什么攻击者不能将相同的恶意值传递到他或她已经使用的任何输入中并获得相同的结果。

【问题讨论】:

因为如果将某些东西作为参数发送,那么 SQL Server 会将其视为参数,并且不会尝试将其视为 SQL 代码执行。所以参数的内容不会被执行 你的第一个 SQL 语句是参数化的,不容易受到 SQL 注入的攻击。 C# 代码string sql = "SELECT FirstName, LastName FROM Customers WHERE CustomerId = " + valueFromApplication; 易受攻击。 当你传递给参数一些代码破坏语法,如'--'或';'被视为普通字符,只需将它们插入或更新到您的列字段或执行其他工作,例如 LIKE 运算符将搜索参数值“;Drop Database..”作为字符串本身而不是执行。 为了速度和安全性,将准备好的语句准确地预编译为存储过程。 另外,大多数用于执行参数化语句的 API 一次只会执行一条语句。 【参考方案1】:

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

参数化查询不会简单地被服务器替换为值(就像您可能手动将 @var 替换为 value 一样)。它们的发送和接收与您发送的完全相同。使用@valueFromApplication

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

要添加关于实体框架,它在内部使用参数化查询,因此它也是 SQL 注入安全的。

【讨论】:

【参考方案2】:

参数不是简单地内嵌到 SQL 中的 - 它们是从查询中单独发送到 SQL Server 的。

所以,SQL Server 得到类似:

Query:
   SELECT FirstName, LastName FROM Customers WHERE CustomerId = ?
Parameter 1:
   '' ; DROP DATABASE Foo --

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

【讨论】:

以上是关于为啥使用参数化查询或实体框架会阻止 sql 注入?的主要内容,如果未能解决你的问题,请参考以下文章

Knex.js 会阻止 sql 注入吗?

为啥实体框架会生成嵌套 SQL 查询?

未提供的参数化查询。实体框架

参数化sql查询语句

实体框架核心 - .Contains() - 为啥转义而不是参数化?

参数化查询防止Sql注入