From the category archives:

Ruby on Rails

The One-day app challenge

by neil on July 29, 2009

Please note this blog has been moved to blog.platform45.com

Inspired by Rails Rumble we’ve decided to run our own one-day app challenge.

The idea of a one-day app is to conceptualize, develop, design and market a web based application in 24 working hours. This challenge is aimed at keeping us, the Platform45 team on our toes and it ensure that we stick to the fundamentals of developing and designing applications.

Rules of the game:24tv-730423

1. The whole process must be completed in 24 working hours, 3 working days.
2. No design or development is allowed once the time is up.

If you want to play, let us know: We are looking for idea’s, tips and hints for our next application. Leave a comment or email us.

If you would like to know when the countdown for the next challenge begins, take a look at the one-day app section on our website. Here you’ll find all one-day apps and apps in progress.

{ 2 comments }

Watch twitter in real time

by neil on July 21, 2009

Please note this blog has been moved to blog.platform45.com

There’s been a lot of talk about real time web at Platform45 lately. All these discussions spurred on the creation of our first one-day app.

The idea behind our one-day apps are too conceptualize, design and develop an application in one working day.

Mentions will track a keyword as it is posted on twitter in realtime.

madiba

Try out Mentions. I find it strangely addictive!

Ruby on Rails : Danger! Mass Assignment

by neil on May 28, 2009

Please note this blog has been moved to blog.platform45.com

You should not create or update records directly from parameters!

 
     @user = User.new(params[:user])
 

This is mass assignment. It is creating a new user object from all the attributes assigned to :user

 <% form_for @user do |f| %>
 <%= f.text_field :name %>
 <%= f.text_field :email %>
 ...

All the attributes from this parameters hash with be be used in creating a new user model. If your user table contains an admin field. The ‘attacker’ can submit a post, setting admin = true.

 <% form for @user do |f| %>
 <%= f.text_field :name %>
 <%= f.text_field :email %>
 <%= f.text_field :admin, :value => true %>
 ...

How can we prevent this ?

We need to only allow “safe” attributes from being mass assigned.

You might think it’s easier to specify which attributes should be restricted, but remember foreign keys are also susceptible to mass assignment.

So we are rather going to set the attributes that are allowed, rather than restricted. The rest we will have to assign individually. In this example you would add to your model:

 
    attr_accessible :name, email
 

You should explicitly set which attributes are allowed in every model. If you’re lazy and forgetful like most of us. Try the plugin audit-mass-assignment It allows you to run:

 rake audit:mass_assignment

It will fail on every model that does not include attr_accessible.

{ 0 comments }

Please note this blog has been moved to blog.platform45.com

The attack works by including a link or script in a page that accesses a site to which the user is known to have authenticated. Then a task is performed as the logged in user. 

Huh?

I could create an image tag

 <img src="http://target_site/account/transfer?1milliondollars&from.you.to.me>

or I could put it in a hidden iframe (*holds pinkie up to corner of mouth)

Because you have a valid cookie for the target site this will work. By using post requests for something like this makes it harder to do but still possible. You should be using post when changing the state of a resource anyway. 

What can I do?

From rails 2.0 we have a protect_from_forgery and a secret key. Rails helpers puts this key in every form request. This verifies that the request is coming from somebody using the page. It will protect all POST, PUT, DELETE requests.

If you’re using good ‘ol jQuery you’ll have to set this up yourself.

application_helper.rb

  def yield_authenticity_token
    if protect_against_forgery?
        "<script type='text/javascript'>
        //<![CDATA[
          window._auth_token_name = '#{request_forgery_protection_token}';
          window._auth_token = '#{form_authenticity_token}';
        //]]>
      </script>"
    end
  end

View

 <%= yield_authenticity_token %>

application.js

$(document).ready(function() {
 
	// All non-GET requests will add the authenticity token
  // if not already present in the data packet
  $("body").bind("ajaxSend", function(elm, xhr, s) {
    if (s.type == "GET") return;
    if (s.data && s.data.match(new RegExp("\\b" + window._auth_token_name + "="))) return;
    if (s.data) {
      s.data = s.data + "&";
    } else {
      s.data = "";
      // if there was no data, jQuery didn't set the content-type
      xhr.setRequestHeader("Content-Type", s.contentType);
    }
    s.data = s.data + encodeURIComponent(window._auth_token_name)
                    + "=" + encodeURIComponent(window._auth_token);
  });

Thank you Lawrence Pit for this code.

{ 0 comments }

Ruby on Rails : Danger! Cross Site Scripting

by neil on September 10, 2008

Please note this blog has been moved to blog.platform45.com

Lets take a simple example:

You allow a user to enter his company name.
You then display his company name at the top of his profile page.

We fetch the company name from the database and display it:

 <%= user.company.name %>

When another user visits the attacker’s profile page. A javascript alert dialogue will be displayed.

The attacker may have read my post on popup dialogues and decided to annoy you with one. But be warned, far more malicious code could be injected.

Solution? Use ruby’s escape_html method.

This will replace all characters that could be used for malicious input. We could simply rewrite the code above as:

 <%= h user.company.name %>
# h is an alias for html_escape

You need to escape all strings that could contain malicious content.
It is easy to forget just one string making your entire application vulnerable.

Being forgetful. I use the Safe ERB plugin.

Once installed it will raise an exception on each output string not escaped using the h( ) method.

If you wish to allow a string with formatting you can use the untaint method

 <%= (user.company.name).untaint %>