3 ms·
Assuming you have no ruby knowledge: ActiveRecord (rails' default ORM) has a feature called "dynamic finders". When you call a method like `Forum.find_by_url('
by xentronium 14y ago
Assuming you have no ruby knowledge:
ActiveRecord (rails' default ORM) has a feature called "dynamic finders". When you call a method like `Forum.find_by_url('news.ycombinator.org')` it gets a first forum with such url. This is a sugar over `Forum.where(:url => 'news.ycombinator.org').first`.
Normally, you use it like that `Forum.find_by_url(params[:url])` where `params` is a hash of parameters (that is auto-generated from http get/post params). What happens if instead of "normal" value like "news.ycombinator.org" you pass a hash?
1.9.3p327 :018 > Forum.find_by_id({:select => 'id FROM forums --'})
Forum Load (0.5ms) SELECT id FROM forums -- FROM `forums` WHERE `forums`.`id` IS NULL LIMIT 1
Uh-oh.
However, not everything is lost. Rails params are converted to a special hash class. It's called HashWithIndifferentAccess, because you can access its values by string keys and symbol keys likewise. So that
h = {:a => 1, "b" => 2}.with_indifferent_access
h["a"] # => 1
h[:a] # => 1
h["b"] # => 2
h[:b] # => 2
What happens if we pass user-generated params? It seems like not much:
1.9.3p327 :024 > Forum.find_by_id({:select => 'id FROM forums --'}.with_indifferent_access)
ArgumentError: Unknown key: select
So I guess they are erring on a safe side here.
- MichaelGG 14y agoWhat's the great benefit of these methods? Why not just do find_by("url", x)? I just don't understand the desire to move string parameters into member names.
- xentronium 14y agoThere is slight benefit in readability for cases like find_by_name_and_role("Jack", "admin"), but other than that, no benefit whatsoever. In Rails 4.0, most dynamic finders are deprecated and removed from the source into a separate gem.
- awj 14y agoThat method predates the "Forum.where(:url => ...)" syntax of xentronium's demo code. Previously it looked like this: "Forum.find(:first, :conditions => {:url => ...})". Dynamic finders were really sugar over this form, which was always kind of an eyesore.
- TallboyOne 14y agoStupid question, but how was that not discovered until now? That seems quite major, or something that the developers would have tested for ..
- FooBarWidget 14y agoThe vulnerability doesn't get triggered normally. As the grandparent said, request parameters are stored in an object of class HashWithIndifferentAccess, which stores all keys as strings. For the vulnerability to be triggered, the keys must be symbols. You cannot trigger this vulnerability unless your have written code in your app which converts the HashWithIndifferentAccess to a normal hash. This patch does not fix a wide vulnerability. It just fixes a corner case, a just-in-case-somebody-might-write-vulnerable-code fix. It just so appears that Authlogic does this. They pass a cookie value into a dynamic finder, so you can tamper the cookie to inject SQL.
- TallboyOne 14y agoThanks for the great explanation, Sir widget.
- FooBarWidget 14y agoMore information here: http://blog.phusion.nl/2013/01/03/rails-sql-injection-vulnerability-hold-your-horses-here-are-the-facts/ http://blog.phusion.nl/2013/01/03/rails-sql-injection-vulner...