Avoiding SQL Injection in :order?

This thread references:
http://www.ruby-forum.com/topic/90258#new
http://www.ruby-forum.com/topic/82349#143790

ActiveRecord’s find() method has built in ways to avoid SQL injection by
using the format

:conditions => [ “user_name = ?”, user_name]

Is there any such system for escaping injection in :order? It seems to
only take a string and feed it to the SQL statement. This causes a
vulnerability when using params to set :order as in this function:

def list
sort_by = params[:sort_by]
@book_pages, @books = paginate :books,
:order => sort_by,
:per_page => 10
end

We’ve tried a few methods to sanitize sort_by such as :order => [‘?’,
sort_by] but it just passes that to the SQL statement like a flattened
array. The ‘escaping magic’ does not work for :order. Should I use
gsub! to sanitize params[:sort_by]?

Taylor S. wrote:

Is there any such system for escaping injection in :order?

Maybe check it first to make sure it’s actually one of the columns in
the model?

sort_by = params[:sort_by] if
Book.column_names.include?(params[:sort_by])

How about calling ActiveRecord#sanitize_sql directly?

Danny B. wrote:

How about calling ActiveRecord#sanitize_sql directly?


Posted via http://www.ruby-forum.com/.

My solution to this is to have the params[:sort] point to a key for a
hash of predefined sort options.

sort_options = { ‘name_up’ => ‘name ASC, created_at DESC’,
‘name_down’=>‘name DESC, created_at DESC’}

then use

Object.find(:all, :order=>sort_options[params[:sort]])

If the :sort parameter is messed up, it will return the Hash.default.

_Kevin

Chris: your way works well and is pretty low maintenance. Tested and
works by simply discarding any sort_bys without matching columns.
Thanks!

Danny: The API docs on ActiveRecord#sanitize_sql are terrible, even by
Rails standards! I’m not sure how to do it.

Kevin: Your way would definitely work, but it would be a lot of
maintenance as models and attributes change.

I was ultimately hoping for some way to sanitize sort_by so that I could
use it as an application helper for all the times I want to sort. The
search continues! Thanks everyone for your help.

Here is the epilogue - I created this module (comments removed):

def set_sort_method(model)
unless params[:sort_by].nil?
if model.column_names.include?(params[:sort_by])
@sort_by = params[:sort_by]
end
unless session[:sort_by].nil?
if session[:sort_by] == @sort_by
@sort_by += ’ desc’
end
end
session[:sort_by] = @sort_by
end
end

And then all I have to add in the controller is set_sort_method() and
:order => @sort_by:

def list
set_sort_method(Publisher)
@publisher_pages, @publishers = paginate :publishers,
:order => @sort_by,
:per_page => 10
end

This works for every model and is DRY. Thanks again!

On 5 December 2006 01:33, Taylor S. wrote:

Chris: your way works well and is pretty low maintenance. Tested and
works by simply discarding any sort_bys without matching columns.
Thanks!

Danny: The API docs on ActiveRecord#sanitize_sql are terrible, even by
Rails standards! I’m not sure how to do it.

Kevin: Your way would definitely work, but it would be a lot of
maintenance as models and attributes change.
Personally, I would stick with Kevin’s suggestion on “sorting names” and
here
is why:

  1. Chris’ solution doesn’t allow to handle multiple sort params (e.g.
    ‘company
    desc, name asc’)
  2. Kevin’s solution IMHO is more flexible and secure.
  3. Danny, probably, right but it’s not straight forward.
   end
 end
 session[:sort_by] = @sort_by

You might want to do…

session[:sort_by][model]…

here and a couple of lines up to avoid any conflicts arrising from
multiple browser windows open to different pages, etc…

Maxim K. wrote:

Personally, I would stick with Kevin’s suggestion on “sorting names” and
here is why:

  1. Chris’ solution doesn’t allow to handle multiple sort params (e.g.
    ‘company
    desc, name asc’)
  2. Kevin’s solution IMHO is more flexible and secure.

What would be the best way to implement this? Give each model a class
method (called “sort_hash” or something) that returns the hash Kevin
describes?

On 5 December 2006 17:19, Chris G. wrote:

method (called “sort_hash” or something) that returns the hash Kevin
describes?
Personally, I had this “hash” in my controller which should show my
corresponding model data.
You see, it’s not a generic way to order collections (you have :order
param
already). It’s, IMHO, handy way to make sure that no sql injection will
occur.

Chris G. wrote:

method (called “sort_hash” or something) that returns the hash Kevin
describes?


Posted via http://www.ruby-forum.com/.

You could do that. I tend to customize the hash for each particular
view (or I only ever use it in one), so I just define it right in the
view action. In my view, this is part of the ‘view’ part of MVC, so
the model should probably not be aware of it.

_Kevin