I touched upon CSRF (cross-site request forgery) in my previous blog post, but as I was mentionining that it is distinct from XSS since the two get mixed up sometimes (must be the multi-fricative-consonant abbreviation), I realized that I should discuss it in greater detail.
Web Attack Types Vulnerabilities: Gotta Catch ‘Em All
Both XSS abd CSRF are types of web attacks (there are more than these two, but I have seen people get them confused, and they do have interesting parallels). XSS is cross-site scripting. CSRF, as previously mentioned, is cross-side request forgery.
The fundamental conceptual difference between CSRF and XSS is that CSRF exploits a website’s trust (authentication) of a user, whereas XSS exploits a user’s trust for a website.
XSS: The Mechanics
XSS involves injecting malicious scripts (in the case of Rails, it would usually be JavaScript, potentially combined with HTML, often with a <script>
tag) into a webpage. That script can be then executed when other users access the website.
For instance, a hacker introduces some JavaScript to the comments section of a webpage, and when other users try to access it, the script is executed and, say, the user is re-directed to a porn website they otherwise from their original destination S.H.I.E.L.D. subreddit.
XSS attacks are incredibly common and easy to execute if a website does not have appropriate security features.
XSS and Ruby on Rails: Opting Out of HTML Escape
As with CSRF, Rails comes with a reasonably strong protection against XSS attacks. That certainly makes life easier for most beginners who want to have a reasonably secure website without spending too much time researching security and focusing on building other skills first.
The idea behind Rails XSS protection is automatically sanitizing user input so that nothing gets executed as a script if it’s not meant to be. Back in the day, that had to be done manually, which, was extremely time-consuming and error-prone. So Rails 3 incorporated a simple idea: opting out of html escaping instead of opting in, if need be.
It accomplished that by integrating RailsXss
plugin, and the feature became part of Edge Rails as early as October 2009 (see more on Edge Rails in my post here ).
Rails 3+ officially supports this feature, and it backports to earlier versions of Rails as well.
I noticed from reading source code that Rails now assumes that no string input is html_safe?
by default, while integers are:
This is what it looks like in Rails console:
Html escape it can be still done manually with an html_escape
in front of whatever you are rendering within the erb tags.
html_escape
can be also aliased as h
, and it is fine to use it even if something is getting html escaped by default as Rails will recognize it as such and will only escape it once.
See example from source code:
The potentially ‘dangerous’ charactaters are converted into their human-readable equivalents as the same source code indicates:
HTML_ESCAPE = { '&' => '&', '>' => '>', '<' => '<', '"' => '"', "'" => ''' }
Similarily, html_escape_once
escapes HTML code without affecting existing escaped code:
If you do not want user input to be sanitized, then using raw
in the erb template is the way to go, e.g.:
If That Were Not Enough
Wikipedia article is a good starting point.
This Railscast episode is worth spending 8 minutes on, even though it is a bit older.
And as usual, more on XSS on the Rails Guides website.