Rails 3.2.10, 3.1.9, and 3.0.18 have been released!

いつの間にか新しいの出てました。
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の文字列がセットされるので
とりあえずの回避策のようですね。