我在向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,有没有人知道如何在这种情况下传递表名安全吗?
答案 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%'
无论您选择哪种解决方案,请注意从安全角度来看这是至关重要的。您应该非常小心允许系统的哪些组件编写自定义表/列值,并在每个点中应用验证。