如果检查输入,是否需要参数化 SQL 搜索?

Do you need parameterized SQL searches if you check the inputs?

我正在编写一个 R Shiny/SQLite 应用程序。在应用程序中,我有一个函数 returns 我的 SQLite 数据库中 table 之一的列,该函数将 table 名称作为输入.

在将查询发送到 SQLite 之前,函数会检查 table 名称是否等于允许用户访问的 table 名称之一。但是,我没有使用参数化查询,因为我正在更改的术语不是用于比较的变量,而是要从中提取信息的 table 的名称。 (我想可能有一种方法可以通过参数化搜索来完成这项工作。)

我的问题是这对 SQL 注射是否安全?查询是否可以在从服务器到数据库的途中被更改,或者仅从 ui 输入到服务器的更改?

(请耐心等待,我是 SQLite 的新手。)

假设您的查询按如下方式连接:

tbl <- "yourTable"
sql <- paste0("select * from ", tbl, " where some_col = 1")

那么应该没有 SQL 注入的机会,假设您检查传入的 table 名称并验证它与白名单中的 table 名称匹配。请注意,此步骤对于确保事物安全至关重要。假设您没有 消除传入的table 名称。然后,考虑一下:

tbl <- "yourTable; delete from yourTable"

这将导致提交以下查询以供执行:

select * from yourTable; delete from yourTable where some_col = 1;

假设您的 SQLite 驱动程序允许执行多个 SQL 语句,上述 hack/trick 可能最终会从您的 table 中删除大部分数据s.

因此,只要您检查 table 名称,您的方法应该是安全的。请注意,严格来说 table 名称本身是 而不是 参数化查询中的参数。相反,只有查询中的文字值是参数。

SQL注入的问题只是用户输入问题。查询从服务器到数据库的过程中没有发生任何事情(理论上恶意软件可以改变它,但即使是参数化查询也无济于事)。

即,如果您创建这样的 SQL 字符串 (C#):

sql = "SELECT * FROM " + tableName;

然后用户可能会输入 tableName 喜欢

MyTable; DROP TABLE MyTable

猜猜会发生什么。

因此,如果您检查 table 名称,就安全了。

SQL 查询参数无论如何都不能代替 table 名称,因此将 table 名称与已知的授权 table 列表进行比较是您的唯一的选择。

是的,很安全。如果您控制可以插入到 SQL 查询中的值集,那么您可以防止未经授权的 SQL 注入。

请注意 SQL 查询的其他一些元素不能作为参数:

  • 任何标识符,例如table 名称、列名称或架构名称。
  • 表达式
  • IN ( ... ) 谓词中的值列表。列表中的每个值使用一个参数。
  • SQL 个关键字。

只能使用查询参数来代替单个标量值。也就是说,您可以在其中使用带引号的字符串文字、带引号的日期文字或数字文字。