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

Posted

技术标签:

【中文标题】如何在我的 ASP.NET 应用程序中避免 SQL 注入攻击?【英文标题】:How can I avoid SQL injection attacks in my ASP.NET application? 【发布时间】:2010-09-23 05:35:32 【问题描述】:

我需要避免在我的 ASP.NET 应用程序中受到 SQL 注入的攻击。我怎样才能做到这一点?

【问题讨论】:

【参考方案1】:

即使您的问题非常笼统,但始终适用一些规则:

使用参数化查询(SqlCommandSqlParameter)并将用户输入放入参数中。 不要根据未经检查的用户输入构建 SQL 字符串。 不要假设您可以构建一个清理例程来检查用户输入的各种格式错误。边缘情况很容易被遗忘。检查数字输入可能很简单,可以保证您的安全,但对于字符串输入,只需使用参数。 检查二级漏洞 - 如果 SQL 表值包含用户输入,则不要根据这些值构建 SQL 查询字符串。 使用存储过程封装数据库操作。

【讨论】:

除了最后一个之外,所有这些都被第一个暗示(如果您的所有输入都被正确转义,总是通过使用准备好的语句(或参数化查询)),不是吗?或者你认为有细微的差别? 没有。但是提出这类问题的人很可能对其中的含义没有明确的理解。使它们明确是支持理解。随着您的经验和抽象能力的提高,您将不再需要明确性,并且您不太可能再提出此类问题。 这是一个很好的答案,但我觉得“使用存储过程封装数据库操作”具有误导性。参数化动态 SQL 与参数化存储过程一样安全。为了清楚起见,也许您应该在答案中更加隐含。 @Daniel:如果开发人员在数据库技术方面没有太多控制或专业知识,则可以使用与SqlCommand 一起使用的参数化查询。如果您是普通的 C# 开发人员而不是 DBA,那么在数据库中创建存储过程并不简单。如果 DBA 想要为 C# 开发人员封装复杂性,则使用存储过程是一种很好的方法。 @Vinko:我同意。将答案分成 2 个部分可以更好地回答:首先第 2-4 点作为您需要考虑的问题的答案,然后第 1 点和第 5 点作为解决所指出问题的可能解决方案。【参考方案2】:

使用Prepared Statements(链接到使用“为产品添加节点”部分中的准备好的语句的 ASP.NET 教程)。这里的所有都是它的。

好吧,或者使用 ORM,例如 Linq to SQL 或 NHibernate,它们在内部使用预准备语句。

【讨论】:

【参考方案3】:

使用参数!真的就是这么简单:-)

像这样创建您的查询(对于使用 C# 的 MS Sql 服务器):

SqlCommand getPersons = new SqlCommand("SELECT * FROM Table WHERE Name = @Name", conn); 

这里@Name是你要避免sql注入的参数,conn是一个SqlConnection对象。 然后要添加参数值,请执行以下操作:

getPersons.Parameters.AddWithValue("@Name", theName);

这里 theName 是一个变量,其中包含您要搜索的名称。

现在应该不可能对该查询进行任何 sql 注入。

既然这么简单,就没有理由不使用参数。

【讨论】:

【参考方案4】:

从不信任用户输入 - 使用验证控件、正则表达式、代码等验证所有文本框条目

永远不要使用动态 SQL - 使用参数化 SQL 或存储过程

永远不要使用管理员级别的帐户连接到数据库 - 使用受限访问帐户连接到数据库

不要以纯文本形式存储机密 - 加密或散列密码和其他敏感数据;您还应该加密连接字符串

异常应该泄露最少的信息 - 不要在错误消息中透露太多信息;在发生未处理的错误时使用 customErrors 显示最少的信息;将调试设置为 false

MSDN 上的有用链接Stop SQL Injection

【讨论】:

很好的答案,但是,我不同意“从不使用动态 SQL”。动态 SQL 是一个非常通用的术语,可以非常强大,在很多情况下都应该使用它。您的观点应该只是将可变数据作为参数传递。 Aye Robin,我同意动态 SQL 可能非常有用,并且在一些很好的情况下应该使用它,根据我的观点,仅基于与外界用户的交互,停止他们注入SQL。例如,由 SQL 与用户输入的值连接构成的 SQL 语句。 嗯,我刚刚获得了 -1 票,而且我下面的一些帖子让我们都失望了? (可能都是同一个用户??)【参考方案5】:

SQL注入是因为对数据库的查询是实时构建的,例如:

SELECT * From Table1 WHERE " + UserInput

UserInput 可能是恶意的,并且包含您不希望的其他陈述。

为避免这种情况,您需要避免将查询连接在一起。

您可以通过使用参数化查询来完成此操作 - 查看 DBCommand 对象以了解您的特定数据库风格。

【讨论】:

【参考方案6】:

使用参数化查询和/或存储过程并通过 SQL 参数解析您的参数。 从不通过连接字符串生成 SQL 代码。还要阅读有关 SQL 注入和编写安全代码的知识,因为防止 SQL 注入只是安全性的一小部分。还有更多(例如 XSS - 跨站点脚本)。如果黑客想要破坏您的站点/应用程序,他会寻找更多的东西,而不仅仅是 SQL 注入。

【讨论】:

【参考方案7】:

Scott Guthrie posted a decent little article 不久前谈及此事。在其中,他提出了 5 条保护自己的建议:

    不要在不使用类型安全参数编码机制的情况下构造动态 SQL 语句。 [...]

    始终在将您的应用程序投入生产之前对其进行安全审查,并建立正式的安全流程以在您进行更新时审查所有代码。 [... ]

    切勿在数据库中以明文形式存储敏感数据。 [...]

    确保编写自动化单元测试,专门验证您的数据访问层和应用程序免受 SQL 注入攻击。 [...]

    锁定您的数据库,只授予访问它的 Web 应用程序运行所需的最小权限集。 [...]

他很好地解释了为什么这些很重要,并链接到其他几个资源......

【讨论】:

很重要,但只有第一个项目符号解决了 OP 的问题。【参考方案8】:

从不信任用户输入,始终对其进行验证,并使用 sql 参数。应该有足够的基础来防止 SQL 注入。

【讨论】:

【参考方案9】:

希望这会有所帮助:

http://www.codersbarn.com/post/2008/11/01/ASPNET-Data-Input-Validation.aspx

简短的回答是使用参数化查询。

安东尼 :-) www.codersbarn.com

【讨论】:

【参考方案10】:

始终只使用参数化查询。

【讨论】:

【参考方案11】:

正如其他人所说,不要连接用户输入来创建动态 sql 语句;使用动态 SQL 时始终使用参数化 SQL。但是我要指出,在存储过程中创建动态 sql 时,该规则也适用。这个事实是人们经常忽略的。他们认为他们是安全的,因为他们“使用存储过程”。

【讨论】:

【参考方案12】:

“构建安全的 ASP.NET 应用程序”指南这本书有一个关于这个主题的section。

【讨论】:

【参考方案13】:

使用 Microsoft.Security.Application.AntiXss.UrlEncode 使用 XSS 安全 UrlEncode 和 SQL 注入将不起作用。或者你可以使用 ASP.NET – JSON – 序列化和反序列化

还可以使用 Macfee Fre Tool 中的 SiteDigger 测试您的应用程序。

更多来自here

.NET 安全工具包 v1.0 .NETMon v1.0 Validator.NET v1.0

【讨论】:

【参考方案14】:

每个人都说“使用参数”。如果不是那么困难,我们就不得不少说。

使用QueryFirst。连接的诱惑被消除,正确的方法成为最简单的方法。您只需在 SQL 中键入 @myParam 即可创建参数,其余的由工具完成。

免责声明:我写的是 QueryFirst

【讨论】:

【参考方案15】:

了解究竟什么是 SQL 注入,然后永远不要编写任何易受其攻击的东西。

【讨论】:

【参考方案16】:

尝试使用存储过程,并验证数据的输入。不要使用任何直接的 SQL,例如 INSERT INTO ...

【讨论】:

存储过程与它无关,您可以通过不参数化调用以不安全的方式执行SP。

以上是关于如何在我的 ASP.NET 应用程序中避免 SQL 注入攻击?的主要内容,如果未能解决你的问题,请参考以下文章

使用asp.net插入数据时如何避免数据库中的不同记录?

如何在我的 ASP.NET 菜单中使用 BreadCrumb 的 Bootstrap 样式?

如何使用json从sql server ASP.net中检索数据

如何在我的 ASP.NET 应用程序中为文件定义正确的路径

如何在我的 ASP.NET MVC 应用程序中使用 ACE?

在我的 ASP.Net 项目中无法从 VS2019 连接到 SQL Server 数据库