Является ли метод "заказа" ActiveRecord уязвимым для SQL-инъекции?

Я знаю, что небезопасно использовать интерполированные строки при вызове .where.

например. это:

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

следует переписать как:

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

Можно ли использовать интерполированные строки при вызове .order? Если нет, как следует переписать следующее:

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

Ответ 1

Да, метод "Order" ActiveRecord уязвим для SQL-инъекции.

Нет, небезопасно использовать интерполированные строки при вызове .order.

Вышеуказанные ответы на мой вопрос были подтверждены Аарон Паттерсон, который указал мне на http://rails-sqli.org/#order. С этой страницы:

Использование SQL-инъекций в предложениях ORDER BY является сложным, но Оператор CASE может использоваться для проверки других полей, переключения сортировки столбец для true или false. Хотя это может занять много запросов, злоумышленник может определять значение поля.

Поэтому важно вручную проверить, что все, что происходит в order, безопасно; возможно, используя методы, похожие на @dmcnally предложения.

Спасибо всем.

Ответ 2

Короткий ответ: вам нужно санировать ваши входы.

Если строки, которые вы планируете интерполировать, поступают из ненадежного источника (например, веб-браузера), вам необходимо сначала сопоставить их с доверенными значениями. Вы можете сделать это через хэш:

# 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)

Ответ 3

Попробуй это!

# 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

Ответ 4

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

следует записать как

order = sanitize_sql_array(['%s, %s', some_value_1, some_value_2])
Client.order(order)