2

我在对 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 似乎没问题。但是如果我将表名添加为带有占位符的参数“?” 我收到以下错误:错误 [HY000] [Microsoft][ODBC Excel 驱动程序] 参数“Pa_RaM002”指定了需要表名的位置。

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

4

1 回答 1

1

我认为不可能在 SQL 中参数化表名和列名。因此,以某种方式,您仍然会求助于字符串连接来构建动态 SQL 语句。

不过,您可以在执行语句之前进行一些检查。我看到您可以执行两种类型的检查:

1.白名单检查(更好的解决方案)

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

2.动态检查(有风险的解决方案)

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

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

例如,如果您使用的是 SQL Server,您可以通过查询信息架构视图来执行此操作,如下所示:

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%'


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

于 2013-01-02T15:34:15.110 回答