Posts Tagged ‘security’

Rails XSS Filter

Wednesday, June 20th, 2007

I was pushed to put XSS protections into CrowdVine when one of the Foo Camper’s released this XSS crack into the Foo Camp social network. It causes a person to friend everyone in the network and then inserts itself into your profile. It was brutal. Worse it was a very simple and readable 49 lines of code. I took one glance at it and realized that even I know enough javascript to write one of these.

Looking around I saw two approaches for Rails. Run Safe ERB and force yourself to validate each individual input or run Rick Olson’s white list plugin.

I decided to use the white_list plugin to clean all values in params. It required a little bit of tweaking. Here’s the details.

Install the white list plugin:

script/plugin install -x http://svn.techno-weenie.net/projects/plugins/white_list/

Edit vendor/plugins/white_list/init.rb so that white_list is available in the Controller:


require 'white_list_helper'
ActionController::Base.send :include, WhiteListHelper

Add a filter to application.rb in order to walk the params hash:


before_filter :sanitize_params

def sanitize_params
# TODO: 2007-06-20  -- I found that this didn't
# work when called with params instead of @params. I assume
# I'm clueless in some important regard. (Many important regards?)
@params = walk_hash(@params) if @params and !site_owner?
end

def walk_hash(hash)
hash.keys.each do |key|
if hash[key].is_a? String
hash[key] = white_list(hash[key])
elsif hash[key].is_a? Hash
hash[key] = walk_hash(hash[key])
elsif hash[key].is_a? Array
hash[key] = walk_array(hash[key])
end
end
hash
end

def walk_array(array)
array.each_with_index do |el,i|
if el.is_a? String
array[i] = white_list(el)
elsif el.is_a? Hash
array[i] = walk_hash(el)
elsif el.is_a? Array
array[i] = walk_array(el)
end
end
array
end

Does this look right to people? Is there a more idiomatic ruby/rails way to do this? I’m a bit worried about how this will perform on very large chunks of data or on deeply nested hashes.