作为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注入?
答案 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'
这将为您提供一个很好的列表,列出您指定的表。