20

我知道在调用.where.

例如这个:

Client.where("orders_count = #{params[:orders]}")

应改写为:

Client.where("orders_count = ?", params[:orders])

调用时使用插值字符串是否安全.order?如果不是,应该如何重写以下内容?

Client.order("#{some_value_1}, #{some_value_2}")

4

5 回答 5

19

是的,ActiveRecord 的“order”方法容易受到 SQL 注入的影响。

不,调用时使用插值字符串是不安全.order

Aaron Patterson已确认我的问题的上述答案,他将我指向http://rails-sqli.org/#order。从该页面:

在 ORDER BY 子句中利用 SQL 注入很棘手,但可以使用 CASE 语句测试其他字段,将排序列切换为真或假。虽然它可能需要许多查询,但攻击者可以确定该字段的值。

因此,手动检查任何东西order是否安全是很重要的;也许通过使用类似于@dmcnally 建议的方法。

谢谢大家。

于 2013-07-25T18:42:46.010 回答
9

简短的回答是你需要清理你的输入。

如果您计划插入的字符串来自不受信任的来源(例如 Web 浏览器),那么您需要首先将它们映射到受信任的值。你可以通过哈希来做到这一点:

# Mappings from known values to SQL
order_mappings = {
  'first_name_asc'  => 'first_name ASC',
  'first_name_desc' => 'first_name DESC',
  'last_name_asc'   => 'last_name ASC',
  'last_name_desc'  => 'last_name DESC',
}

# Ordering options passed in as an array from some source:
order_options = ['last_name_asc', 'first_name_asc']

# Map them to the correct SQL:
order = order_options.map{|o| order_mappings[o] }.compact.join(', ')
Client.order(order)
于 2013-07-25T15:04:29.330 回答
2

@Mike 的解释是正确的。@dmcnally 解决方法会起作用。我正在遵循 [Railscast][1] http://railscasts.com/episodes/228-sortable-table-columns中提到的稍微不同的路径

简而言之,如果您可以在控制器中构造一个私有方法,以清理用户输入:

  1. 按表列的名称排序:

        private 
    
        def sort_column
           Client.column_names.include?(params[:sort]) ? params[:sort] : "first_name"
        end
    
  2. 按其他标准排序,然后使用白名单结构,如下所示:

    def sort_direction
        %w[asc desc].include?(params[:direction]) ? params[:direction] : "asc"
    end
    

然后您的控制器方法应如下所示:

    Client.all.order(sort_column + " " + sort_direction)

只是去罗马的另一条路。希望这有帮助。

于 2019-03-08T17:15:35.960 回答
0

让我们试试这个!

# app/models/concern/ext_active_record.rb
module ExtActiveRecord
    extend ActiveSupport::Concern

    included do
        scope :sortable, -> (params) do
            return unless params[:sort_by] && params[:sort_dir]
            reorder("#{params[:sort_by]}" => "#{params[:sort_dir]}")
        end
    end
end

# app/models/user.rb
class User < ActiveRecord::Base
    include ExtActiveRecord
    # ....
end

# app/controllers/user_controller.rb
class UserController < ApplicationController
    def index
        @users = User.sortable(params).page(params[:page]).per(params[:per])
    end
end
于 2015-05-12T09:02:10.840 回答
-4

Client.order("#{some_value_1}, #{some_value_2}")

应该写成

order = sanitize_sql_array(['%s, %s', some_value_1, some_value_2])
Client.order(order)
于 2013-07-25T14:38:04.360 回答