【发布时间】:2014-01-04 22:39:20
【问题描述】:
感谢您对此的帮助!我正在开发一个遗留的 Rails 应用程序,我检查了一些来源,但无法使它们适合我的情况。在 Rails 2.3 中,我有一个搜索表单 (index.html.erb) 和一个控制器 (search.rb)。控制器使用搜索字段构建一个字符串,该字符串保存在变量@search_string 中。
@search_string = ""
为了显示搜索结果,控制器使用:
@location_matches = Location.paginate_by_sql("select * from locations where #{@search_string} order by nickname asc", :page => params[:page], :per_page => 20)
对我来说,清理上述内容的最简单方法是什么?我试过了
@location_matches = Location.paginate_by_sql('SELECT * FROM locations WHERE #{@search_string} = ?', @search_string)
这会引发错误 ArgumentError(预期参数散列)。仅供参考,@search_string 是用这样的表单字段构建的:
表格
<label for="city">City</label>
<input id="city" name="city" size="30" type="text" value="" />
控制器
if params[:city] != ""
@search_string << "and city like '%#{params[:city]}%' "
if @first_term == 'y'
@search_string = @search_string.gsub('and ', " ")
@first_term = 'n'
end
end
我很确定各个字段没有正确参数化,但我没有遍历每个字段并尝试修复它,而是通过调整 paginate_by_sql 语句来寻找更快的解决方案(我是 Rails 新手我只是想快速修复一下,因为整个应用程序最终都需要升级。)
编辑
我按照Rails, how to sanitize SQL in find_by_sql 中的步骤添加了一个初始化程序。我还将我的声明更改为以下内容。但是,当我运行搜索时,我没有得到任何结果。我还不得不删除升序条件,因为它引发了错误。非常欢迎任何想法!
初始化器
class ActiveRecord::Base
def self.escape_sql(clause, *rest)
self.send(:sanitize_sql_array, rest.empty? ? clause : ([clause] + rest))
end
end
控制器
query = Location.escape_sql(["SELECT * from locations WHERE #{@search_string} = ?", params[:@search_string]])
@location_matches = Location.paginate_by_sql(query, :page => params[:page], :per_page => 20)
日志(看起来和返回结果的代码一样)
Parameters: {"city"=>"New York", "commit"=>"Search", "search"=>{"size_category"=>"", "state"=>""}}
【问题讨论】:
-
是的,这实际上是我检查的来源之一,但我无法将那里的内容应用于这个问题,我在 WHERE 语句中有一个变量,我正在尝试清理变量。我对这些陈述不熟悉,所以我非常感谢您提供的任何帮助!
-
我可以这样做吗?
query = Location.escape_sql(["SELECT * from locations WHERE #{@search_string} = ?", @search_string)然后@location_matches = Location.paginate_by_sql(query order by nickname asc, :page => params[:page], :per_page => 20)
标签: mysql ruby-on-rails sql-injection ruby-on-rails-2