的OdbcCommand。使用表名进行参数化

时间:2013-01-02 15:05:30

标签: c# odbc sql-injection parameterized

我在向C#中的odbc驱动程序执行OdbcConnection的参数化sql查询时遇到问题。 列名和表名可以从web gui配置,所以我希望它免受注入

using (OdbcCommand command = connection.CreateCommand())
{
    command.CommandText = "SELECT ? FROM ?";
    command.CommandTimeout = SynchTimeout;
    command.CommandType = CommandType.Text;

    command.Parameters.Add(new OdbcParameter(string.Empty, "User"));
    command.Parameters.Add(new OdbcParameter(string.Empty, "TableName"));

    OdbcDataReader reader = command.ExecuteReader();
    while (reader.Read())
    {
      // TODO: Do something clever..
    }
}

使用odcparameters作为列名“User”似乎没问题。但是如果我将表名添加为占位符'''的参数 我收到以下错误: 错误[HY000] [Microsoft] [ODBC Excel驱动程序]参数'Pa_RaM002'指定了需要表名的位置。

如果它不能是OdbcParameter,有没有人知道如何在这种情况下传递表名安全吗?

1 个答案:

答案 0 :(得分:1)

我认为不可能在SQL中参数化表名和列名。因此,在某种程度上,您仍然会使用字符串连接来构建动态SQL语句。

虽然可以在执行语句之前进行一些检查。我看到你可以执行两种类型的检查:

<强> 1。白名单检查(更好的解决方案)

如果可能,请提供允许以这种方式使用的表和列的列表。当用户指定表和列时,请确保只允许列表中的元素。

<强> 2。动态检查(风险解决方案)

仅当事先不知道表/列的名称时才应用此方法(例如:动态创建)并且无法构建白名单。否则,请转到白名单方法。

您可以检查数据库中是否存在已配置的表和列。

例如,如果您使用的是SQL Server,则可以通过查询the Information Schema views来执行此操作,如下所示:

select top 1 COLUMN_NAME
from INFORMATION_SCHEMA.COLUMNS
where TABLE_NAME = @tableNameParameter
and COLUMN_NAME = @columnNameParameter
and <additional criteria*>

为避免经常运行检查,您可以在允许配置表名和列名的网页中执行这些检查作为验证。

* 警告:如果您只验证表和列是否存在,那么这将使用户能够发现数据库中的所有表。为避免这种情况,您可以在SQL中添加其他条件,以确保只选择要以这种方式使用的表。例如,所有动态表都可以有一个特定的前缀,因此您可以执行[...] and TABLE_NAME like 'prefix%'


无论您选择哪种解决方案,请注意从安全角度来看这是至关重要的。您应该非常小心允许系统的哪些组件编写自定义表/列值,并在每个点中应用验证。