1

作为如何在 C# 中保护用户指定的表名免受 SQL 注入的扩展,使用 MySQL,我试图弄清楚如何保护用户指定的表查询免受 SQL 注入:

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

需要明确的是:我很想使用预定义的库来参数化 input,但我找不到一个

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

在我看来,许多人声称不可能做出 100% 安全的解决方案,但这对我来说没有意义,因为诉诸参数化应该与自己完成所有工作一样“不安全” . 本质上,我只想复制MySQL 连接器会做的事情,如果它支持参数化的表名。

我对 SQL 还不是很有经验,但到目前为止,我发现我需要:

还有什么可以防止 SQL 注入?

4

2 回答 2

1

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

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

出于性能考虑,您已排除根据 dbms 中的模式检查表和列名。您可能需要重新考虑该决定:这些查询并不像您想象的那么慢。MySQL 信息模式允许您执行如下查询:

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

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

于 2012-11-22T12:40:06.790 回答
1

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

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

所以看起来你需要验证和清理表名。

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

于 2012-11-22T12:38:47.387 回答