Ruby 1.9.2 リファレンスマニュアル > spec/safelevel

セキュリティモデル

RubyにはCGI等のプログラミングを安全に行うことを助ける為に、セキュリティ 機構が備わっています。

Rubyのセキュリティモデルは「オブジェクトの汚染」と「セーフレベル」という 仕組みによってなりたっています。

オブジェクトの汚染

Rubyではオブジェクトは「汚染されている」とみなされることがあります。この しくみは大きく分けて二つの使われ方をします。

ひとつ目は、信用できない入力をもとに作られたオブジェクトを「汚染されてい る」とみなし、「危険な操作」の引数として使えないようにすることです。悪意 あるデータによって、プログラムが意図しない動作をする事を防ぐことを目的と しています。

もうひとつは、信用しているオブジェクト(汚染されていないオブジェクト)を 信用できないプログラムから守るという使い方です。セーフレベル4で汚染されて いないオブジェクトへの操作が大幅に制限されるのはこの事を意図しています。

オブジェクトの汚染に関連するメソッド

Object#taint

オブジェクトを汚染する

Object#tainted?

オブジェクトが汚染されている場合に真を返す

Object#untaint

オブジェクトの汚染を取り除く

セーフレベル

各スレッドは固有の「セーフレベル」を持っています。セーフレベルが高くなるほ ど、行える操作は制限されます。セーフレベルはスレッドローカル変数 $SAFE で 設定します。

[ruby-list:37415]

$SAFE に関するルール

      $SAFE = 1
      th = Thread.new{
        p $SAFE #=> 1
        $SAFE = 3
      }
      th.join
      p $SAFE #=> 1
      $ ruby -e '$SAFE = 1; $SAFE = 0'
      -e:1: tried to downgrade safe level from 1 to 0 (SecurityError)

原則として、各セキュリティレベルにはそれ以下のセキュリティレベルの制限も 適用されます。たとえばレベル1で許されない操作はレベル2でも行えません。

レベル 0

デフォルトのセーフレベルです。

汚染されるオブジェクト

  $ ruby -e 'p ARGV[0].tainted?' hoge
  true

(環境変数PATHだけは特別)

環境変数PATHだけは例外で、値に危険なパスを含む場合のみ汚染されます。

ここでは危険なパスとは誰でも変更/書き込みが可能なパスをいいます。 ルートディレクトリから階層が順番にチェックされ、一箇所でも誰でも 変更可能な個所があればそのパスは危険とみなされます。

禁止される操作

レベル 1

信用しているプログラムで信用できないデータを処理する為のレベルです。 CGI等でユーザからの入力を処理するのに適しています。

汚染されるオブジェクト

禁止される操作

          $ ruby -e '$SAFE = 1; open(ARGV[0])' hoge
          -e:1:in `initialize': Insecure operation - initialize (SecurityError)
                  from -e:1

レベル 2

汚染されるオブジェクト

禁止される操作

レベル1の制限に加え、以下の操作が禁止されます。

レベル 3

生成される全てのオブジェクトが汚染されます。レベル4でプログラムを実行す る環境を作り上げるのに適しています。

汚染されるオブジェクト

禁止される操作

レベル2の制限に加え、以下の操作が禁止されます。

レベル 4

信用することのできないプログラムを実行するためのレベルです。

レベル4は信頼できないプログラムによる危険な操作をほぼ全て検出できますが、 完全な安全性は保証されません。

このレベルではレベル3では禁止されている「汚染された文字列のeval」が許可 されています。(evalで実行すると危険な操作は全て禁止されているからです。)

汚染されるオブジェクト

禁止される操作

レベル3の制限(上記のとおりevalは除く)に加え、以下の操作が禁止されます。

セーフレベルに関するその他の詳細

      * 環境変数 RUBYLIB を $: に加えない
      * カレントディレクトリを $: に加えない
      * 環境変数 RUBYOPT を処理しない
      * 以下のスイッチを使用できない
        -s -S -e -r -i -I -x
        (スクリプトがsetgid, setuidされている時も同様)
      * 標準入力からのプログラム読み込みを行わない
        (スクリプトがsetgid, setuidされている時も同様)
  汚染された文字列を第二引数に指定して trap/trace_var を
  実行するとその時点で例外 [[c:SecurityError]] が発生する。

* レベル4以上では out of memory でも [[c:fatal]] にならない。

* 実装の都合上、Fixnum・Symbol・true・false・nil は汚染されない。
  なお Bignum・Float は汚染されることは注意が必要。

使用例

一旦高くした$SAFEレベルを低く変更する事はできませんが、以下のようにスレッ ドを使うことで、プログラムの一部だけを高いセーフレベルで実行することが可 能です。

例:

def safe(level)
  result = nil
  Thread.start {
    $SAFE = level
    result = yield
  }.join
  result
end

safe(4) { puts "hello" }    # $SAFEなので例外
puts "world"                # 外側は影響を受けない

拡張ライブラリでの扱い

[ruby-list:37407]

Libraries

Classes