Rails 5.2.3上的危险查询方法弃用警告

Gom*_*thi 5 sql-injection ruby-on-rails ruby-on-rails-5.2

我正在将Rails应用程序升级到5.2.3

我在我的应用程序中使用以下代码。

MyModel.order('LOWER(name) ASC')
Run Code Online (Sandbox Code Playgroud)

它将引发以下弃用警告:

DEPRECATION WARNING: Dangerous query method (method whose arguments are used as raw SQL) called with non-attribute argument(s): "LOWER(name)". Non-attribute arguments will be disallowed in Rails 6.0. This method should not be called with user-provided values, such as request parameters or model attributes. Known-safe values can be passed by wrapping them in Arel.sql()
Run Code Online (Sandbox Code Playgroud)

我已根据弃用警告的建议更改了上述内容,并且该警告消失了:

MyModel.order(Arel.sql('LOWER(name) ASC'))
Run Code Online (Sandbox Code Playgroud)

我已经在这里浏览了有关的讨论。似乎引入了此更改是为了禁止SQL注入。

但是order子句LOWER(name) ASC不包含任何用户输入。为什么此命令被认为是不安全的?这是预期的行为,还是我在这里遗漏了任何东西?

Zia*_*hal 10

这是预期的行为,您链接到正确的讨论,这正是它的内容。不过,我可以再详细说明一下,这样很容易理解。

首先重新解释sql注入,仅供参考,这样做:

MyModel.order('LOWER(name) ASC')
Run Code Online (Sandbox Code Playgroud)

意味着人们可以在 order 函数中传递任意字符串,该字符串可能包含用户输入的列名和/或订单类型。

现在可以说,您的 Web 应用程序中有一个下拉列表,用户在其中选择列,另一个用户选择 desc 或 asc 并提交。数据。

在控制器操作上,人们可能正在做的是:

order_sql = "#{params[:column_name]} #{params[:column_order]}"
Run Code Online (Sandbox Code Playgroud)

这正是 sql 注入可能发生的地方,恶意用户可以编辑表单提交数据,而不是发送ascdesccolumn_orderparam 中,他可以发送一些 sql 脚本,例如:asc; delete from table_name_user_guessed_or_knows导致 SQL 注入,这就是为什么 rails 希望用户在使用时要小心使用 sql 排序函数。并允许特定用户的安全sql Arel

现在是第二部分,为什么name asc允许作为输入而LOWER(name) asc不允许?

弃用警告如下:

弃用警告:使用非属性参数调用的危险查询方法(其参数用作原始 SQL的方法):“LOWER(name) asc”。Rails 6.0 中将不允许使用非属性参数。不应使用用户提供的值调用此方法,例如请求参数或模型属性。可以通过将已知安全值包装在 Arel.sql() 中来传递它们

关注以下词:non-attribute argument(s), 非属性参数是任何不是属性的东西,无论是在 SQL 注入的末尾附加的任何额外的 sql 还是对属性的一些方法调用,因为方法调用也可用于改变预期的行为SQL。

接下来,你问:

订单子句 LOWER(name) ASC 不包含任何用户输入

Rails 根本无法知道字符串是如何形成的,它只知道它正在传递一个字符串。这就是为什么它抱怨并希望开发人员保持谨慎。

这就是为什么name asc是允许的,因为它是简单的属性参数。虽然LOWER(name) asc抛出警告是因为它不是简单的属性参数,但在这个参数上有一个方法调用,它可能被用于 SQL 注入。
(显然,攻击者可能不会使用简单的LOWER函数进行攻击,而是会使用一些特殊的函数,也许是他在之前的某个甚至相同的调用中使用类似注入方法定义的函数)。