默认情况下,ActiveRecord中的.order方法参数是否已清理?

and*_*scu 12 ruby-on-rails rails-activerecord

我正在尝试将字符串传递给.order方法,例如

Item.order(orderBy)
Run Code Online (Sandbox Code Playgroud)

我想知道orderBy是否默认清理,如果没有,那么清理它的最佳方法是什么.

Dyl*_*kow 16

订单没有消毒.此查询实际上将删除Users表:

Post.order("title; drop table users;")
Run Code Online (Sandbox Code Playgroud)

orderBy如果有任何方法orderBy可能会被用户输入污染,您将需要在运行查询之前检查变量.像这样的东西可以工作:

items = Item.scoped
if Item.column_names.include?(orderBy)
  items = items.order(orderBy)
end
Run Code Online (Sandbox Code Playgroud)


dro*_*att 7

它们的处理方式与.where子句相同?,但您可以使用#sanitize_sql_for_order:

sanitize_sql_for_order(["field(id, ?)", [1,3,2]])
# => "field(id, 1,3,2)"

sanitize_sql_for_order("id ASC")
# => "id ASC"
Run Code Online (Sandbox Code Playgroud)

http://api.rubyonrails.org/classes/ActiveRecord/Sanitization/ClassMethods.html#method-i-sanitize_sql_for_order

  • 这实际上对清理订单部分几乎没有作用。像 `sanitize_sql_for_order("id; drop table Somethings") 这样的东西仍然会出现意外的行为,最坏的情况是删除表:/ (3认同)
  • 检查源代码:https://github.com/rails/rails/blob/d15527800fbc199b969019c665226f836d8fedce/activerecord/lib/active_record/sanitization.rb#L64如果是单个字符串,它只会做_nothing_ :( (3认同)

Chr*_*all 5

只是为了更新 Rails 5+,在撰写本文时,将数组传递给orderwill(尝试)清理右侧输入:

Item.order(['?', "'; DROP TABLE items;--"])
#=> SELECT * FROM items ORDER BY '''; DROP TABLE items;--'
Run Code Online (Sandbox Code Playgroud)

这将在 Rails 5.1 中触发关于“危险查询方法”的弃用警告,该警告将在 Rails 6 中被禁止。如果您知道左侧输入是安全的,将其包装在Arel.sql调用中将使警告静音,并且可能仍然有效在 Rails 6 中。

Item.order([Arel.sql('?'), "'; DROP TABLE items;--"])
#=> SELECT * FROM items ORDER BY '''; DROP TABLE items;--'
Run Code Online (Sandbox Code Playgroud)

需要注意的是,左侧的不安全 SQL 将未经修改地发送到数据库。谨慎行事!

如果您知道您的输入将成为您模型的一个属性,您可以将参数作为散列传递:

Item.order(column_name => sort_direction)
Run Code Online (Sandbox Code Playgroud)

在这种形式中,如果列名对模型无效或排序方向无效,则 ActiveRecord 会报错。