Topic: XSS and when h just ain't enough.

I'm just setting out developing with rails at the moment and one of the things I take a bit of an interest (as it's my day job) is website security.

Now I hope everyone will be familiar with the concepts of Cross-Site Scripting (XSS) and why it's a bad thing, but if not here's a brief overview.

Basically XSS attacks generally occur when a user of a site is able to pass code to a website which contains Javascript code, which is executed by the site when the page containing the users submission is rendered.

A classic example is a bulletin board site, if a user can enter a post which has

<script>alert("xss")</script>
and not have any of those characters escaped or removed, then they'll likely be able to execute any javascript as though it came from the source website.

So onto Rails.  One of the standard pieces of advice I've seen for dealing with this problem in rails apps is to use the h() function whereever your putting content supplied by the user up onto the screen, and that is good advice...

but...

What about times where you can't do that.  A good example is the in place editor field.  If you try using h() there you will usually just end up breaking the javascript that runs the control.

My advice would be to look at santizing all your input data, at the point it gets submitted to your application, not just when it's replayed to the screen, that way you can avoid running the risk of missing an h() off somewhere or having the data output somewhere where you can't use it.

One method I've used to do this on a little app. I'm using to teach myself rails is this.

This is the controller method I use to create a new task in my todolist program

def create_task
  params[:task].each do |key, value|
    params[:task][key] = CGI::escapeHTML(value)
  end
  @task = Task.new(params[:task])
  if @task.save
    flash[:notice] = "New Task Saved OK"
    redirect_to :action => :index
  else
    render :action => :new_task
  end
end

The key lines are the first three which essentially iterate through the values for the task and escape any HTML characters in them (by the way you'll need require 'cgi' at the top of your controller for this to work)

Another option would be instead of escaping the characters in the form to simply strip any character classes you don't want from the data before saving it, using a similar mechanism...

hope this helps.

Re: XSS and when h just ain't enough.

Good tip and easy to implement. I always feel more comfortable knowing that the data is secure and safe before it gets near the database.

Does RoR have the equivilent of PHP's strip_tags() in which you can define certain HTML tags that are allowed, or would you just need to write out a regexp for it?

Re: XSS and when h just ain't enough.

Kelli wrote:

Does RoR have the equivilent of PHP's strip_tags() in which you can define certain HTML tags that are allowed, or would you just need to write out a regexp for it?

WhiteList looks really nice for this kind of thing; you can filter out tags and attributes that you want/don't want displayed as HTML.

vinnie - rails forum admin

Re: XSS and when h just ain't enough.

Let's say you where going to implement a simple forum.  You most certainly would allow somone to post an off-site image, right?  I mean, you'd not filter out <img ...> from a forum.  What kind of a forum would not allow images?

I'm running a very old phpBB based website, and am up to my gills in XSS, and possibly CSRF vulnerabilities.  A good article to read is: Foiling Cross-Site Attacks.

If you look at that article, and then go to the Excellent set of XSS test cases, and you'll find you've got a pretty big mess on your hands.
Example:

<IMG SRC="http://www.thesiteyouareon.com/somecommand.php?somevariables=maliciouscode">

Even if you dissallow all HTML, and do something like BBCode, it's not a given that you'll be safe.  I'm just now wrapping my head around the security implications.  Would h catch the malformed ASCII example?

I'm not an expert on this by any means -- I'm just starting to read up on the problem, and it's really tricky.

So the next step is to try to parse what is in the <IMG...> tags, right?  Well, that is harder than one might think.  At least it appears to me that way.  You can't rely on anything to be as it appears.  Null-breaks, special charcater encodings, spaces that you don't expect, and to top it off, the URL could look absoluteley correct:

<IMG SRC="http://bad.website.com/a.jpg">

The above may actually be a vulnerability if the apache server on bad.website.com is set up like so:
Redirect 302 /a.jpg http://victimsite.com/admin.asp&deleteuser

So with that example, if you trust any extrenal images, you've just opened yourself up for possibly security issue.  Certainly the redirect will only work if (in the above example)  admin.asp was not careful in checking things.

Security is an issue for me, and I'm in the process of deciding what framework I want to start with to re-implement my website with.  At the moment my head is spinning from all the possible attacks. 

Please someone that knows ruby-on-rails:  Can you read the above articles and security threat examples I provided on the links and comment. 

I'm not sure what the answer is to security... are you?  What about session cookies and sticky logins?  How secure are those things, if someone somehow can find a way to inject a script?

Re: XSS and when h just ain't enough.

Slurpy wrote:

Let's say you where going to implement a simple forum.  You most certainly would Example:

<IMG SRC="http://www.thesiteyouareon.com/somecommand.php?somevariables=maliciouscode">

I don't get the risk here. Obviously IMG tags can include any URL, if simply accessing a url on your page can damage stuff, then surely that is your problem, not the ability to post any old url in an IMG?

-MrFunk

Last edited by MrFunk (2006-11-07 23:07:26)

Re: XSS and when h just ain't enough.

The point is that an IMG tag can point to an off-site image.  How do you know that the offsite resource really is an image and not a piece of code that injects javascript or simply a redirect back to your site, which in turn tries to activate some administrative function?

Let's say you have an admin called "jeff", and a hacker called "hacker".

Step 1:
Hacker posts a message with an img tag that goes to his own server.  He sets up his server to not serve an image, but instead redirect the browser back to your sites administrative function to delete a user.  You'd not know this by looking at the IMG tag.

Step 2:
Jeff logs into the site.  He authentiactes as usual, and evertyhing is fine.  Jeff browses the forums, and comes across the post written by hacker.  Jeffs' browser goes off to fetch that "image" that hacker posted -- but instead of getting an image, your browser is redirected to the admin function.  You'd not know it, because the IMG tag looks like it's going to a normal image.  It's hacker's server that did a bait-and-switch on you (with the specified redirect).

Step 3: 
The redirect that hacker wrote goes and executes, and because jeff is authenticated as an admin, the browser and session is authenticated as an admin.  Although jeff didn't mean to, the redirect just gone and performed some administrative function for him to delete some user (maybe even himself?).

Yes there are ways of writing your application to protect from a redirect attack, but if you sit down and read though the hacker page (http://ha.ckers.org/xss.html), and spend some time really understanding the implications -- I think it will make your skin crawl.

My point is that your website is vulnerable to this kind of attack if you trust all third-party IMG tags, and allow people to embed the graphics into your website -- and you are not super careful in how you deal with admin functionality.  Again, we're talking about a vulnerability that exploits the proper function of your website after a trusted user & admin (Jeff) has been authenticated.

It is dangerous to whitelist tags in general and think you're safe. 

Most of the time no one is going to go through the trouble of hacking your site like that.  The issue is that when you have a website for an online game (like I do), and you have people that declare "war" on you because they violated your community rules, and you had to ban them -- well, some people just seem to have infinite time to think about how to attack your site and "get back" at you.

I'm highly annoyed about all of this.  It's not like I'm some ivry-tower what-if guy that likes to theorize about highly unlikeley attacks and then spend uncountable number of hours securing something that didn't need to be secured in the first place.

Re: XSS and when h just ain't enough.

reply to Slurpy:
Dontcha know that all actions that delete/edit and so fourth wants to have a method other than get (post, put, ...), and redirects can't do other than get right?

//yay, my first message in this forum, and you need to bare with my english tongue

Re: XSS and when h just ain't enough.

That is a good point, and the controller should make sure that a delete or modify action are written to ensure the proper request type.  Good thing rails has verify :method => :post, :only => [...]

The biggest point I'm trying to make is that whitlisting tags cannot be the whole story to your security.  As you point out, controllers must also make sure certain create/update/deletes require a post or put.  But when you think about it, the reason why create/update/delete should not be executed on a get isn't so much about security, but about "clean" and "good" implementation style that embraces original thinking of the W3C spec.  It's more about what can "safely be cached" etc.

So it's a technicality that can also make your application more secure.  Clearly whitelisting wasn't the whole story to making your application more secure if you rely on this line of protection.

I would not be surprised that there are other attacks to consider.  I just raised this one example because it's somewhat unexpected.  I certainly never thought about what could be done with a simple IMG tag.  If you look at the hackers site, it seems a good amount of attacks are used by putting unexpected things into the IMG tag.  My point is, if you allow an IMG tag, and you care about security, can you be sure that none of these methods are going to bite you?

Re: XSS and when h just ain't enough.

Is this article still up to date? Or does rails has now built-in security for xss?

Last edited by reyntjensw (2008-08-02 16:21:43)

Re: XSS and when h just ain't enough.

class XssInputObserver < ActiveRecord::Observer
  observe Employee, Employer

  def before_save(model)
    model.attribute_names.each do |attrib|
      model[attrib] = CGI::escapeHTML(model[attrib]) if model[attrib].kind_of? String
    end
  end
end


Unfortunately, further updates causes some recursion:

&lt;script&gt;&lt;/script&gt;
&amp;lt;script&amp;gt;&amp;lt;/script&amp;gt;
&amp;amp;lt;script&amp;amp;gt;&amp;amp;lt;/script&amp;amp;gt;

Re: XSS and when h just ain't enough.

reyntjensw wrote:

Is this article still up to date? Or does rails has now built-in security for xss?

Rails now has a little bit more security than it used to do. You can read more at http://api.rubyonrails.org/classes/Acti … thods.html

David Svensson
Rails developer at Standout solutions, Vaxjo, Sweden

Re: XSS and when h just ain't enough.

marcin.urbanski wrote:

... further updates causes some recursion:

&lt;script&gt;&lt;/script&gt;
&amp;lt;script&amp;gt;&amp;lt;/script&amp;gt;
&amp;amp;lt;script&amp;amp;gt;&amp;amp;lt;/script&amp;amp;gt;

Can you do a simple replace where

&amp;

is replaced with
&

wherever its found?

I'm kinda new to this, so if this raises a security issue, please point it out...

Re: XSS and when h just ain't enough.

We use xss_terminate to sanitize user input (even from admins), and instead users can use Textile handled by RedCloth to to do some styling of any input.

Re: XSS and when h just ain't enough.

Thanks for the tips, there's more here than I would have hoped to find. I was mainly concerned about the security features so I found a cloud security resource that is supposed to cover all the information we need.