Advanced Rails - Building Industrial-Strength Web Apps in Record Time

(Tuis.) #1

140 | Chapter 5: Security


In many cases, this is desirable: a blog will allow users to comment on entries, in
some cases adding their own HTML. This can expose a vulnerability: if script tags
are not filtered out before displaying the content, they are exposed to viewers as if
part of the third-party site. This can bypass browser security policies, as browsers
usually restrict scripts’ access permissions based on the origin of the code. If the code
appears to be coming from the target site, it can access information (e.g., cookies)
belonging to the target site.


Mitigation


Defending against XSS vulnerabilities can be either very easy or very difficult. If the
application in question does not allow untrusted users to enter HTML, defending
against XSS is easy. In this case, each HTML character must be escaped before out-
put. The Railsh( ) method escapes all special HTML characters for you:


<% @post.comments.each do |comment| %>
<li><%=h comment.text %></li>
<% end %>

On occasion, there is debate over whether to store content that must be escaped for
display in its plain-text or escaped forms. The advantage of storing data escaped is that
you never forget to escape it for display; the advantage of storing it unescaped is that it
is in its “natural” state. Cal Henderson makes a good point regarding this: you never
know when you might have to escape data in a different manner for display else-
where, so data should usually be stored in its plain-text form. An exception might be
made for Unicode: it is usually important to ensure that data stored in a Unicode
encoding is well-formed, lest it cause problems in processing. In situations like this,
it is usually best to check for well-formedness at both ingress and egress.


Of course, things are rarely this simple. The reason XSS attacks are still so common
is that often developers want their untrusted users to be able to enter arbitrary
HTML, just not the “verboten tags” and “verboten attributes”—those that can exe-
cute scripts. And filtering them out is harder than it might seem (see the section
“Canonicalization: What’s in a Name?,” later in the chapter, for the reason why).


Rails provides some help here, through the sanitize( ) method. This method
removes form and script tags, elides the onSomething attributes, and kills any URIs
with the “javascript:” scheme. The default set of prohibited tags and attributes may
be sufficient to block execution of arbitrary script. This method is used just likeh( ):


<% @post.comments.each do |comment| %>
<li><%=sanitize comment.html %></li>
<% end %>

However, you should be very, very careful when using blacklisting such as this. There
are too many edge cases to be absolutely sure that every piece of potentially malicious
code is blocked. Rails security experts advise against the use of blacklisting.*



  • Seehttp://www.rorsecurity.info/2007/08/17/dont-use-strip_tags-strip_links-and-sanitize/.

Free download pdf