我可以通过使用参数来避免所有 SQL 注入攻击吗?

Posted

技术标签:

【中文标题】我可以通过使用参数来避免所有 SQL 注入攻击吗?【英文标题】:Can I avoid all SQL-injection attacks by using parameters? 【发布时间】:2010-09-17 15:44:07 【问题描述】:

是否可以通过使用参数来避免所有 SQL 注入攻击? 并且在这种情况下不用担心 SQL 注入中的任何事情? 或者是否有一些类型的攻击需要程序员更加小心?

【问题讨论】:

【参考方案1】:

不,您无法通过使用参数来避免所有 SQL 注入攻击。动态 SQL 是真正的问题,这可能发生在存储过程以及您的应用程序代码中。

例如,这很容易受到 SQL 注入攻击:您的参数化查询将用户名传递给存储过程,并在存储过程中将参数连接到 SQL 命令然后执行。

有关多种 SQL 注入攻击的示例,请参阅此SQL Injection Cheat Sheet。您会看到,简单地转义单引号只是表面问题,还有很多方法可以解决这个问题。

【讨论】:

解决方案是永远不要使用动态 SQL。如果这是不可能的,那么您必须竭尽全力确保正确转义将连接到 SQL 语句的任何字符串,并考虑如何跨域编组字符串(例如,html --> javascript- -> URL 编码-->),因为这些转换可能会带来额外的复杂性。 @Quandary:这还不够。在某些情况下,例如当您连接一个整数时,它周围不会有任何引号。这是一个不平凡的问题,因此这就是存在参数化查询的原因。他们解决了 99% 的案件。 查看我添加到答案中的链接,该链接演示了不使用单引号的注入攻击,因此无法通过简单地替换引号来缓解。 replace(replace(replace(replace(@yourstring,'update', ''), 'delete', ''),'insert', ''),'drop',''),... 等等你能想到的每一个可能的邪恶行为。换句话说,没有真正的解决方案来保护动态 SQL。 你可以在动态 sql 中使用参数......所以它确实总是会回到使用参数。【参考方案2】:

是和不是。是的,如果您的所有 SQL 语句确实是静态的并且只使用参数,那么您将 100% 免受 SQL 注入攻击。

当参数本身用于构造动态 SQL 语句时,问题就出现了。一个示例是动态生成 SQL 语句以查询多种不同选项的存储过程,其中单个整体语句是不切实际的。虽然这个问题有更好的解决方案,但这是一个常见的解决方案。

【讨论】:

100%,也就是说,假设 MS 或 Novell 没有犯任何错误。【参考方案3】:

是的,您可以通过使用参数来避免所有 SQL 注入攻击,只要您完全在调用堆栈中一直使用参数。例如:

您的应用程序代码调用数据库中的存储过程或动态 SQL。那必须使用参数来传递所有值。 存储过程或动态 SQL 在内部构造对另一个存储过程或动态 SQL 语句的调用。那还必须使用参数来传递所有值。 无限重复直到代码用完。

如果您在 SQL Server 中编程,您可以使用sp_executesql 执行动态 SQL,它可以让您定义参数化值并将其传递给正在执行的语句。

【讨论】:

+1 我认为人们忘记了您可以在动态 SQL 中使用参数。【参考方案4】:

如果您要使用这些参数(例如,传递给存储过程)构建动态 sql 查询,那么如果不采取预防措施,就有可能发生 sql 注入。

【讨论】:

【参考方案5】:

只要您的数据库引擎支持,您始终可以通过使用准备好的语句将 SQL 注入的风险降至最低。

无论如何,prepared statements 可能是阻止 SQL 注入的最安全的方法。

【讨论】:

【参考方案6】:

问题在于动态构建 SQL 语句。

例如,您可能希望根据用户选择的列对结果进行排序。在大多数数据库中,您不能在此处使用参数(“ORDER BY ?”不起作用)。所以你必须“ORDER BY”+列。现在,如果“column”是一个字符串,那么您的 Web 应用程序的用户可以在那里注入代码(这并不容易,但可能)。

【讨论】:

以上是关于我可以通过使用参数来避免所有 SQL 注入攻击吗?的主要内容,如果未能解决你的问题,请参考以下文章

如何防止sql注入攻击?

避免mysql注入应该避免都有哪些特殊字符

如何在我的 ASP.NET 应用程序中避免 SQL 注入攻击?

参数真的足以防止 Sql 注入吗?

我可以通过在PostgreSQL函数中包装SQL来防止SQL注入攻击吗?

dljd_013_使用PreparedStatement避免SQL注入攻击