Thursday, July 19, 2012

ActiveRecord Injection

As I already explain about sql injection in my previous post. Here is more about sql injection through active record. Many of the time we pass params[:id] or some other params variable in activerecord method to generate sql query. It is also unsafe way for query generation.

For example
User.where(:id => params[:id])

In this case attacker can make request like
params[:id] = [1,2,3,4,5,……]

and he will get multiple records from multiple users as query will execute with 'IN' instead of '=' generated query will be.
SELECT `users`.* FROM `users` WHERE `users`.`id` IN (1, 2, 3, 4, 5)

and if attacker uses

params[:id] = (1..1000)

then generated query will be execute with between operator. generated query
SELECT `users`.* FROM `users` WHERE (`users`.`id` BETWEEN 1 AND 1000)

Lets take another example
params[:name] = "hitesh"
User.where(:username => params[:name])

Just think what happen if someone try like

params[:name] = ('a'..'z')

query will be like SELECT COUNT(*) FROM `users` WHERE (`users`.`username` BETWEEN 'a' AND 'z')

How to prevent?

Before passing params in active record method, don't forget to typecast them with expected value. It will prevent your code from the sql injection.

User.where(:id => params[:id].to_i)
Now if params[:id] = (1..1000)
  then It will raise exception: undefined method `to_i' for 1..1000:Range

User.where(:username => params[:name].to_s)
Now query will be like
SELECT `users`.* FROM `users` WHERE `users`.`username` = 'a..z'

So if the attacker tries to mess with params then no worries he will not succeed.

This active record SQL injection vulnerability is available in all the rails version and they have fixed this issue in v3.2.6. so don't worry!! Just upgrade your rails version.

But if you don't want to upgrade then you need to apply work around immediately.