PERLSEC(1)               USER COMMANDS                 PERLSEC(1)



NAME
     perlsec - Perl のセキュリティ

DESCRIPTION
     Perl は安全な setuid スクリプトや setgid スクリプトを書くこ
     とが簡単にできるように設計されています。 シェルはスクリプト
     内の各々の行に対して置換を何回も行ないますが、Perl は見えな
     い「内部動作」を少なくした、より伝統的な評価機構を使っていま
     す。 さらに、この言語では、より多くの組み込み機能を備えてお
     り、目的達成のために、外部の (そして、信頼のおけない可能性の
     ある) プログラムに頼らなければならないことが、少なくなってい
     ます。

     多くの OS で、スクリプトのような柔軟なシステムに対して、特別
     な権限を与えることによる明らかな問題以前に、setuid スクリプ
     トは、スタート時点から本質的に安全ではありません。 これは、
     特にシステム上にシンボリックリンクがある場合には、カーネルが
     何を実行するのかを調べるためにファイルをオープンしてから、
     setuid インタプリタが変更を行なって、そのファイルを解釈する
     ために再オープンするまでに、何かが変更される可能性があるから
     です。

     幸いにも、カーネルの「機能」は、禁止することができる場合があ
     ります。 不幸にも、禁止する方法は 2 通りあります。 一つは、
     システムが setuid ビットが設定されているスクリプトを扱えない
     ようにするもので、こちらは余り役に立つことがありません。 も
     う一つは、単にスクリプトに付いた setuid ビットを無視するとい
     うものです。 もし、後者であれば、Perl スクリプトに付けた、
     意味のなくなった setuid/setgid ビットを Perl が見つけたとき
     に、setuid と setgid の機構をエミュレートすることができます。
     これは、必要なときに自動的に呼ばれる、suidperl という特別な
     実行ファイルによって行なわれます。

     しかし、カーネルの setuid スクリプトの機能が禁止されていなけ
     れば、Perl は、この setuid スクリプトが安全ではないと警告を
     発します。 カーネルの setuid スクリプトの機能を禁止するか、
     スクリプトに C ラッパーを被せる必要があります。 どのように
     これを行なうかについては、Perl 配布キットの eg ディレクトリ
     の wrapsuid プログラムを参照してください。

     setuid スクリプトが、この本質的な非安全性のバグから免れてい
     るシステムも存在します。 たとえば、Solaris の最近のリリース
     では大丈夫なようです。 このようなシステムでは、カーネルがイ
     ンタプリタへオープンする setuid スクリプトの名前を渡すとき、
     そのものを表わすパス名を渡すのではなく、代わりに /dev/fd/3
     を渡します。 これは、既にスクリプトに対してオープンされた特
     殊ファイルですから、横取りをするような悪意を持った競合条件を
     避けることになります。 こういったシステムでは、Perl をコン
     パイルするときに -DSETUID_SCRIPTS_ARE_SECURE_NOW をつけてお
     くとよいでしょう。 Perl を作る Configure プログラムは、自分
     でこれを見つけようとします。




Perl manpages Last change: Release 5.0 Patchlevel 00            1






PERLSEC(1)               USER COMMANDS                 PERLSEC(1)



     Perl が setuid スクリプトを実行するとき、明らかな罠に填った
     りしないように、特別な予防策がとられます。 (いくつかの点で、
     Perl スクリプトは同じことをする C プログラムよりも安全である
     といえます。) すべてのコマンドラインの引数、環境変数、入力
     は、「汚染」マークが付けられ、サブシェルを起動するコマンドや、
     ファイルやディレクトリやプロセスに修正を加えるコマンドには、
     直接的にも間接的にも使用できないようになっています。 汚染マ
     ークが付けられた値を含んだ式で、設定を行なった変数もすべて、
     (たとえ、論理的に汚染された値が、その変数に影響を与えること
     が不可能であっても) 汚染されたことになります。 たとえば:

         $foo = shift;               # $foo は汚染された
         $bar = $foo,'bar';          # $bar も汚染された
         $xxx = <>;                  # 汚染された
         $path = $ENV{'PATH'};       # 汚染されたが、以下も参照
         $abc = 'abc';               # 汚染されていない

         system "echo $foo";         # 安全ではない
         system "/bin/echo", $foo;   # 安全 (sh を使いません)
         system "echo $bar";         # 安全ではない
         system "echo $abc";         # PATH が設定されるまでは、
                                     # 安全ではない

         $ENV{'PATH'} = '/bin:/usr/bin';
         $ENV{'IFS'} = '' if $ENV{'IFS'} ne '';

         $path = $ENV{'PATH'};       # 汚染されていない
         system "echo $abc";         # これで安全 !

         open(FOO,"$foo");           # OK
         open(FOO,">$foo");          # OK ではない

         open(FOO,"echo $foo|");     # OK ではありませんが ...
         open(FOO,"-|") || exec 'echo', $foo;        # OK

         $zzz = `echo $foo`;         # 安全ではなく、zzz は汚染

         unlink $abc,$foo;           # 安全ではない
         umask $foo;                 # 安全ではない

         exec "echo $foo";           # 安全ではない
         exec "echo", $foo;          # 安全 (sh を使いません)
         exec "sh", '-c', $foo;      # 安全と解釈されてしまいます

     汚染状況は、スカラ値ごとに管理されますから、配列要素の一部の
     要素だけが汚染され、他は大丈夫ということもあります。

     もし、何か安全とはいえないことをしようとしたならば、"Insecure
     dependency" とか "Insecure PATH" といった致命的エラーになり
     ます。 それでも、安全でないシステムコールや exec を書くこと
     ができることに注意しなくてはなりませんが、実行するためには、
     上記の最後の例のように、明示的に行なうことが必要になっていま



Perl manpages Last change: Release 5.0 Patchlevel 00            2






PERLSEC(1)               USER COMMANDS                 PERLSEC(1)



     す。 サブパターンを参照することでも、この汚染チェックの仕組
     みの裏をかくことができます。 $1, $2 といった部分文字列を使
     うときには、Perl は、使っているみなさん自身が、パターンを書
     く時点で、自分で何をしているのかが分かっているものと、仮定す
     るのです:

         $ARGV[0] =~ /^-P(\w+)$/;
         $printer = $1;              # 汚染されません

     これは、\w+ がシェルのメタ文字にマッチしませんから、かなり安
     全です。 /.+/ は安全とはいえないものですが、Perl はそれをチ
     ェックしてくれませんから、パターンの内容にも注意しないといけ
     ません。 これは、($> を $< に合わせないのであれば) ファイル
     名を与えて、そのファイルに何か操作を行ないたい場合に、汚染の
     マークを取り除く「唯一」の手段でもあります。

     "Insecure PATH" というメッセージには、$ENV{'PATH'} に既知の
     値を設定し、パスの中のディレクトリは、一般の権限では書き込み
     ができないようになっていることが必要です。 よく言われる文句
     には、実行ファイルのパス名をフルパスで書いても、このメッセー
     ジが出るというものがあります。 しかし Perl は、その実行ファ
     イルが PATH に依存して別のプログラムを実行しないと判断するこ
     とはできないのです。

     汚染された値を使うことには関与しない操作で、問題が起こること
     もあります。 ユーザが指定したファイル名を扱うときには、ファ
     イルテストを賢く利用してください。 可能ならば、open などは、
     $> = $< を設定してから行なってください。 (グループ ID の方
     も忘れないでください。) Perl は、汚染されたファイル名を読み
     込みのために open することは咎めませんので、出力に気を付けて
     ください。 汚染チェックの仕組みは、setuid の過ちを防ぐこと
     を目的としているのであって、何も考えなくてもよいということで
     はありません。






















Perl manpages Last change: Release 5.0 Patchlevel 00            3