我知道在调用.where
时使用插值字符串是不安全的。
e.g。这样:
Client.where("orders_count = #{params[:orders]}")
应改写为:
Client.where("orders_count = ?", params[:orders])
调用.order
时使用插值字符串是否安全?如果没有,应该如何重写以下内容?
Client.order("#{some_value_1}, #{some_value_2}")
答案 0 :(得分:16)
是的,ActiveRecord的“订单”方法 容易受到SQL注入攻击。
不,在调用.order
时使用插值字符串 是安全的。
我的问题的上述答案已由Aaron Patterson确认,他指出http://rails-sqli.org/#order。从该页面:
在ORDER BY子句中利用SQL注入是棘手的,但是a CASE语句可用于测试其他字段,切换排序 列为true或false。虽然它可能需要许多查询,但攻击者 可以确定该字段的值。
因此,手动检查前往order
的任何内容是安全的非常重要;也许通过使用类似于@dmcnally建议的方法。
谢谢大家。
答案 1 :(得分: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)
答案 2 :(得分:1)
@Mike的解释是正确的。 @dmcnally解决方法将起作用。我遵循的是[Railscast] [1] http://railscasts.com/episodes/228-sortable-table-columns
中提到的略有不同的路径简而言之,如果您可以在控制器中构造一个私有方法,以便清理用户输入:
按表列之一的名称排序:
private
def sort_column
Client.column_names.include?(params[:sort]) ? params[:sort] : "first_name"
end
按其他条件排序,然后使用以下白名单结构:
def sort_direction
%w[asc desc].include?(params[:direction]) ? params[:direction] : "asc"
end
然后您的控制器方法应如下所示:
Client.all.order(sort_column + " " + sort_direction)
前往罗马的另一条路。希望对您有所帮助。
答案 3 :(得分: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
答案 4 :(得分:-2)
Client.order("#{some_value_1}, #{some_value_2}")
应该写成
order = sanitize_sql_array(['%s, %s', some_value_1, some_value_2])
Client.order(order)