使用column_names.include?防止SQL注入?

时间:2017-06-01 21:05:22

标签: ruby-on-rails

我有一个rails API来处理来自我前端的请求。这些请求包括url中的查询参数,用于对数据库中的结果进行精炼和排序。示例URL查询如下所示:

http://localhost:8000/clients?_sort=name&_order=DESC&_start=0&_end=10

我的控制器中的索引方法抓取这些参数并使用它们进行过滤和排序:

def index
  @all_clients = Client.all
  response.headers['X-Total-Count'] = @all_clients.count

  if (Client.column_names.include?(params[:_sort]))
    if (params[:_order] == 'ASC') 
      @clients = Client.filtered(params[:_start].to_i, params[:_end].to_i).order("#{params[:_sort]} asc")
    else
      @clients = Client.filtered(params[:_start].to_i, params[:_end].to_i).order("#{params[:_sort]} desc")
    end
  end

  json_response(@clients || @all_clients)
end

filtered方法是一个看起来像这样的范围: scope :filtered, -> (_start, _end) { limit(_end-_start).offset(_start) }

我的问题是:通过使用Client.column_names.include?来检查params[:_sort]是否是要排序的有效属性,我是否有效地将SQL注入列入白名单?如果没有,我怎么能改变这个代码来防止SQL注入?

1 个答案:

答案 0 :(得分:3)

这里要考虑的重要事项不是“params的白名单”(因为你已经在挑选使用哪些参数,而不是盲目地使用整个params哈希值),而是如何构建SQL

代码中有两个潜在的注入区域:

limit(_end-_start)

这容易受到伤害吗? 否。如果_end_start除了整数之外的任何内容,那么代码将会失败并显示错误消息 - 例如:

  

NoMethodError:未定义的方法` - '表示“DROP_TABLE”:字符串

     

     

ArgumentError:Integer()的值无效:3.14159

order("#{params[:_sort]} desc")

这容易受到伤害吗? 是。(但不容易。)This page给出了一个具体的例子:

params[:_sort] = "(CASE SUBSTR(password, 1, 1) WHEN 's' THEN 0 else 1 END)"

你应该永远不要在SQL 中使用直接字符串插值,除非你绝对100%确定该字符串是“安全的”。在这种情况下,您可以将其写为:

order(params[:_sort] => :asc)