Railsセキュリティアップデートへの対処法

2013/01/30

今月(2013年1月)、Ruby on Railsに2つの脆弱性が相次いで発見され、アップデートがリリースされました。

1番目の脆弱性の対象となるRailsのバージョンは、2.3.0から2.3.14、3.0.0から3.0.18、3.1.0から3.1.9、3.2.0から3.2.10。

2番目の脆弱性の対象は、2.3.0から2.3.15、3.0.0から3.0.19。

いずれも「極めて深刻な(extrenely critical)」という形容付きでアナウンスされています。直ちにアップデートを適用すべきです。

しかし、他の誰か(開発会社とか知人とか)にRuby on Railsで作ってもらったWebサイトを運用していて、自分自身はエンジニアではなく、その誰かとも連絡が取れない(取りにくい)という場合は、どうすればいいでしょうか。

原則としてはやはりRailsに詳しい人に相談すべきなのですが、予算の関係でそうも行かないこともあるでしょう。以下、対処法を説明します。

注意 実運用中のWebサイトに対してこの記事で書かれたことを実施すると、場合によってはWebサイトが正常に機能しなくなる可能性があります。自己責任でお願いします。

最初に確認すること

まずは、以下の点を確認しましょう。

  1. サーバーマシンにログインできるか。
  2. Webサイトのドキュメントルートはどこか。

これらの情報は、その誰かから受け取っているはずです。受け取っていないとすれば、少し話が複雑になります。専門家に相談すべきです。

Railsのバージョンを調べる

次に、Railsのバージョンを調べます。仮にドキュメントルートが /var/rails/example/current/public だとすれば、その親ディレクトリ(これを「Railsルートディレクトリ」と呼びます)に移動します。

$ cd /var/rails/example/current/

Gemfile の有無を調べます。

$ ls Gemfile

あれば Gemfile と、なければ No such file or directory といったエラーメッセージ(環境によって異なります)が表示されます。

Gemfile が存在する場合

Gemfile の中身を表示します。

$ less Gemfile

次のような記述があるはずです。

gem 'rails', '3.2.4'

この 3.2.4 がRailsのバージョン番号です。

Gemfile が存在しない場合

config ディレクトリに environment.rb というファイルの中身を表示します。

$ less config/environment.rb

次のような記述があるはずです。

RAILS_GEM_VERSION = '2.3.9' unless defined? RAILS_GEM_VERSION

この 2.3.9 がRailsのバージョン番号です。

Railsのバージョンが2.3.0未満の場合

今回発表された脆弱性では、2.3.0未満のバージョンは対象に入っていません。これは「2.3.0未満なら大丈夫」という意味ではなく、「2.3.0未満はサポート外」という意味です。

この場合、Railsのバージョンアップと同時に、おそらくはアプリケーション自体を修正しないと、正常に動作しません。これは素人には難しいので、専門家に相談した方がいいでしょう。

Capfile が存在する場合

次に、Railsルートディレクトリに、Capfile というファイルが存在するかどうかを調べます。

$ ls Capfile

存在する場合は、Capistranoというプログラムを使ってソースコードの配置が自動化されています。また、Git、Mercurial、Subversionなどのソースコード構成管理(SCM)ツールが使われています。

もしかすると、Capistranoを使おうと考えてセットアップを始めたけど途中でやめて、設定ファイルの残骸が残っているだけかもしれません。本当にCapistranoを使っているかどうかの判定は、なかなか難しいです。

CapistranoやSCMツールの設定は config ディレクトリの下にある deploy.rb というファイルに書かれています。例えば、その中に、

  set :repository, "git@github.com:oiax/example.git"

と書かれていれば、git@github.com:oiax/example.git がSCMツールで使用するリポジトリ(ソースコードの履歴を管理するデータベース)のURLです。

ここからの手順は次の通り:

  1. 作業マシンにCapistranoとSCMツールをインストール。
  2. リポジトリのURLから作業マシンにソースコードを取得。
  3. 後述するアップデート手順に従いソースコードを修正。
  4. リポジトリにソースコードを登録。
  5. Capistranoでソースコードを配置する。

非エンジニアがCapistranoやSCMツールの使い方をマスターするのは、ちょっとハードルが高いです(今回は説明しません)。ここまでの情報を持って、専門家に相談した方がいいかもしれません。

Railsのアップデート

Gemfile の有無により手順が異なります。

Gemfile が存在する場合

Gemfile に記載されているバージョン番号を変更します。その際、3番目のバージョン番号だけを変更する点に注意してください。例えば、3.0.1 なら 3.0.20 に変更します。3.1.193.2.11 に変更すると、アプリケーションが正常に動作しないかもしれません。

Railsのバージョンが2.3.xの場合は、config/environment.rb に記載されているバージョン番号も同様に変更します。

そして、次のコマンドを実行します。

$ bundle update rails

無事アップデートが完了すると、次のようなメッセージが表示されます。

Your bundle is updated! Use `bundle show [gemname]` to see where a bundled gem is installed.

しかし、次のようなエラーメッセージが出るかもしれません。

You are trying to install in deployment mode after changing
your Gemfile. Run `bundle install` elsewhere and add the
updated Gemfile.lock to version control.

If this is a development machine, remove the Gemfile freeze 
by running `bundle install --no-deployment`.

You have added to the Gemfile:
* rails (= 3.0.20)

You have deleted from the Gemfile:
* rails (= 3.0.1)

この場合は、.bundle ディレクトリにある config ファイルをVimなどのエディタで開きます。その中に、次のような書かれた箇所がありますので、その行を削除してください。

BUNDLE_FROZEN: "1"

そして、もう一度 bundle update rails コマンドを実行してください。

Gemfile が存在しない場合

config/environment.rb に記載されているバージョン番号を変更します。その際、3番目のバージョン番号だけを変更する点に注意してください。例えば、3.0.1 なら 3.0.20 に変更します。3.1.193.2.11 に変更すると、アプリケーションが正常に動作しないかもしれません。

続いて、バージョン番号を指定してRailsをインストールします。必ず config/environment.rb に記入したバージョン番号と一致させてください。

$ gem install rails --version=3.0.20

途中で次のようなメッセージが現れたら、パスワードを入力してください。

Enter your password to install the bundled RubyGems to your system:

ここで正しいパスワードを入力してもエラーになってしまう場合は、サーバーマシンにログインしたユーザーに sudo 権限がありません。su コマンドで root ユーザーになって、もう一度同じコマンドを実行してください。

Railsアプリケーションの再起動

Railsのアップデートを適用するには、アプリケーションの再起動が必要です。再起動方法は、環境により異なります。再起動直後しばらくはWebサイトのレスポンスが「重く」なります。

script/spin がある場合

script ディレクトリに spin というファイルが存在する場合は、おそらく Mongrel を使っています。次のコマンドで再起動できるはずです。

$ nohup script/spin &

tmp/pid/unicorn.pid がある場合

tmp/pid ディレクトリに unicorn.pid というファイルが存在する場合は、Unicorn を使っています。次のコマンドで再起動できるはずです。

$ kill -QUIT tmp/pids/unicorn.pid

その他の場合

おそらくは Passengerを使っています。次のコマンドを実行してみてください。

$ touch tmp/restart.txt

最後にもう一度

注意 実運用中のWebサイトに対してこの記事で書かれたことを実施すると、場合によってはWebサイトが正常に機能しなくなる可能性があります。自己責任でお願いします。