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

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

提问人:Hattie35 提问时间:7/30/2020 更新时间:8/4/2020 访问量:147

问:

我正在编写一个 R Shiny/SQLite 应用程序。在应用程序中,我有一个函数,它从我的 SQLite 数据库中的一个表中返回一列,该函数将表名作为输入。

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

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

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

r sqlite 闪亮的 sql 注入 参数化查询

评论

0赞 Your Common Sense 8/4/2020
问题是,你为什么要讨价还价?准备好的陈述有那么可怕吗?你为什么要避免标准的做法?

答:

2赞 Tim Biegeleisen 7/30/2020 #1

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

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

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

tbl <- "yourTable; delete from yourTable"

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

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

假设您的 SQLite 驱动程序允许执行多个 SQL 语句,上述技巧/技巧最终可能会从其中一个表的大部分中删除数据。

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

1赞 Olivier Jacot-Descombes 7/30/2020 #2

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

也就是说,如果您创建如下 SQL 字符串 (C#):

sql = "SELECT * FROM " + tableName;

然后,用户可能会输入“赞”tableName

MyTable; DROP TABLE MyTable

猜猜会发生什么。

因此,如果您检查表名称,则安全起见。

1赞 Bill Karwin 8/1/2020 #3

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

是的,这是安全的。如果您控制可插入 SQL 查询的值集,则可以防止未经授权的 SQL 注入。

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

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

查询参数只能用于代替单个标量值。也就是说,您将使用带引号的字符串文本、带引号的日期文本或数字文本。