Sean Collins

sean [at] seanmcollins [dot] com

GPG Key ID: 0xf60f564978913931

sean [at] coreitpro [dot] com

GPG Key ID: 0xA1D7E590

profile for Sean at Stack Overflow, Q&A for professional and enthusiast programmers

Does Ruby on Rails Have Too Much Magic?

We’ve all seen Mickey in Fantasia: Micky The Sorcerer’s Apprentice

Does the “magic” in Rails that helps developers carry water from the well compromise security?

Suppose we have a signup page, written using Ruby on Rails.

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

Rails has some “magic” (a programming term for features a framework does for you behind the scenes) called mass-assignment, which relieves developers of the drudgery of having to pull data out of the HTTP request sent from the client, assign it to temporary variables, and then pass those variables further into the application.

Mass-assignment saves you work, because you don’t have to set each value individually. Simply pass a hash to the new method, or assign_attributes= a hash value, to set the model’s attributes to the values in the hash.

One has to wonder, how useful this is feature is, in comparison to how dangerous it could be in the wrong hands. Rails’ own security documentation goes to great lengths to warn about the dangers:

If you’re using Rails and you want to be secure, you should be protecting against mass assignment. Basically, without declaring attr_accessible or attr_protected, malicious users can set any column value in your database, including foreign keys and secure data.

What is to stop someone from filling the params[:user] with malicious data in the URL, like http://www.example.com/user/signup?user[name]=ow3ned&user[admin]=1

Which will result in the hash equaling

params[:user] # => {:name => “ow3ned”, :admin => true}

One intrepid, young GitHub user by the name of Egor Homakov decided to raise concerns about how powerful this feature could be, in the hands of junior developers who are attracted to Ruby on Rails, and who may not fully understand that you should Never. Ever. Trust User Input

Let’s view at typical situation - middle level rails developer builds website for customer, w/o any special protections in model(Yeah! they don’t write it! I have asked few my friends - they dont!)

Next, people use this website but if any of them has an idea that developer didnt specify attr_accesible - hacker can just add an http field in params … After execution of that POST the hacker owns the target

The Rails Development Team Refuses to Respond

Shockingly, a member of the Rails development team acknowledges that this is indeed a problem that has been discussed, then dismisses the whole problem with the wave of a hand.

You are not discovering anything unknown, we already know this stuff and we like attr protection to work the way it is.

We Like It The Way It Is

Mr. Homakov clearly felt that this was a serious issue, and since the Rails developers believed that everyone who was using Ruby on Rails was aware of the “magic” and the implications, the only alternative was to demonstrate how serious an issue this was.

A high profile Rails application that was vulnerable would need to be found. Perhaps one that would snap the Rails developers back to their senses.

Why not GitHub?

Indeed. Why not? Especially when the Rails codebase is hosted on Github!

So Mr. Homakov decided to play a bit of a practical joke on the Rails team by actively exploiting the security hole in GitHub’s rails app, and added a commit to the Rails project.

GitHub quickly recognized the problem, which is commendable, but larger questions remain.

If It Happened To GitHub - It Can Happen To Anybody

Again, why was this feature added to Ruby on Rails? Does convenience outweigh security? Why did the Rails developers dismiss this issue, claiming that they already know about it and it’s nothing new?

For now, we’ll have to wait and see.