HOME情報セキュリティ資料・報告書・出版物調査・研究報告書情報セキュリティ技術動向調査(2010 年下期)

本文を印刷する

情報セキュリティ

情報セキュリティ技術動向調査(2010 年下期)

1 Ruby on Rails とセキュアプログラミング

長谷川 武

1. Ruby on Rails

  著名なWebアプリケーションフレームワークのひとつにRuby on Rails がある。Ruby on Rails は、プログラミング言語 Ruby を対象として作られたWebアプリケーションフレームワークである。2004年7月に初めて登場し、2010年8月29日にはバージョン3が正式リリースされた。[1]
  Ruby on Rails は、多くの機能を備えた部類のフレームワークである。主に次の機能を備えている。

 
  • Web アプリケーションの基本構造
  • セッション維持の仕組み
  • HTTPリクエストと処理モジュールのマッピング
  • テンプレートエンジンによる Webページの生成
  • 入力検査の仕組み
  • ユーザ認証とアクセス認可の仕組み ※
  • データベースアクセス(O/R マッピング[注]等)
  • REST サポート(URLのマッピング)
  • Ajax サポート
  • キャッシュ 等

※ サードパーティから入手できる認証・認可用のプラグインモジュールを追加して実現する。Ruby on Rails はそのための枠組みをもっている。

  Ruby on Rails は、Ruby言語がもつ拡張性の高さを利用して作られている。Rubyでは、実行時にクラスの機能を拡張することができる。そのことを利用して、新しい「指令」をいくつも定義し、ひとつのクラスをドメイン固有言語(DSL)の処理系として使うことができる。プログラミングの場面では、そのようにして定義された Ruby on Rails 特有の「指令」を多数用いることになる。

2. Ruby on Rails 上のセキュアプログラミング

  Ruby on Railsはバージョン2から、SQL注入等の著名な脆弱性への対応が考慮され始めたと言われている。それは、現在の最新版(バージョン3)においても引き継がれ、拡充されている。
  Ruby on Rails のセキュアプログラミング機能、およびセキュリティの考慮事項には、主に次のものがある。[2][3]

 
  • 著名な脆弱性対策
    • a) SQL注入対策
      b) スクリプト注入(XSS)対策
      c) リクエスト強要(CSRF)対策
  • 入力値対策
    • d) 入力値検査
      e) Taintを利用した入力値追跡
  • 計画的なセキュリティ機能性
    • f) ユーザ認証
      g) アクセス認可

  これらのうち、(1)~(4) が、Ruby on Rails そのものが備えているものであり、(5)~(7) は、サードパーティによるプラグイン等が提供している機能である。

2.1 SQL注入対策

  Ruby on Rails では(バージョン2以降)変数バインディング機能を用いることで、不用意な文字列連結によるSQL注入脆弱性の発生を回避できるようになっている。

  例
	  (1) r1 = Persons.all(:conditions => ["name = ?", params[:x]])
	  (2) r2 = Persons.where("name = ?", params[:x])
    

  上記のうち、(1) がバージョン2、(2) がバージョン3のスタイルである。
  これらの変数バインディングの実装であるが、Ruby on Rails の中のデータベース・アダプタ・クラスにおいて、それぞれのデータベース・ソフトウェアに応じた特殊文字のエスケープ処理を設けることによって実現されている。データベース・ソフトウェアの prepared statement 機能は利用されていない。
  ところで、文字列連結によるSQL文の組み立てはAPI の上では禁止されていないので注意が必要である。例えば、次のような書き方は避けるべきである。

  避けるべき例
	  (1) r1 = Persons.all(:conditions => ["name = '#{params[:x]}'"])
	  (2) r2 = Persons.where("name = '#{params[:x]}'")
    

  以前から Ruby on Rails には、ActiveRecord と呼ばれるO/Rマッパーがバンドルされてきたが、Ruby on Rails 3 では、この ActiveRecord にも改造が施された。データベース・クエリに ARel と呼ばれるドメイン固有言語(DSL)が導入されたので ある。
  ARel のプログラミングは、従来のようにSQL文全体を一度に記述するのではなく、select, from, where, group といった、SQLの構成要素に対応したメソッドを呼び出して、Relation クラスのインスタンスの上にクエリの条件を追加してゆくスタイルをとる。
  ARel の導入で、例えば、次のようなメソッドが追加されている。

    (1) Rails 2 までに存在していたメソッド

      find, first, last, all, exists?, count_by_sql, find_by_sql,
      create, update, update_all, delete_all, destroy_all 等

    (2) Rails 3 から追加されたメソッド

      select, from, where, group, having, includes, joins,
      limit, order, reorder,
      create_with, eager_load, preload
      average, calculate, count, maximum, minimum, sum 等

  ARel の導入にともなって増やされたメソッドにおいても、変数バインディングの機能が設けられているので、常にそれを用いることを推奨する。
  クエリを断片ごとに記述する ARel のメソッド呼び出しは、見た目は異なっていても、相変わらずSQL文を操作しているのだという意識をもち、SQL注入脆弱性に用心する必要がある。

2.2 スクリプト注入対策

  Ruby on Rails 2 では、出力ページのERBテンプレート(rhtmlファイル)に例えば次のような記述をすることによって、& " < > の記号にエスケープ処理を施した上で値を出力させることができる。

  Rails 2 の例
     <%= h @name %>
    

  この h メソッドは、ERB::Util クラスの html_escape メソッドの別名である。
  Ruby on Rails 3 では、ERBテンプレートにおける h メソッドの適用がデフォルトになった。

  Rails 3 の例
     <%= @name %>
    

  何も書かなければ、h メソッドによるエスケープ処理が適用される。これに伴い、逆に、このエスケープ処理を敢えて行わせないための raw メソッドが導入された。

  Rails 3 の例(推奨はしない)
     <%= raw @name %>
    

  このhメソッドによるエスケープ処理は多くの箇所で効果を発揮するものの、タグの属性値を出力する際値を必ず引用符で囲む("...")配慮が必要である。また、次の箇所では対策効果が無いかまたは弱く、出力値にさらなる制約を設ける必要がある。:

 
  • タグの属性値のうち次の箇所
  • -  <img src="...">等のURIを指定可能な属性
    -  style="..." 属性
    -  onMouseOver="..." 等のイベントハンドラ属性
  • <script>...</script>の内側

2.3 リクエスト強要(CSRF)対策

  Ruby on Rails ではリクエスト強要(CSRF)対策の、フォームへのトークンの埋め込みとフォームデータを受信した際のトークンの照合が自動で行われる。


2.3.1 トークンの自動埋め込み

  form_for 等のメソッドで生成するフォームには、自動でリクエスト強要(CSRF)対策のトークンが自動で埋め込まれる。Rails 2 ではトークンの固定値をプログラマが指定する形態が存在したが、Rails 3 では、処理系がランダムな値を生成するよう変わっている。
  例えば、form_for メソッドでフォームを記述すると:

    <%= form_for @foo do |f| %>
    ...
    

  次のように、フォーム内にauthenticity_tokenという名前のトークンが埋め込まれる。:

    <form action="/foos"  class="new_foo" id="new_foo" method="post">
    <input name="authenticity_token"  type="hidden" value="JWI+bZ1tsj8dhTmBC8ZOV+PYGlfhKQwP2u0b9ehCCcg=" />
    ...
    

2.3.2 トークンの自動照合

  コントローラクラスのビジネスロジックが呼び出される前に、リクエスト強要(CSRF)対策のトークンの照合が自動で行われる。ただし、照合が行われるのは次のようなHTTPリクエストの場合である。

  (1) POSTで送信されるフォームデータに限られる。
 
  (2) protect_from_forgery 指令によって指定されたコントローラクラスとメソッドの範囲。デフォルトの保護対象は、すべてのコントローラクラスの全メソッド(ただしPOSTで呼ばれるもの)である。

  照合が行われ、トークンの値が適切でないと、

    ActionController::InvalidAuthenticityToken

という例外が発生し、当該HTTPリクエストの処理は中断される。
  この、リクエスト強要(CSRF)対策のトークン自動照合は、Ruby on Rails が備えているbefore_filter という機能を用いて実現されている。この before_filter を用いると、ビジネスロジックと、そのビジネスロジックの呼出をWebクライアントに許すか否かのセキュリティロジックとを分離して配置することが可能である。
  所定のセキュリティロジックを配置しておけば、プログラマはビジネスロジックの記述に集中することができ、また、ソースコードをシンプルに保つことができる。

2.4 入力検査

  Ruby on Rails アプリケーションの「モデル」クラス群には、項目ごとの入力値チェックを指定できるvalidates 指令および validates_xxx 指令群が用意されている
  Ruby on Rails 2 では、例えば、次のような validates_xxx 指令群を用いて入力値検査を指定することができる。

  • validates_presence_of :name
    (項目 name の値が空でないこと)

  • validates_length_of :password, :minimum => 8, :maximum => 20
    (項目 password の値が8桁以上20桁以下であること)

  • validates_format_of :email, :with => /\A[-_.\w]+@[-\w]+\.[-.\w]+\z/
    (項目 email の値が当該正規表現にマッチすること)

  • validates_inclusion_of :gender, :in => %w( m f )
    (項目 gender の値が m または f のみであること)

  • validates_uniqueness_of :customer_code, :case_sensitive => false
    (項目 customer_code がDBテーブル中で重複しないこと。大文字小文字は区別せず比較する) 等

  Ruby on Rails 3 からは、validates 指令が加わった。ひとつの入力項目の複数の検査仕様を、ひとつの validates 指令を使って記述できるようになった。

  • validates

  この validates 指令および validates_xxx 指令群は、アプリケーションの「モデル」部分、すなわちActiveRecord 継承クラスに記述する。検査は値がデータベースへの格納の前に行われる。
  データベースに格納されるデータの仕様への合致は確保できるが、「モデル」のどれかのクラスのフィールドを、データベースに格納する前に参照し、何らかの形で利用する場合、独自の入力検査ロジックを書く必要がある。

2.5 Taint機能

  Ruby 言語には Taint 機能が備わっている。Taint 機能とは、オブジェクトにマークをつけ、信頼できない入力値の伝播を追跡できる仕組みである。
  Ruby on Rails 自体は Taint 機能を利用していないが、Taint 機能を用いたプラグインをつくることが可能である。
  Ruby on Rails 2 用には、Taint 機能を利用したスクリプト注入(XSS)対策プラグインとして SafeERB というものが存在している。

2.6 ユーザ認証

  Ruby on Rails 本体には、ユーザ認証の仕組みは用意されていない。しかし、ユーザ認証のための複数のプラグインがサードパーティから提供されている。

  サードパーティによるユーザ認証プラグインの例 [4]

 
  • Devise
  • Authlogic
  • Restful authentication
  • Clearance
  • Rails OpenID 等

2.7 アクセス認可

  Ruby on Rails 本体には、アクセス認可の仕組みは用意されていない。しかし、アクセス認可のための複数のプラグインがサードパーティから提供されている。


2.7.1 所有者やロールによる認可

  情報の所有者やロールにもとづくアクセス認可のプラグインには、例えば、CanCan、declarative_authorization、grant 等がある。[5]

    コード CanCanの権限記述例
      
      # models/ability.rb
      class Ability
        include CanCan::Ability
      
        def initialize(user)
          user ||= User.new # guest user
      
          if user.role? :admin
            can :manage, :all
          else
            can :read, :all
            can :create, Comment
            can :update, Comment do |comment|
              comment.try(:user) == user || user.role?(:moderator)
            end
            if user.role?(:author)
              can :create, Article
              can :update, Article do |article|
                article.try(:user) == user
              end
            end
          end
        end
      end
      
      
        出典 http://railscasts.com/episodes/192-authorization-with-cancan

2.7.2 ログインによる保護

  未ログイン者からコンテンツを保護するしくみは、ユーザ認証プラグインがサポートしていることが多い。


2.7.3 before_filter によってコンテンツを保護する

  Ruby on Rails アプリケーションの「コントローラ」クラス群(HTTPリクエストに応じた処理を行う)では、before_filter という指令が使える。これは、「コントローラ」クラス群のビジネスロジックが呼び出される前に、何らかのフィルタ処理メソッドの呼び出すよう定義するものである。これを用いると、ビジネスロジックとアクセス認可のためのコードをきれいに分離して配置できる。ユーザ認証やアクセス認可のプラグインの多くは、これを利用している。

以上

参考文献・参照プロジェクト

[1] "Ruby on Rails 3.0 Release Notes"
http://edgeguides.rubyonrails.org/3_0_release_notes.html
[2] Heiko Webers "Ruby on Rails Security Updated"
http://www.slideshare.net/heikowebers/ruby-on-rails-security-updated-rails-3-at-railswaycon
[3] Heiko Webers "Ruby On Rails Security Guide"
http://guides.rubyonrails.org/security.html
[4] 認証プラグインのプロジェクト(主なもの)
 Device - https://github.com/plataformatec/devise
 authlogic - https://github.com/binarylogic/authlogic
 restful-authentication - https://github.com/technoweenie/restful-authentication
 clearance - https://github.com/thoughtbot/clearance
 ruby-openid - https://github.com/openid/ruby-openid
[5] 認可プラグイン・プロジェクト
 CanCan - https://github.com/ryanb/cancan
 declarative_authorization - https://github.com/stffn/declarative_authorization
 grant - https://github.com/nearinfinity/grant

参考資料

木村,「Ruby On Rails Security Guideの訳 : 概要 + 1.Introduction」
http://www.flatz.jp/archives/1942
松田明 ,「Rails 3を支える名脇役たち その1 - Arel -」
http://gihyo.jp/dev/serial/01/ruby/0043
「Rubyリファレンスマニュアル - ERBクラス」
http://www.ruby-lang.org/ja/man/html/erb.html

 

目次へ 次へ