2

这个问题仅用于教育目的,因为我目前没有构建任何使用用户输入构建 SQL 查询的应用程序。

也就是说,我知道在 ADO.NET 中,您可以通过执行以下操作来防止 SQL 注入:

OleDbCommand command = new OleDbCommand("SELECT * FROM Table WHERE Account = @2", connection);
command.Parameters.AddWithValue("@2", "ABC");

但是假设你的应用程序的设计方式是用户可以实际输入表的名称,你能做到以下几点吗?(我不在乎允许用户提供表的名称是否是一个坏主意,我只想知道以下是否可能......)

OleDbCommand command = new OleDbCommand("SELECT * FROM @1 WHERE Account = @2", connection);
command.Parameters.AddWithValue("@1", "Table");
command.Parameters.AddWithValue("@2", "ABC");

当我运行第二个代码时,我不断收到异常,说 SQL 查询不完整,我想知道问题是我试图做的事情根本无法完成,或者我是否忽略了某些东西。

4

1 回答 1

4

不,查询参数可以替换 SQL 语句中的一个标量值
例如,单个字符串文字、日期文字或数字文字。

它不必在 WHERE 子句中。在 SQL 中任何可以有表达式的地方,都可以包含一个标量值,因此也可以包含一个参数。例如,在连接条件中,或在选择列表中,或在 ORDER BY 或 GROUP BY 子句中。

不能将查询参数用于:

  • 表标识符
  • 列标识符
  • SQL 关键字
  • SQL 表达式
  • 值列表(例如在 IN() 谓词中)

如果您需要使查询的任何这些部分可由用户定义,则需要通过将应用程序变量插入或连接到字符串中来构建 SQL 查询字符串。这使得防御 SQL 注入变得困难。

在这种情况下,最好的防御措施是将可以安全插入 SQL 字符串的特定值列入白名单,例如您在代码中定义的一组表名。让用户从这些预先批准的值中选择一个表,但不要在您随后执行的 SQL 代码中逐字使用他们的输入。

用户输入可以提供值,但绝不应该提供代码。

您可能会发现我的演示文稿SQL 注入神话和谬误很有帮助。我在该演示文稿中介绍了白名单(我的示例使用 PHP,但这个想法适用于任何编程语言)。

于 2012-11-03T17:52:45.493 回答