C# 防止SQL注入的好方法是什么?

C# 防止SQL注入的好方法是什么?,c#,sql,security,sql-injection,C#,Sql,Security,Sql Injection,我必须为我的OJT公司编写一个应用程序管理系统。前端将用C#完成,后端用SQL完成 现在我从来没有做过这样的项目;在学校里,我们只上了SQL的基础课。不知何故,我们的老师完全没有讨论SQL注入,这是我现在才在网上读到的 所以不管怎样,我的问题是:如何防止C#中的SQL注入?我模糊地认为,可以通过适当地屏蔽应用程序的文本字段,使其只接受指定格式的输入来实现。例如:电子邮件文本框的格式应为“example@examplecompany.tld". 这种方法是否足够?或者.NET有预定义的方法来处理这

我必须为我的OJT公司编写一个应用程序管理系统。前端将用C#完成,后端用SQL完成

现在我从来没有做过这样的项目;在学校里,我们只上了SQL的基础课。不知何故,我们的老师完全没有讨论SQL注入,这是我现在才在网上读到的


所以不管怎样,我的问题是:如何防止C#中的SQL注入?我模糊地认为,可以通过适当地屏蔽应用程序的文本字段,使其只接受指定格式的输入来实现。例如:电子邮件文本框的格式应为“example@examplecompany.tld". 这种方法是否足够?或者.NET有预定义的方法来处理这样的事情吗?我是否可以对文本框应用过滤器,使其只接受电子邮件地址格式或名称文本框,而不接受特殊字符?

我的答案很简单:

使用实体框架在C#和SQL数据库之间进行通信。这将使参数化SQL字符串不易受到SQL注入的攻击


另外,它也很容易使用。

不应该通过尝试验证输入来阻止SQL注入;相反,应该在将输入传递到数据库之前对其进行正确转义

SELECT * FROM Users WHERE Username = 'Admin' --' AND password = ''
如何转义输入完全取决于您使用什么技术与数据库接口。在大多数情况下,除非您正在编写纯SQL(您应该尽可能避免),否则框架会自动处理它,因此您可以免费获得防弹保护


在确定了接口技术之后,您应该进一步探讨这个问题。

SQL注入可能是一个棘手的问题,但有办法解决。只需使用像Linq2Entities、Linq2SQL、NHibrenate这样的ORM,您的风险就会降低。但是,即使使用SQL注入,也可能出现问题

SQL注入的主要功能是用户控制输入(XSS也是如此)。在最简单的示例中,如果您有一个使用用户名和密码的登录表单(我希望您永远不会有这样的表单)

SELECT * FROM Users WHERE Username = '" + username + "' AND password = '" + password + "'"
如果用户要为用户名Admin'输入以下内容--在对数据库执行时,SQL语句将如下所示

SELECT * FROM Users WHERE Username = 'Admin' --' AND password = ''
在这个简单的例子中,使用参数化查询(ORM就是这样做的)将消除您的风险。还有一个不太有名的SQL注入攻击向量,它是用存储过程来解决的。在这种情况下,即使使用参数化查询或ORM,仍然会有SQL注入问题。存储过程可以包含execute命令,这些命令本身可能会被SQL注入攻击所接受

CREATE PROCEDURE SP_GetLogin @username varchar(100), @password varchar(100) AS
DECLARE @sql nvarchar(4000)
SELECT @sql = ' SELECT * FROM users' +
              ' FROM Product Where username = ''' + @username + ''' AND password = '''+@password+''''

EXECUTE sp_executesql @sql
因此,即使使用参数化查询或ORM,此示例也会遇到与前一个示例相同的SQL注入问题。虽然这个例子看起来很傻,但你会惊讶地发现,像这样的东西经常被写出来

我的建议是使用ORM来立即减少出现SQL注入问题的机会,然后学习发现可能出现问题的代码和存储过程并解决它们。我不建议直接使用ADO.NET(SqlClient、SqlCommand等),除非您必须这样做,不是因为在参数中使用ADO.NET不安全,而是因为它更容易变得懒惰,只需开始使用字符串编写SQL查询,而忽略参数。ORM在强迫您使用参数方面做得很好,因为它们就是这么做的

接下来访问关于SQL注入的OWASP站点,并使用SQL注入备忘单确保您能够发现并解决代码中出现的任何问题。最后,我想说的是,在您和公司的其他开发人员之间建立一个良好的代码审查机制,您可以在其中审查彼此的代码,例如SQL注入和XSS。很多时候,程序员会错过这些东西,因为他们试图匆忙推出一些特性,而不会花太多时间来检查代码

通过使用,检查sql注入的所有痛苦都将从您身上消失,并将由这些类来处理

下面是一个例子,摘自上面的一篇文章:

private static void UpdateDemographics(Int32 customerID,
    string demoXml, string connectionString)
{
    // Update the demographics for a store, which is stored  
    // in an xml column.  
    string commandText = "UPDATE Sales.Store SET Demographics = @demographics "
        + "WHERE CustomerID = @ID;";

    using (SqlConnection connection = new SqlConnection(connectionString))
    {
        SqlCommand command = new SqlCommand(commandText, connection);
        command.Parameters.Add("@ID", SqlDbType.Int);
        command.Parameters["@ID"].Value = customerID;

        // Use AddWithValue to assign Demographics. 
        // SQL Server will implicitly convert strings into XML.
        command.Parameters.AddWithValue("@demographics", demoXml);

        try
        {
            connection.Open();
            Int32 rowsAffected = command.ExecuteNonQuery();
            Console.WriteLine("RowsAffected: {0}", rowsAffected);
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

抱歉,你说的“编写纯sql”是什么意思?@LeonidasFett:通常你通过编写像
User.Name=“Joe”这样的代码来处理数据库;User.Save()而不是像
Database.ExecuteQuery(“更新用户集名称='Joe'其中id=1”)。第二个是编写裸sql.ah ok。现在我明白了:)所以基本上我应该通过一个框架而不是sql与数据库交互?你在这里提倡的是一个类似ORM的实体框架。我自己使用它,也很喜欢它,但它确实有一些缺点——比如批量操作的速度非常慢。另一种方法是使用参数化命令—您为变量编写带有占位符的SQL,然后将变量传递给另一个方法,该方法负责将变量合并到查询中(事实上,它们分别传递给处理其余变量的Db服务器)。到目前为止,现有数据库中大约有3000条记录,但这将在今年急剧扩大。我将列出这两个选项(EF和参数化命令)及其优缺点,并让我的项目主管决定:DIm不知道EF/类似ORM在内部使用参数化查询时存在任何SQL注入风险-您能提供链接吗?感谢上面我给出的存储过程的示例,即使您使用类似ORM的实体框架来调用该过程,存储过程仍然容易受到SQL注入攻击,因为漏洞存在于该过程中。因此,我试图传达的是,你不能简单地使用ORM,并认为你已经涵盖了