如何防止SQL注入攻击?

4

目前,我正在创建一个SQL查询,类似于以下操作:

string SQLQuery = "SELECT * FROM table WHERE ";
foreach(word in allTheseWords)
{
     SQLQuery = SQLQuery + " column1 = '" + word + "' AND";
}

我知道这可能会导致SQL注入攻击。我不知道如何将数组作为参数传递。
where report in @allTheseWords

===========

我正在使用 SQL Server 2012。


你使用哪种SQL数据库系统?例如SQL Server,Oracle等。 - Damien_The_Unbeliever
1
解决方案:使用Entity Framework。 - Federico Berasategui
5
一个好的开始是阅读关于参数化查询的内容。链接在这里:http://www.dotnetperls.com/sqlparameter - JMK
我不太确定在C#中是否是相同的方法,但这里有一个链接:http://www.youtube.com/course?list=EC5F8BFE541D972472 - Ankur Sinha
6个回答

3

很遗憾,如果不添加用户定义的表值参数类型,您无法将数组作为参数传递。绕过此限制的最简单方法是在循环中为数组的每个元素创建单独命名的参数,然后将值绑定到这些元素中的每一个:

string SQLQuery = "SELECT * FROM table WHERE column1 in (";
for(int i = 0 ; i != words.Count ; i++) {
    if (i != 0) SQLQuery += ",";
    SQLQuery += "@word"+i;
}
...
for(int i = 0 ; i != words.Count ; i++) {
    command.Parameters.Add("@word"+i, DbType.String).Value = words[i];
}

你也可以创建一个临时表,将单词逐个插入其中,然后执行一个与临时单词表内连接的查询。


2
使用ADO,您可以通过params来完成此操作。
SqlConnection Con = new SqlConnection(conString);
SqlCommand Com = new SqlCommand();
string SQLQuery = "SELECT * FROM table WHERE ";
int i=1;
foreach(word in words)
{
      Com.Parameters.Add("@word"+i.ToString(),SqlDbType.Text).Value = word;
      SQLQuery = SQLQuery + " column1 = '@word"+i.ToString()+"' AND ";
      i++;
}
Com.CommandText =SQLQuery;

2
这里是微软的建议:点击这里
  1. 使用代码分析来检测Visual Studio项目中容易受到SQL注入攻击的区域;
  2. 参考文章以降低攻击风险:

简单来说,他们提到了以下几点:

  • 使用存储过程。
  • 使用参数化的命令字符串。
  • 在构建命令字符串之前验证用户输入的类型和内容。

顺便说一下,您可以将静态分析作为构建过程的一部分启用,并配置它,使得违反安全规则时也会中断构建。这是确保团队编写安全代码的好方法!


1
对于SQL Server,您需要使用表值参数。SQL具有表示同一类型的多个项目集合的一种结构。它被称为表。它没有数组。
当然,您应该更新的查询:
where report in @allTheseWords

这个查询与您原始的查询不等价,但可能更接近意图。在使用AND构建的查询中,您正在说同一行中的同一列必须等于多个不同的单词。除非所有单词都相等,否则永远不会返回任何行。更新后的查询回答了是否有任何一个单词匹配,而不是所有的。


1

您需要使用预处理语句。处理方式是编写查询并为要使用的值放置占位符。以下是一个例子:

SELECT * FROM table WHERE column1 = @word

您需要经过准备阶段,SQL引擎知道需要将参数绑定到查询中。然后可以执行查询。SQL引擎应该知道何时以及如何解释绑定到查询中的参数。
以下是一些代码示例:
SqlCommand command = new SqlCommand(null, rConn);

// Create and prepare an SQL statement.
command.CommandText = "SELECT * FROM table WHERE column1 = @word";
command.Parameters.Add ("@word", word);
command.Prepare();
command.ExecuteNonQuery();

这个要放在我已经有的循环里面吗? - Cocoa Dev

0
I combine the use of params with HtmlEncoding(to get rid of special characters where not needed). Give that a shot.

using (SqlConnection conn = new SqlConnection(conString))
{     
    string sql = "SELECT * FROM table WHERE id = @id";
    using (SqlCommand cmd = new SqlCommand(sql, conn))
    {
        cmd.paramaters.AddWithValue("@id", System.Net.WebUtility.HtmlEncode(id));
        conn.Open();
        using (SqlDataReader rdr = cmd.ExecuteReader())
        {

        }
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接