我知道在调用.where
.
例如这个:
Client.where("orders_count = #{params[:orders]}")
应改写为:
Client.where("orders_count = ?", params[:orders])
调用时使用插值字符串是否安全.order
?如果不是,应该如何重写以下内容?
Client.order("#{some_value_1}, #{some_value_2}")
我知道在调用.where
.
例如这个:
Client.where("orders_count = #{params[:orders]}")
应改写为:
Client.where("orders_count = ?", params[:orders])
调用时使用插值字符串是否安全.order
?如果不是,应该如何重写以下内容?
Client.order("#{some_value_1}, #{some_value_2}")
是的,ActiveRecord 的“order”方法容易受到 SQL 注入的影响。
不,调用时使用插值字符串是不安全的.order
。
Aaron Patterson已确认我的问题的上述答案,他将我指向http://rails-sqli.org/#order。从该页面:
在 ORDER BY 子句中利用 SQL 注入很棘手,但可以使用 CASE 语句测试其他字段,将排序列切换为真或假。虽然它可能需要许多查询,但攻击者可以确定该字段的值。
因此,手动检查任何东西order
是否安全是很重要的;也许通过使用类似于@dmcnally 建议的方法。
谢谢大家。
简短的回答是你需要清理你的输入。
如果您计划插入的字符串来自不受信任的来源(例如 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)
@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)
只是去罗马的另一条路。希望这有帮助。
让我们试试这个!
# 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
Client.order("#{some_value_1}, #{some_value_2}")
应该写成
order = sanitize_sql_array(['%s, %s', some_value_1, some_value_2])
Client.order(order)