Ruby on Rails Security Guide

Please refer the following for Ruby on Rails best practices on the security. CSRF and XSS are the most important ones:-

 

1) CSRF – https://selvaonrails.wordpress.com/2012/04/03/ruby-on-rails-security-csrf-3/

2) XSS – https://selvaonrails.wordpress.com/2012/04/03/ruby-on-rails-security-xss-2/

3) Protection flags on cookies – https://selvaonrails.wordpress.com/2012/04/03/ruby-on-rails-security-protection-flags-on-session-cookies/

4) Filter parameter logging – https://selvaonrails.wordpress.com/2012/04/03/ruby-on-rails-security-filtering-parameter-logging/

Advertisements

Ruby on Rails Security – XSS

Analysis:

An entry point to this kind of attack is a vulnerable URL and its parameters where an attacker can start attack. An attacker injects some code, the web application saves it and displays it on a page. XSS can steal the cookie, hijack the session, redirect the victim to a fake website, display advertisements, change elements on the web site or install malicious software through security holes in the web browser. The most common XSS language is of course the most popular client-side scripting Javascript, often in combination with HTML. Escaping the user input is essential.

Solution and Fix:

Multiple fixes is needed for this, 1) Escaping on the parameters and 2) Escaping on the output values.

1)      Escaping on the parameters (Refer:- https://selvaonrails.wordpress.com/2012/04/03/ruby-on-rails-sanitize-4/)

A check has to be done for escaping the malicious scripts in the parameters with the help of ‘Sanitize’ gem. For example, an attacker can pass some script like below in the scope parameter.

https://www.domain.com/user/login?scope=<script>document.write(document.cookie);</script>.

If the above is executed successfully means, the attacker will stole the cookie from the web page. To avoid this, parameters needs to be checked and the scripts needs to be escaped. This can be achieved with the help of ‘Sanitize’ gem with some code like below.

Sanitize.clean(“//value goes here//”)

The above will check for the value of the parameters and escape the scripts, if any.

2)      Escaping on the output values

As a second step, it is good practice to escape all output of the application, especially when re-displaying user input, which hasn’t been input-filtered using escapeHTML() or it’s alias h() method to replace the HTML input characters &,”,<,> by their uninterpreted representations in HTML.

Ex:- <%=h @value_to_be_displayed %>

Links for References:

1)   http://guides.rubyonrails.org/security.html#cross-site-scripting-xss

Comparition of Adopting Unobstructive Javascript and XSS in Rails 2 & 3

Cross-Site-Scripting in Rails 2

<%= @post.body %> –> Unsafe
<%= h @post.body %> –> Safe

Cross-Site-Scripting in Rails 3

<%= @post.body %> –> Safe
<%= raw @post.body %> –> Unsafe

Adopting Unobstructive Javascript
Example 1 :

Rails 2:

<%= link_to_remote ‘Show’, :url => post %>

Will generate a HTML like,
“<a href=”#” onclick=”new Ajax.Request(‘/posts/1′, {asynchronous:true,
evalScripts:true, parameters:’authenticity_token=’ +
encodeURIComponent(‘9sk..44d’)}); return false;”>Show</a>”
Rails 3:

<%= link_to ‘Show’, post, :remote => true %>

Will generate a HTML like,
“<a href=”/posts/1″ data-remote=”true”>Show</a>”

Example 2 :

Rails 2:

<% remote_form_for(@post) do |f| %>

Will generate a HTML like,
“<form action=”/posts” id=”new_post” method=”post”
onsubmit=”new Ajax.Request(‘/posts’, {asynchronous:true,
evalScripts:true, parameters:Form.serialize(this)}); return false;”>”
Rails 3:

<% form_for(@post, :remote => true) do |f| %>

Will generate a HTML like,
“<form action=”/posts” data-remote=”true” id=”new_post” method=”post”>”

Example 3 :

Rails 2 & 3:

<%= link_to ‘Destroy’, post, :method => :delete %>

Will generate a HTML like this for Rails 2,
“<a href=”/posts/1″ onclick=”var f = document.createElement(‘form’); f.style.display = ‘none’;
this.parentNode.appendChild(f); f.method = ‘POST’; f.action = this.href;var m =
document.createElement(‘input’); m.setAttribute(‘type’, ‘hidden’); m.setAttribute(‘name’, ‘_method’);
m.setAttribute(‘value’, ‘delete’); f.appendChild(m);var s = document.createElement(‘input’);
s.setAttribute(‘type’, ‘hidden’); s.setAttribute(‘name’, ‘authenticity_token’); s.setAttribute(‘value’,
‘9skdJ0k+l9/q3PWToz6MtfyiB2gcyhnKubeGV6WFL44=’); f.appendChild(s);f.submit();return false;”>Destroy</a>”

And Will generate a HTML like this in Rails 3,
“<a href=”/posts/1″ data-method=”delete” rel=”nofollow”>Destroy</a>”

Example 4 :

Rails 2 & 3:

<%= link_to ‘Destroy’, post, :confirm => ‘Are you sure?’, :method => :delete %>

Will generate a HTML like this for Rails 2,
“<a href=”/posts/1″ onclick=”if (confirm(‘Are you sure?’)) { var f = document.createElement(‘form’);
f.style.display = ‘none’; this.parentNode.appendChild(f); f.method = ‘POST’; f.action = this.href;var m =
document.createElement(‘input’); m.setAttribute(‘type’, ‘hidden’); m.setAttribute(‘name’, ‘_method’);
m.setAttribute(‘value’, ‘delete’); f.appendChild(m);var s = document.createElement(‘input’);
s.setAttribute(‘type’, ‘hidden’); s.setAttribute(‘name’, ‘authenticity_token’); s.setAttribute(‘value’,
‘9skdJ0k+l9/q3PWToz6MtfyiB2gcyhnKubeGV6WFL44=’); f.appendChild(s);f.submit(); };return false;”>Destroy</a>”

And Will generate a HTML like this in Rails 3,
“<a href=”/posts/1″ data-confirm=”Are you sure?” data-method=”delete” rel=”nofollow”>Destroy</a>”

Example 5 :

Rails 2 :

<%= f.submit ‘Create Post’, :disable_with => “Please wait…” %>

Will generate a HTML like ,
“<input id=”post_submit” name=”commit” onclick=”if (window.hiddenCommit)
{ window.hiddenCommit.setAttribute(‘value’, this.value); }else { hiddenCommit =
document.createElement(‘input’);hiddenCommit.type = ‘hidden’;hiddenCommit.value =
this.value;hiddenCommit.name =
this.name;this.form.appendChild(hiddenCommit); }this.setAttribute(‘originalValue’,
this.value);this.disabled = true;this.value=’Please wait…’;result =
(this.form.onsubmit ? (this.form.onsubmit() ? this.form.submit() : false) :
this.form.submit());if (result == false) { this.value =
this.getAttribute(‘originalValue’);this.disabled = false; }return result;” type=”submit”
value=”Create Post” />”

Rails 3 :

<%= f.submit :disable_with => “Please wait…” %>

Will generate a HTML like ,

“<input data-disable-with=”Please wait…”
id=”post_submit” name=”commit” type=”submit” value=”Create Post” />”