It is very important to filter malicious input, but when it comes to user agent injection, it is also important that the output does not contain executable code. I will introduce input filters afterwards. In general, it checks the user input to be of a specific format, and if not, rejects it with an error message. But importantly, the error message should not be too specific and should not re-display the input without output filtration.
Output filtration most commonly happens in Rails' view part of the application. If there is absolutely no HTML allowed in the user input, you can filter it with Ruby's escapeHTML() (or its alias h()) function which replaces the possibly malicious input characters &,",<,> with its uninterpreted representations in HTML (&, ", <, >). However, it can easily happen that the programmer forgets to use it just in one place, and so the web application is vulnerable again. It is therefore recommended to use the Safe ERB (http://www.kbmj.com/~shinya/rails/) plugin which will throw an error if so-called tainted strings are not escaped. In Ruby, a string will be tainted if it comes from an external source (for example, from the database, a file or via the Internet) and can be untainted by Safe ERB's modified escapeHTML() function or the Object.untaint() function.
However, if your application's users need text formatting in their input, it is best to use a markup language which is not interpreted by the user agent, but by the web application. For example there is RedCloth (http://whytheluckystiff.net/ruby/redcloth/) for this.
As for character encoding, you should enforce the user's browser to use the encoding you chose. In Rails you can enforce ISO-8859-15 by adding the following lines to application.rb:
after_filter :set_charset
private
def set_charset
content_type = @headers["Content-Type"] || 'text/html'
if /^text\//.match(content_type)
@headers["Content-Type"] = "#{content_type}; charset=ISO-8859-15"
end
end
And in the controller you can convert encodings, for example ISO-8859-15 to UTF-8, with this:
sconvcomment = Iconv.new('ISO-8859-15', 'UTF-8').iconv(params[:comment])






3 responses so far ↓
1 Alessandro "jekil" Tanasi blog // Jul 14, 2007 at 13:12
Rails Security: Secure your Ruby on Rails web application…
Ruby on Rails is a great Ruby framework for rapid development of web applications.But default Rails comes with some (in)security features that must be hardened and fixed.And a lot of the how to and tutorials in internet that publish the sponsor "w…
2 Maarten // Sep 11, 2007 at 3:17
Wouldn’t it be a better practice to verify all data before it is saved to string fields in the database with a white list for the fields that are allowed to contain html characters?
That way you only need to verify the data once: when it goes into the database and not every time you display it, accordingly to the DRY principle.
You could achieve this in the models with validation or write a plugin for it …
3 Heiko // Sep 11, 2007 at 3:42
This will certainly work for a small project, but a large project is much more complicated. Has this been sanitized before? Was this string being saved in an old version when we sanitized only the database output? What happens if there’s an error and the unsaved string will be re-displayed?
I prefer to validate it when it comes in and sanitize/escape it according to the output processor (HTML,CSS,Ferret,SQL,…).
Leave a Comment