いつの間にか新しいの出てました。
Riding Rails: Rails 3.2.10, 3.1.9, and 3.0.18 have been released!
いつものように、security fixです。
CVE-2012-5664
SQL Injection Vulnerability in Ruby on Rails (CVE-2012-5664) - Google グループ
Post.find_by_id(params[:id]) のような書き方に
SQL Injectionの可能性があるとのこと。
そこらじゅうありそうですね。
Workarounds
# こう書いてるのを Post.find_by_id(params[:id]) # to_sすることで軽減できるらしい Post.find_by_id(params[:id].to_s)
修正箇所
method_missingの中で hashの値を取り出す(arguments.extract_options)処理に
条件を加えています。
options = if arguments.length > attribute_names.size arguments.extract_options! else {} end
追加されたテスト
よくわかんないので、テストを見てみます。
class FinderTest < ActiveRecord::TestCase def test_find_by_id_with_hash assert_raises(ActiveRecord::StatementInvalid) do Post.find_by_id(:limit => 1) end end def test_find_by_title_and_id_with_hash assert_raises(ActiveRecord::StatementInvalid) do Post.find_by_title_and_id('foo', :limit => 1) end end
どうやら、find_by_… を利用する際にhashが渡された場合に例外(ActiveRecord::StatementInvalid)を
発生するように修正しているようです。
いまいちピンとこないので
手元で試してみます。
#ralils 3.2.9 >>Word.find_by_id(:limit => 1) Word Load (0.2ms) SELECT "words".* FROM "words" WHERE "words"."id" IS NULL LIMIT 1 # rails 3.2.10 >> Word.find_by_id(limit: 1) Word Load (0.3ms) SELECT "words".* FROM "words" WHERE "id"."limit" = 1 LIMIT 1 SQLite3::SQLException: no such column: id.limit: SELECT "words".* FROM "words" WHERE "id"."limit" = 1 LIMIT 1 ActiveRecord::StatementInvalid: SQLite3::SQLException: no such column: id.limit: SELECT "words".* FROM "words" WHERE "id"."limit" = 1 LIMIT 1 from /Users/rochefort/.rbenv/versions/1.9.3-p327/lib/ruby/gems/1.9.1/gems/sqlite3-1.3.6/lib/sqlite3/database.rb:91:in `initialize' (略)
なるほど、329だと IS NULL で検索されてしまうので、null可の項目だとまずいですね。
3210だと不正なSQLとして処理しているようです。
workaroundsのto_sだと、数値の場合は0がセットされそれ以外はhashの文字列がセットされるので
とりあえずの回避策のようですね。