我有一个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注入?
答案 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)