[#37249] ruby 1.8でのCGI#[]の挙動 — 堀川 久 <vzw00011@...>

こんにちは。

14 messages 2003/03/09

[#37283] 両方の式とも常に評価する論理和・論理積 — Shinya Kawaji <kawaji@...>

かわじ、です

17 messages 2003/03/13

[#37324] optparse は使いやすいですか? — 成島 寛則 <narushima@...>

こんにちは。Narushima Hironori と申します。

13 messages 2003/03/15

[#37370] Secure「ではない」script の書き方 — satoru takahashi <hisai@...>

高橋聡@JFプロジェクトで翻訳しています、です

50 messages 2003/03/20
[#37381] Re: Secure「ではない」script の書き方 — satoru takahashi <hisai@...> 2003/03/20

高橋聡です

[#37382] Re: Secure「ではない」script の書き方 — matz@... (Yukihiro Matsumoto) 2003/03/20

まつもと ゆきひろです

[#37405] Re: Secure「ではない」script の書き方 — Taku Nakajima <tnakajima@...> 2003/03/24

[#37407] Re: Secure「ではない」script の書き方 — matz@... (Yukihiro Matsumoto) 2003/03/24

まつもと ゆきひろです

[#37414] Re: Secure「ではない」script の書き方 — Taku Nakajima <tnakajima@...> 2003/03/25

[#37415] Re: Secure「ではない」script の書き方 — matz@... (Yukihiro Matsumoto) 2003/03/25

まつもと ゆきひろです

[#37417] Re: Secure「ではない」script の書き方 — Taku Nakajima <tnakajima@...> 2003/03/25

[#37421] Tmpfile.newがデフォルトで/tmpを利用すること — Tadatoshi Kamimura <kamimura.tadatoshi@...>

上村と申します。はじめまして。

35 messages 2003/03/26
[#37422] Re: Tmpfile.newがデフォルトで/tmpを利用すること — WATANABE Hirofumi <eban@...> 2003/03/26

わたなべです。

[#37467] Re: Tmpfile.newがデフォルトで/tmpを利用すること — Tadatoshi Kamimura <kamimura.tadatoshi@...> 2003/03/31

上村です

[#37468] Re: Tmpfile.newがデフォルトで/tmpを利用すること — "Akinori MUSHA" <knu@...> 2003/03/31

At Mon, 31 Mar 2003 09:51:27 +0900,

[#37470] Re: Tmpfile.newがデフォルトで/tmpを利用すること — Tadatoshi Kamimura <kamimura.tadatoshi@...> 2003/03/31

上村です。

[#37472] Re: Tmpfile.newがデフォルトで/tmpを利用すること — "Akinori MUSHA" <knu@...> 2003/03/31

 なるほど、 $SAFE=1 のところをすっぱり読み飛ばしてました。

[#37479] Re: Tmpfile.new がデフォルトで/tmpを利用すること — siena@... (Siena. / SHINAGAWA, Norihide) 2003/03/31

Siena. です。

[#37480] Re: Tmpfile.new がデフォルトで/tmpを利用すること — siena@... (Siena. / SHINAGAWA, Norihide) 2003/03/31

Siena. です。

[#37483] Re: Tmpfile.newがデフォルトで/tmpを利用すること — nobu.nakada@... 2003/04/01

なかだです。

[#37493] Re: Tmpfile.newがデフォルトで/tmpを利用すること — TAKAISHI Hayato <rio-t@...> 2003/04/02

こんにちは、高石です。

[#37496] Re: Tmpfile.new がデフォルトで/tmpを利用すること — siena@... (Siena. / SHINAGAWA, Norihide) 2003/04/03

Siena. です。

[#37499] Re: Tmpfile.new がデフォルトで/tmpを利用すること — matz@... (Yukihiro Matsumoto) 2003/04/03

まつもと ゆきひろです

[#37500] Re: Tmpfile.new がデフォルトで/tmpを利用すること — "U.Nakamura" <usa@...> 2003/04/03

こんにちは、なかむら(う)です。

[ruby-list:37417] Re: Secure「ではない」script の書き方

From: Taku Nakajima <tnakajima@...>
Date: 2003-03-25 17:19:18 UTC
List: ruby-list #37417
中島@ブレーンです。

> |だから、できれば各safelevelについて、抽象的に簡潔に「このレベルの意味
> |はこうです」というようなガイドラインのようなものがほしいような気がしま
> |す。なんとなく、暗黙のガイドラインがすでにあるような気がするので、でき
> |れば、それを明文化していただけるとありがたいです。
> 
> あちこちに書いたような気がしますが。まあ、いいや、こうなります。
> 
>   0 デフォルト。なにもしない
>   1 汚染されたデータによる危険な操作の禁止
>   2 プロセス関係の操作の禁止
>   3 生成されるオブジェクトが汚染される
>   4 信頼できないコードが実行できる

確かにこの説明は「オブジェクト指向スクリプティング言語Ruby」に書いてあ
りました(^^;

この説明で、「何をすればよいか」はだいたいわかるんですが、「なぜそれを
するのか」がもうひとつわかりません。untaintしてevalするようなライブラ
リを配ろうとすると、すごく不安です。

# 本音を言えば、何か作者の想定外の使い方で事故が起きた時に「おまえが悪
# い」と言えるだけの理論武装をしたいと(笑)

そこで、自分なりに「こういう説明がほしかった」というのをたたき台として
書いてみますので、もし間違いや不足があったら指摘してください。

---------------------------------------------------------------------
== Rubyのセキュリティ機能は何をするものか?

Rubyは動的な言語ですから、実行時にコードの一部を変更したり、プログラム
にプログラムを作らせてそれを実行することができます。この柔軟性はRubyの
大きなメリットですが、このために「自分の書いたコードに何ができるのか」
ということが、書いた本人にさえもわからなくなることがあります。

そこで、安全性を重視する場合には、自分の書いたコードを檻に入れて暴れな
いようにすることが必要になります。つまり、コードにできることを制限して、
予想外の動作をしても問題が起きないようにすることが必要になります。

それをサポートするのがRubyのセキュリティ機能です。そして、この檻を調整
するのが$SAFEという大域変数です。この変数に1〜4を入れることで、檻の広
さを調整できます。

レベル3や4は、檻が狭くできることが非常に限定されています。ですから、他
人の書いたコードを実行することもできます。つまり、全く信頼できないコー
ドでも、この檻の中に入れてしまえば、もう悪さができなくなります。

=== $SAFE=0

デフォルトでは、$SAFE=0、つまり全く檻が無い状態で、あなたのコードは何
でも好きなことができます。

=== $SAFE=1

$SAFE=1にすると、あなたのコードのうち、外部からのデータによって変化す
る部分が檻に入れられます。例えば、

  t = STDIN.gets # 外部からのデータ

このtが檻に入ります。実装としては、tという文字列オブジェクトはtainted?
というフラグが立っている状態になります。

  p t.tainted? # => true

このtから生まれるオブジェクトは全部檻に入った状態で生まれます。

  t2 = t + "aaa"
  t3 = t[0]
  t4 = t.scan(/./)[0]

t2〜t4はtainted?フラグがONの状態で生まれます。

檻に入ったオブジェクトは、プログラムの外部に影響を及ぼすことができなく
なります。外部への操作とはコマンドの実行とかファイルの生成、変更等です。

つまり、$SAFE=1とは何から何を守るのかと言うと

  何から → コードの中で外部のデータに依存する部分から
  何を   → ファイルシステム等プログラムの操作対象(実行環境?)

このレベルでは、以下のものは守られません。

  * プログラム実行時にプログラム内部で生成されるオブジェクト
  * 自プロセス

=== $SAFE=2

$SAFE=2でコードを実行すると、檻の外にある(tainted?フラグが立ってない) 
オブジェクトにも制限がつきます。すなわち、以下の操作は一切できなくなり
ます。

  * 自プロセスの状態に影響を及ぼす操作(chdir trap exec exit等)

つまり、$SAFE=2とは何から何を守るのかと言うとまず$SAFE=1と同様次のもの
を守ります。

  何から → コードの中で外部のデータに依存する部分から
  何を   → ファイルシステム等プログラムの操作対象

それに加え、次のものも守ります。

  何から → 実行される全てのコードから
  何を   → 自プロセス

このレベルでは、プログラム実行時に生成されるオブジェクトは守られません。

=== $SAFE=3

$SAFE=3でコードを実行すると言うことは、このレベルで実行されるコード自
体を檻に入れることを意味します。つまり、このコードから生成されるオブジェ
クトは全て檻の中で生まれます(生成されるオブジェクトは全てtainted?がON)

また、このレベルは檻の中にあるオブジェクトを外に出すことはできません。
(tainted?フラグをoffにする操作が許されない)コード自体が檻の中にあるか
らです。

つまり、$SAFE=3とは何から何を守るのかと言うと

  何から → このレベルで実行される全てのコードから
  何を   → ファイルシステム等プログラムの操作対象と自プロセス

なお、このレベルでも、プログラム実行時に生成されるオブジェクトは守られ
ません。

=== $SAFE=4

これまでは、プログラムの操作対象、つまりファイルや自プロセス等は檻の外
にあって檻の中からは手が出せない状態でしたが、Rubyオブジェクトは全て檻
の中から手が出る所にありました。(外部に影響を及ぼさない、プログラム内
部のオブジェクトに対する操作は無条件に許可)

このレベルになってはじめて、プログラム実行時に生成されるオブジェクトの
一部を保護するようになります。つまり、一部のオブジェクトは檻の中からは
手が出ない所に置かれた状態になります。

しかも、檻の外にあるオブジェクトを檻の中に入れることもできなくなります。
(tainted?フラグをONにする操作が許されない)

つまり、$SAFE=4とは何から何を守るのかと言うと

  何から → このレベルで実行される全てのコードから
  何を   → ファイルシステム等プログラムの操作対象と自プロセスと
            檻の外で生成された全てのオブジェクト


== 拡張ライブラリ作成者へのガイドライン

Rubyの拡張ライブラリは、なるべくRubyのセキュリティモデルに適合すること
が求められます。つまり、檻に穴をあけることが無いように注意します。

まず、メソッドを以下の3つに分類します。

  * オブジェクトを生成するメソッド
  * オブジェクトの内部状態を変更するメソッド
  * 上記以外の(参照系)メソッド

それぞれのタイプごとに、以下のものを説明していきます。

  * メソッドに求められる要件
  * それを(簡単に)実現する方法

また、メソッドの実装において留意すべきことを最後に説明します。

=== オブジェクトを生成するメソッド

==== メソッドに求められる要件

檻の中のオブジェクトが生成したオブジェクトが檻の外に出ないようにする。
すなわち、このオブジェクトの生成に使用したオブジェクトが汚染されている
場合、このオブジェクトは汚染された状態で生成される。

==== それを(簡単に)実現する方法
OBJ_INFECT()
rb_obj_infect()

=== オブジェクトの内部状態を変更するメソッド

==== メソッドに求められる要件

$SAFE=4の時に、檻の外と中の相互作用がないようにする。つまり、自分と相
手が檻の中にいるか(tainted?がONか)外にいるかをそれぞれチェックして、両
者が一致してなければ、例外を発生させる


==== それを(簡単に)実現する方法
rb_secure(4) if tainted?
rb_secure_update(obj) 1.8.0以降?

=== メソッドの実装において留意すべき点

当然ですが、メソッドの実装においては、セキュリティモデルを壊さないよう
に注意しなくてはなりません。そのために必要なことはたくさんありますが、
Rubyオブジェクトの操作については、rb_系メソッドや各マクロの内部でほぼ
自動的に処理されます。

問題は、Rubyオブジェクト以外が関係する操作です。

==== Value以外の変数

Value型以外の変数に、Rubyオブジェクトの内容を保存したり、逆に、変数か
らRubyオブジェクトを生成する場合は、檻の外と中が通じてしまわないような
配慮が必要です。例えば、RStringからchar*に保存して、後でそのchar*から
RStringを作成するような場合です。

この場合は、以下の2つのどちらかを行ないます。

  * 元のオブジェクトのtainted?状態を何らかの形で保存する
  * 変数から生成したオブジェクトをtainted?にする

==== 環境への操作

外部環境への操作は、セキュリティモデルに準じたチェックが必要です。

例 クリップボードへの書きこみ … ファイルへの書きこみに準じる
   Cレベルのグローバル変数の変更 … $SAFE=4では不可

このチェックはSafeStringValue()で簡単に実現できます。

== untaintする前に

$SAFE<=2では、任意のオブジェクトをuntaintすること、つまり檻から出すこ
とができます。当然ですが、これは不注意に使うとセキュリティモデルに穴を
開けることになります。

untaintしてよいオブジェクトは以下のどちらかの条件に合ったもののみです。

  * そのオブジェクトは外部由来のものではない

    自分で作成したキャッシュデータのように、ファイルから読みこんでも、
    スクリプト(開発者)の管理下にあるデータがあります。このようなオブジェ
    クトはuntaintして、檻の外に出してかまいません。ただし、そのキャッ
    シュが外部から変更されないことを(ディレクトリのアクセス権等で)確認
    する(前提条件として明記する)必要があります。

  * そのオブジェクトは外部環境の変更に使用されることはない

    次のようにそのオブジェクトが一時的なオブジェクトで、用途が限定され
    ている場合には、外部から来たオブジェクトをuntaintしてもかまいません。

      eval %Q[puts '#{text.untaint}']

---------------------------------------------------------------------

書きながら考えているうちに、長くなってしまいました。何が欲しかったかと
言うと、次の3つです。

 * 各レベルごとに、このレベルでは何から何を守りたいのか
 * 拡張ライブラリのメソッドに要求されること(どう実現するかを抜きにして)
 * untaintしてもセキュリティモデルを壊さない条件

この3点が、暗黙の合意があるのに明文化されてないことだと思います。

それと、今さら言ってもしょうがないことですが、このように分析してみると
他のレベルと比べて$SAFE=2だけが不明確というかややあいまいな気が・・・

--
「stableでなければ生きていけない。unstableでなければ生きてる意味がない」
中島 拓 (株)ブレーン 研究部 (tnakajima@brain-tokyo.jp)
http://www.brain-tokyo.jp/research/amrita/

In This Thread