SQL injection注入是说攻击者可以输入任意的SQL让网站执行,这可说是最有杀伤力的攻击。如果你写出以下这种直接把输入放在SQL条件中的程式:
Project.where("name = '#{params[:name]}'")
那么使用者只要输入:
x'; DROP TABLE users; --
最后执行的SQL就会变成
SELECT * FROM projects WHERE name = 'x'; DROP TABLE users; --’
其中的;结束了第一句,第二句DROP TABLE users;就让你欲哭无泪。
Exploits of a Momhttp://xkcd.com/327/
要处理这个问题,也是一样要对任何有包括使用者输入值的SQL语句做逸出。在Rails ActiveRecord的where方法中使用Hash或Array写法就会帮你处理,所以请一定都用这种写法,而不要使用上述的字串参数写法:
Project.where( { :name => params[:name] } )
# or
Project.where( ["name = ?", params[:name] ] )
如果你有用到以下的方法,ActiveRecord是不会自动帮你逸出,要特别注意:
• find_by_sql
• execute
• where 用字串参数
• group
• order
详见 Rails SQL Injection
你可以自定一些固定的参数,并检查使用者输入的资料,例如:
class User < ApplicationRecord
def self.find_live_by_order(order)
raise "SQL Injection Warning" unless ["id","id desc"].include?(order)
where( :status => "live" ).order(order)
end
end
或是手动呼叫ActiveRecord::Base::connection.quote方法:
class User < ApplicationRecord
def self.find_live_by_order(order)
where( :status => "live" ).order( connection.quote(order) )
end
end