[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[debian-users:31409] setuid shell script (Re: Re: [Q]I chmod u+s が使えない)



佐野@浜松です。

In <20020108014242.B15C.GAUNT@xxxxxxxxxxxxxxxxxxxxx>,
 on "Tue, 8 Jan 2002 01:52:20 +0900",
 with "[debian-users:31297] Re: [Q]I chmod u+sが使えない",
  Mitsuo KASAHARA <gaunt@xxxxxxxxxxxxxxxxxxxxx> さん wrote:

> Tue, 8 Jan 2002 01:13:05 +0900 に Toyohiko Nagai <nagai@xxxxxxxxxxxx> さんが
> [debian-users:31295] Re: [Q]I chmod u+s が使えない で書きました。
> 
> > > シェルスクリプトのSUIDは無視されるのではないでしょうか?
> > 
> >   ですね。まれに、できる処理系もあるって聞いたような気もしなく
> > もないですけど(これは記憶があやふやなんでちとあやしいですが)。

手元にある「Unix FAQ 日本語訳」に関連する項目が記載されているので、
紹介しておきます。

4.7) setuid されたシェルスクリプトを動かすにはどうすればいいでしょうか。
    
    [この質問に対する回答はかなり長くなります。しかしながら
    この質問は複雑で、とてもよくあるものです。この質問に回答し、
    以下に掲載する "indir" プログラムを作ってくれた
     Maarten Litmaath に感謝します。]
    
    まず、読者がいわゆる「実行可能シェルスクリプト」を認識するUNIX種
     (例えば、4.3BSDとかSunOS) を使っていると仮定します。そのような
    スクリプトは次のような行で始まっているでしょう。
    
        #!/bin/sh
    
    このようなスクリプトは、本物の (バイナリ) 実行形式と同じように、
    実行形式の種類を示すいわゆる「マジックナンバ」で始まっているため
    「実行形式」と呼ばれます。この場合、マジックナンバは '#!' で、
    OS は最初の行の '#!' 以降をスクリプトのインタプリタ (以下のように
    1個だけ初期化オプションを続けることができます) であると解釈します。
    
        #!/bin/sed -f
    
    この例で挙げた上記の行で始まるスクリプトを 'foo' と呼ぶことにしましょう。
    このスクリプトは /bin にあるとします。ここで、次のように入力した場合に
    ついて考えます。
    
        foo arg1 arg2 arg3
    
    OS はこの入力を、以下のような入力があった、というように再配列します。
    
        /bin/sed -f /bin/foo arg1 arg2 arg3
    
    しかしながら、一つ違いがあります。'foo' の setuid 許可ビットが
    設定されている場合、すなわち第一番目の例では、コマンド(foo)の
    許可ビットに従うことになります。もし、2番目のように実際に入力した
    ときには、OSは /bin/sedの許可ビットに従います。当然ながら、
    /bin/sed は setuid されていません。
    
    ----------
    さて次に、もしシェルスクリプトが '#!' 行で始まっていない場合、
    もしくは OS が '#!' を認識していない場合はどうなるでしょう。
    
    この場合には、ファイルが正当なマジックナンバーで始まっていないため、
    シェル(か他のプログラム)がスクリプトを実行しようとした時OSがエラーを
    返します。シェルはこのエラーを受け取ると、当該ファイルがシェルスクリプト
    であると「仮定」して、以下のような実行をしてみます:
    
        /bin/sh shell_script arguments
    
    しかしながら、上述のようにこの場合には 'shell_script' に対する
     setuid ビットは効力を発揮しません。
    
    ----------
    さて、次に setuid シェルスクリプトがセキュリティ上、危ない点について
    述べましょう。
    
    '/etc/setuid_script' というスクリプトが以下のように始まっているとします。
    
        #!/bin/sh
    
    ここで、次のような順序でコマンドを実行したら何が起こるでしょうか。
    
        $ cd /tmp
        $ ln /etc/setuid_script -i
        $ PATH=.
        $ -i
    
    最後のコマンドが以下のようになるのは上述の通りです。
    
        /bin/sh -i
    
    このコマンドはスクリプトの持ち主に setuid された、インタラクティブな
    シェルを起動することになります!まあ、このセキュリティホールは第一行を
    次のようにすることで簡単に塞ぐことが出来ます。
    
        #!/bin/sh -
    
    '-' はオプション列の終りを示します。次の引数の '-i' は本来そうあるべき
    であるように、コマンド群を読み込むべきファイル名として解釈されます。
    
    ---------
    しかしながらもっと重大なセキュリティに関する問題があります。
    
        $ cd /tmp
        $ ln /etc/setuid_script temp
        $ nice -20 temp &
        $ mv my_script temp
    
    3番目のコマンドは次のように解釈されます。
    
        nice -20 /bin/sh - temp
    
    nice をかけることで、コマンドの実行をずっと遅くできるので、'temp' を
    シェルが読み込む「前」に4番目のコマンドによりもともとの 'temp' を 
    'my_script' に置き換えることが可能です。このセキュリティホールを塞ぐ
    には以下の4つの方法があります。
    
    1) OS が setuid スクリプトを別の安全な方法で実行するようにする。
       System V R4 と 4.4BSD ではスクリプトのファイルディスクリプタをインタ
       プリタに渡す時に /dev/fd ドライバを使っています。
    
    2) スクリプトが間接的に実行されるようにする。実際のインタプリタがスクリ
       プトの実行を開始する前に、すべての環境が正当かどうかをチェックするフ
       ロントエンドを通す。もし、comp.sources.unix に流れた 'indir' プログ
       ラムを使うのでしたら、setuid スクリプトは次のようになります。
    
         #!/bin/indir -u
         #?/bin/sh /etc/setuid_script
    
    3) 'binary wrapper'(バイナリによるカバー)を作る。setuid した本当の実行
       形式(バイナリ)を作ります。その実行形式はスクリプトの名前を引数として
       受け取り、インタプリタを実行することだけを行ないます。
    
    4) 汎用の 'setuid スクリプトサーバ' を作る。このサーバは要求のあった
       'サービス' をデータベース中の正当なスクリプト群から探し、見つかった
       ら正当な引数を使って正しいインタプリタを起動する、というものです。
    
    ---------
    正当なファイルが解釈実行される、というところまでうまくいったと
    しましょう。他に危険はないでしょうか。
    
    そうです!シェルスクリプト中で、PATH 変数に安全なパスを明確に指定する
    ことを忘れてはいけません。何故だかわかりますか。これとは別に適切に
    設定されていないと面倒を引き起こし得る IFS という変数もあります。他にも、
    同様にセキュリティの低下に影響する環境変数がいくつかあります。例えば、
    SHELL 等です。更に、スクリプト中のコマンド群が対話シェルエスケープを
    許していないことを確認しなければなりません!そして、変に設定されている
    かも知れない umask という値があります...
    
    その他諸々。で、setuid スクリプトはスクリプト中で呼び出すすべての
    コマンドのバグとセキュリティに関する危険を「受け継ぐ」ということを
    肝に命じておいて下さい!
    
    概して、setuid シェルスクリプトは非常に危険なものであるということが
    おわかり頂けたと思います。かわりに C のプログラムを書く方がより良い
    解決になるでしょう。
    
以上、御参考まで

> > > 別の方法を用いて行うと良いと思います。
> > 
> >   sudo なんかが一般的なんじゃなかったかと。apt-get sudo してみ
> > てはいかがでしょうか?

 shell script ではありませんが、perl-suid という方法もありますね。

--
   # わたしのおうちは浜松市、アカウミガメもやってくる
    <kgh12351@xxxxxxxxxxx> : Taketoshi Sano (佐野 武俊)