SqlDataAdapter——防止对表名进行SQL注入

本文关键字:注入 SQL SqlDataAdapter | 更新日期: 2023-09-27 18:14:36

我有以下代码:

SqlDataAdapter adapter = new SqlDataAdapter("SELECT TOP 0 * FROM [tableName]", conn);
DataTable dt = new DataTable();
adapter.FillSchema(dt, SchemaType.Mapped);

我正在使用它来构建表模式的DataTable

通常,当人们询问SQL注入时,他们谈论的是查询参数:),我的问题是关于表名:

SELECT TOP 0 * 
FROM [tableName]

[tableName]实际上是在运行时动态/确定的(这是一个框架btw)…

传递到方法的tableName是不可信的,所以我想确保没有任何有趣的业务正在进行?

我是否必须手动擦洗表名(我肯定我会错过一些东西)?还是有一个内置的方法?或者以某种方式防止对表名进行SQL注入?

SqlDataAdapter——防止对表名进行SQL注入

您可以使用有效表名的规则

128个字符-字母、数字和有限的其他特殊字符

在这些规则中,我认为你不能做注射

CreateTable参见table_name
ValidIdentifier

您可以使用以下查询来获取数据库中所有表的列表,并将其用作白列表:

SELECT TABLE_NAME FROM <DATABASE_NAME>.INFORMATION_SCHEMA.Tables 
WHERE TABLE_TYPE='BASE TABLE'
代替

<DATABASE_NAME>

与您的数据库名称。

如果有人试图输入一个不在列表中的表名,则不执行查询。

对于"多个连接字符串"的情况,您也可以使用一个简单的查询来检查当前数据库名称:

SELECT db_name()

因此,无论connection-string/db-name是否是动态的,您都应该能够轻松地编写一个方法,该方法仅从当前数据库获取有效表名列表。从全局来看,我怀疑这两个查询是否会影响应用程序的性能,正如您所说,如果有必要,您可以轻松缓存表列表。

传入方法的tableName是不可信的,所以我想做你确定没有什么奇怪的事情发生吗?

一种方法是首先执行一个参数化查询,将表名作为参数(nvarchar最大长度128)传递给QUOTENAME函数:

SELECT QUOTENAME(@TableName) AS ScrubbedTableName;
返回值可以在TableAdapter查询中使用,而不会有SQL注入的风险。但是,如果指定的表不是预期的表,则不会阻止元数据的披露。

您可以保留sqlDataAdapter并使用

Adapter.selectcommand.parameters。add(@"无所谓",值)

编辑:对不起!我错过了与表名相关的部分,这段代码不起作用。