C# 和 MySQL .NET 连接器 - 有啥方法可以防止泛型类中的 SQL 注入攻击?
Posted
技术标签:
【中文标题】C# 和 MySQL .NET 连接器 - 有啥方法可以防止泛型类中的 SQL 注入攻击?【英文标题】:C# and MySQL .NET Connector - Any way of preventing SQL Injection attacks in a generic class?C# 和 MySQL .NET 连接器 - 有什么方法可以防止泛型类中的 SQL 注入攻击? 【发布时间】:2011-02-16 01:40:37 【问题描述】:我的想法是通过 C# (3.5) Winforms 应用程序通过 mysql .NET 连接器 6.2.2 与 MySQL 数据库对话,为插入/更新/选择创建一些通用类。
例如:
public void Insert(string strSQL)
if (this.OpenConnection() == true)
MySqlCommand cmd = new MySqlCommand(strSQL, connection);
cmd.ExecuteNonQuery();
this.CloseConnection();
然后,我可以在程序中的任何位置通过传递一个 SQL 查询字符串来运行有/无用户输入的查询。
阅读 SO 开始让我知道这可能会导致 SQL 注入攻击(对于任何用户输入值)。无论如何要清理输入的 strSQL,还是我需要在每个需要执行数据库功能的方法中创建单独的参数化查询?
更新1:
我的最终解决方案如下所示:
public void Insert(string strSQL,string[,] parameterValue)
if (this.OpenConnection() == true)
MySqlCommand cmd = new MySqlCommand(strSQL, connection);
for(int i =0;i< (parameterValue.Length / 2);i++)
cmd.Parameters.AddWithValue(parameterValue[i,0],parameterValue[i,1]);
cmd.ExecuteNonQuery();
this.CloseConnection();
【问题讨论】:
这个想法太可怕了。您应该使用 ORM 或编写存储过程。 【参考方案1】:是的,您需要创建参数化查询,其他任何事情都会带来 SQL 注入的风险
【讨论】:
我不会走那么远。有一些密封的方法可以逃避用户输入。不幸的是,程序员只是人类,可能会忘记逃避某些事情...... 问题是在它与 SQL 结合之后进行处理/清理......在这一点上几乎不可能做到【参考方案2】:参数化很容易做到。比清理 SQL 查询要容易得多,而且比手动转义更不容易弄乱或出错。
从this tutorial page稍微编辑复制/粘贴,因为我觉得很懒:
// User input here
Console.WriteLine("Enter a continent e.g. 'North America', 'Europe': ");
string userInput = Console.ReadLine();
string sql = "SELECT Name, HeadOfState FROM Country WHERE Continent=@Continent";
MySqlCommand cmd = new MySqlCommand(sql, conn);
cmd.Parameters.AddWithValue("@Continent", userInput);
using (MySqlDataReader dr = cmd.ExecuteReader())
// etc.
这并不难,是吗? :)
【讨论】:
感谢@Thorarin - 我选择了@Justin Niessner 的回答,因为它具有通用性(我不想在每种方法中都使用连接/MySQL 代码),但您的回答肯定有助于语法。 @John M:当然欢迎您编写包装器方法。我的目标是展示它的裸机。【参考方案3】:您绝对应该使用参数化查询来保证自己的安全。
您不必每次都手动创建参数化查询。您可以修改您提供的通用方法以接受MySqlParameters
的集合:
public void Insert(string strSQL, List<MySqlParameter> params)
if(this.OpenConnection() == true)
MySqlCommand cmd = new MySqlCommand(strSQL, connection)
foreach(MySqlParameter param in params)
cmd.Parameters.Add(param);
cmd.ExecuteNonQuery();
this.CloseConnection();
我还应该提到,在使用完连接后,您应该非常小心地清理连接(通常在 using
块中处理,但我在您的代码示例中看不到那种详细程度) .
【讨论】:
谢谢贾斯汀 - 我开始想办法将泛型类与参数化查询混合起来,但你打败了我。你能澄清一下你所说的 using 块是什么意思吗?【参考方案4】:我建议使用 IDataParameter 对象来参数化您的查询。
【讨论】:
【参考方案5】:你不能真正做到这一点 - 你需要编写一个 SQL 解析器,至少可以说是不平凡且容易出错的。
咬紧牙关,对您的查询进行参数化。
【讨论】:
【参考方案6】:如果您使用MySqlParameter
并且不生成纯字符串查询,那么您是安全的。
【讨论】:
【参考方案7】:我希望清理将用于 SQL 的原始文本会非常困难。如果可能的话,我会尝试使用参数化操作。
如果您没有公开该函数,并且您从未传入根据原始用户输入构造的字符串,则可能是一个例外。
【讨论】:
【参考方案8】:不可能在事后检测到 SQL 注入(换句话说,一旦您构建了一个动态查询字符串,就不可能区分“真实”SQL 是什么与任何注入的 SQL)。
如果您的意图是允许用户执行任意 SQL,那么您似乎不会太担心 SQL 注入(因为这是 SQL 注入的目标)。 p>
【讨论】:
谢谢@Adam - 我没有想过那样 - 我想可能有一些在查询中使用正则表达式等的方法,但每种方法都可能存在漏洞。 @John:没有通用的方法,RegEx 与否。无论您使用什么方法,都必须知道一些关于查询/语句应该的外观,因此无法以上下文中立的方式进行。跨度>以上是关于C# 和 MySQL .NET 连接器 - 有啥方法可以防止泛型类中的 SQL 注入攻击?的主要内容,如果未能解决你的问题,请参考以下文章
在 .NET 应用程序中关闭 MySQL 连接是不是重要? (准确地说,C#)