在C#中保护用户指定的表名不受SQL注入

时间:2012-11-22 12:24:32

标签: c# mysql escaping sql-injection mysql-connector

作为How to protect user specified table name from SQL Injection in C#, using MySQL的扩展,我试图弄清楚如何保护用户指定的表查询免受SQL注入:

string createEventSQL = "INSERT INTO " + TableNameFromUser +
        " (" + TableColumnNames + ") " +
        "VALUES(" + ParametrizedTableColumnParams + ")";

要明确:我喜欢使用预定义的库来参数化输入,但我找不到

我不希望其他查询(例如SHOW TABLES LIKE @TableNameFromUser;)来确保这一点,因为性能是一个问题。

在我看来,许多人声称它isn't possible to to make a 100% secure solution,但这对我来说没有意义,因为诉诸参数化应该像自己做所有工作一样“不安全”。从本质上讲,我只想复制MySQL Connector所做的事情,如果它支持参数化表名。

我对SQL不是很熟悉,但到目前为止我发现我需要:

还可以采取哪些措施来防止SQL注入?

2 个答案:

答案 0 :(得分:1)

MySQL Ado连接器支持MySqlCommand - here上的参数。 正如您所确定的那样,通常,您应该始终传递参数而不是修改ad hoc SQL。

不幸的是,这不会参数化表名,因为这个SO帖子:MySqlParameter as TableName

因此看起来您需要验证并清理表名。

您可以将表名与白名单进行比较吗?或者可能在数据库中的其他地方保留一个有效的表名列表?

答案 1 :(得分:1)

您可以并且应该参数化您的数据值。你知道的。

您无法使用SQL的预准备语句功能参数化表名和列名。但是,您应该对用户提供的表和列名称中的内容建立并强制实施约束。例如,您可以坚持表和列名都以字母开头,并且由字母,数字和下划线组成,包含3到15个字符。您可以轻松编写一个检查器函数,该函数将为违反约束的用户提供的名称抛出异常,并在编写查询时始终使用该函数检查名称。

为了提高性能,您已经排除了根据dbms中的模式检查表名和列名。您可能想重新考虑这个决定:这些查询并不像您认为的那么慢。 MySQL信息架构允许您执行以下查询:

SELECT COLUMN_NAME
  FROM information_schema.COLUMNS
 WHERE TABLE_SCHEMA = 'zip'
   AND TABLE_NAME= 'zip'

这将为您提供一个很好的列表,列出您指定的表。