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

时间:2013-01-17 10:01:55

标签: c# sql security sql-injection

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

现在我从未做过这个范围的项目;在学校我们只有关于SQL的基础课。不知怎的,我们的老师完全没有讨论SQL注入,我现在才通过在网上阅读它来接触它。

所以无论如何我的问题是:你如何阻止C#中的SQL注入?我隐约认为可以通过正确屏蔽应用程序的文本字段来完成它,以便它只接受指定格式的输入。例如:电子邮件文本框的格式应为“example@examplecompany.tld”。这种方法是否足够?或者.NET是否有预定义的方法来处理这样的东西?我可以将过滤器应用于文本框,以便它只接受电子邮件地址格式或名称文本框,因此它不接受特殊字符吗?

5 个答案:

答案 0 :(得分:44)

通过使用SqlCommand及其child collection of parameters,检查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);
        }
    }
}

答案 1 :(得分:7)

我的答案很简单:

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

作为奖励,它也很容易合作。

答案 2 :(得分:7)

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注入问题。存储过程可以包含执行命令,这些命令本身可能是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等...),除非你必须这样做,不是因为它在某种程度上不安全地使用参数,而是因为它更容易变得懒惰并且只是开始编写SQL使用字符串查询,只是忽略参数。 ORMS很好地强迫你使用参数,因为它正是他们所做的。

下一步使用SQL注入https://www.owasp.org/index.php/SQL_Injection访问OWASP站点并使用SQL注入备忘单确保您可以发现并解决代码中出现的任何问题。 https://www.owasp.org/index.php/SQL_Injection_Prevention_Cheat_Sheet最后我会说你和你公司的其他开发人员之间进行了良好的代码审查,在那里你可以查看SQL注入和XSS之类的代码。程序员很多时候都会错过这些东西,因为他们试图匆忙推出一些功能,而不是花太多时间来检查他们的代码。

答案 3 :(得分:5)

使用参数化SQL查询。

查看以下问题和答案:https://stackoverflow.com/search?tab=votes&q=sql%20injection

掌握SQL注入的概念:http://en.wikipedia.org/wiki/SQL_injection

答案 4 :(得分:4)

尝试验证输入时不应阻止SQL注入;相反,该输入应在传递到数据库之前正确转义。

如何完全转义输入取决于您使用什么技术与数据库连接。在大多数情况下,除非您正在编写裸SQL(您应该尽可能地避免使用它),否则框架将自动处理它,以便您免费获得防弹保护。

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