Logo address

UNIX - SUID と root 特権 -

目次

ユーザ

UNIX はマルチユーザシステムである。この事は、マシンを使用するときにユーザの認証が行われるだけではなく、(ネットワークなどを通じて)同時に複数のユーザがマシンを使用できる事を意味している。
マルチユーザオペレーティングシステムは、異なるユーザが互いに干渉しあわないような仕組みを持っている。以下の2つは干渉を排除するための代表的な例である。
1. Alice のファイルを Bob が勝手に読んだり変更したりはできない。
2. Alice が実行中のプログラムを Bob が妨害できない。

UNIX のユーザ管理はパスワードファイル /etc/passwd によって行われる。
以下はパスワードファイルの例である。(一部分だけを抜き出している。)

root:qk3yth3E51zjg:0:1:Operator:/home/operator:/bin/sh
news:*:6:6::/usr/spool/news:/bin/csh
alice:Eaq8Ogbk48Yuw:104:20:Alice:/home/alice:/bin/csh
bob:qKjM5IqG18qwc:103:20:Bob:/home/bob:/bin/csh
このファイルの各行は':' で区切られた7個のフィールドから構成され、各フィールドには、
  1. ユーザ名(login name)
  2. 暗号化されたパスワード
  3. ユーザID
  4. グループID
  5. ユーザの実名
  6. ホームディレクトリ
  7. 起動シェル名
が記されている。

UNIX ではユーザは番号によって管理される。つまり alicebob のようなユーザ名は UNIX の仕組みにとっては本質的ではなくユーザIDが全てである。

どの UNIX システムも特殊なユーザ root が存在する。 root は管理者のユーザ名である。UNIX においてはユーザ root は特別の意味を持っている。即ち、後に述べる、root 特権を行使できるユーザである。

UNIX には人間ではないユーザ名も存在する。この例では news がそうである。そうしたユーザのパスワード欄は * になっている。(最近の UNIX は人間のユーザのパスワード欄も * になったりしている。パスワードの管理法が変化しているのだ。)

グループ

マルチユーザのシステムでは、ユーザ相互のグループ作業を可能にするために、
ユーザグループを定義できるのが望ましい。
UNIX におけるグループ編成の考え方は単純である。即ちグループの相互関係は表現できない。UNIX におけるグループの編成は /etc/group で行われている。以下はその一部の抜き書きである。
wheel:*:0:root,bob
news:*:6:
other:*:20:
このファイルの各行は':' で区切られた4個のフィールドから構成され、各フィールドには、
  1. グループ名
  2. 暗号化されたパスワード
  3. グループID
  4. ユーザを構成するユーザ名の一覧
が記されている。パスワード欄は常に * である。(利用されていない。)
wheel グループは特殊である。このグループのメンバは su コマンドを行使することによって root 特権(後述)を手にする事ができる。

/etc/passwd によってグループの構成員である事が示されている場合には
/etc/group に明示的に記載する必要はない。例えば alicebob はグループ ID が 20 であることが /etc/passwd によって示されている。従って /etc/groupother の欄に alicebob を記載する必要はない。

ファイル

コンピュータの利用者にとってファイルは最も重要な財産である。マルチユーザのシステムでは、ファイルを他の利用者の不正な(あるいは誤った)操作から守るために、ファイルには所有権が付与され、アクセス権を設定できる。
UNIX ではファイルの所有者を識別するために、1つ1つのファイルにはユーザIDとグループIDが付与されている。(ユーザ名やグループ名ではなくてIDである。)
UNIX におけるアクセス権の設定は、読み取り(read)、書き込み(write)、実行(execute)
の許可を、ファイルの所有者(owner)、グループ構成員(group)、その他の全てのユーザ(others)に対して定める事によって行われる。
注意: その他の全てのユーザ others とグループ名としての other を混同してはならない

UNIX ではファイルのアクセス権の設定状況はコマンド

	ls -lg
によって見る事ができる。
-rw-------  1 alice    other        509 Jun 10 20:26 mbox
drwxr-xr-x 51 alice    other       2048 Jun  2 07:05 bin/
-rwxr-xr-x  1 alice    other       1916 Feb 14 1997 a.out
出力の各行は空白で区切られた9個のフィールドから構成されており、各々の意味は以下の通りである。
  1. モード
  2. リンク数
  3. ユーザ名
  4. グループ名
  5. ファイルサイズ
  6. 作成月
  7. 作成日
  8. 作成年または作成時刻
  9. ファイル名
モードは10個の文字から構成され、各カラム毎に意味が与えられている。文字 - はどのカラムにも指定できる。どのカラムも - でない場合には、普通は drwxrwxrwx となる。即ち(特殊な場合を除き)カラム位置によって指定される文字が定まっている。そしてこれらのカラムは以下の図で示されるブロックに分けられる。

先頭の1文字はファイルの種類を表している。通常のファイルの場合には - が書かれている。他方 d はこのファイルがディレクトリである事を意味している。(UNIX ではディレクトリもファイルの一種である。但しユーザによる書き込みはできない)
残りの9個の文字は3つのブロックに分けて解釈される。
最初のブロックは所有者に対しての、次のブロックはグループ構成員に対しての、最後のブロックはその他の全てのユーザに対してのアクセス許可を定める。各々のブロックは3つの文字から構成される。これらは順に read/write/execute の許可の有無を定める。- は許可のない状態、r は readを、w はwriteを、x はexecute を意味している。
従って
	-rw-------  1 alice    other        509 Jun 10 20:26 mbox</pre>
によって以下の事がわかる: mbox はユーザ alice の所有する通常のファイルであり、それはグループ other に属している。そして alice はこのファイルに関しては alice 以外の誰にも read/write/execute のアクセスを許していない。

ファイルに対する実行許可とは、このファイルに対して実行が許可されていることを意味している。(UNIX では内容上実行可能なファイルであっても実行許可が与えられないと実行されない。) 他方ディレクトリに対する実行許可とは、このディレクトリに(コマンド cd によって)入り込める事を意味している。

ファイル管理上の誤解しやすい点がある。この例では mbox は alice だけが書き込み許可を持っているので他人によってこのファイルの内容は変更できない。しかしながらこの事は他人によってこのファイルが消去されない事を意味しない。他人によるファイルの消去を防ぎたい場合にはファイルが置かれているディレクトリの許可モードを

	drwxr-xr-x
をする必要がある。ファイルの消去はディレクトリの変更を伴うのでこれで防ぐ事ができると言う理屈である。この理屈は筋としては通っているけれども回りくどい理屈である。

UNIX ではファイル概念が拡張され様々なデバイスなどもファイルの仲間としての扱いを受けている。従ってモード欄の最初の文字には d 以外にも多くの種類があるが解説を省略する。
UNIX では実行許可を意味する x の代わりに s を与える事ができる。これを SUID ビットと呼ぶ。一般のユーザが SUID ビットを設定する事は実際上あり得ないのだが、このビットは UNIX を理解し適切に運営する上で極めて重要なので、プロセスの解説で触れる。

プロセス

プロセスとは実行に移されたプログラムの事である。プロセスはメモリの中に存在する。プロセスの一覧はコマンド ps によって見ることができる。
	ps -axgu
をコマンドとして実行すると、例えば
USER       PID  %CPU %MEM VSIZE RSIZE TT STAT  TIME COMMAND
root         1   0.0  0.1  736K   96K ?  SW    0:00 /usr/etc/init -xx
root        -1   0.0  5.7 18.1M 3.68M ?  S <   0:00 <mach-task>
root         2   0.0  0.2  688K  136K co SW    0:00  (mach_init)
...
alice      365   0.0  0.3 8.69M  184K p4 SW    0:00 -sh (sh)
alice      368   0.0  0.9 2.95M  568K p4 SW    0:00 bash
root       436   0.0  1.1 2.20M  728K p4 R     0:00 ps -axgu
が表示される。(ps のコマンドオプションは UNIX の種類によって異なる。) ここに表示されている最初のフィールドはプロセスの所有者を表している。

alice が alice の所有するプログラムを実行すればそれによって発生したプロセスは alice のものである。即ち、そのプロセスは他のユーザ、例えば bob の干渉を受けない。またそのプロセスがファイルを生成する場合には生成されたファイルは alice の所有物であり、ファイルへのアクセスに対しても alice としてそのファイルの許可モードに従う。

alice が bob の所有するプログラムを実行した場合には、それによって発生したプロセスは誰のプロセスであろうか?

論理的には二つの考え方があり得る。普通の考え方は、実行者である alice のプロセスと見做すことである。alice は alice のファイルを処理するためにプロセスを起動するのである。従ってもしもこの考え方を採らない場合には、コンピュータシステムはユーザ毎に彼らが必要とする全ての実行ファイルを準備しなければならなくなるだろう。これは実際上不可能である。
もう一つの(特殊な)考え方はファイルの所有者である bob のプロセスと見做す考え方である。UNIX の際立った特徴はこの両者の考え方を共に認めた事にある。そして後者の考え方を表現するために、ファイルの実行許可を表す x の代わりに s を設定することにした。(これを SUID ビットと言う。)

具体的な例を挙げよう。

ユーザが自分のパスワードを変更したい場合にはコマンド passwd を実行する。すると /bin/passwd が実行される。このファイルは

	-rwsr-xr-x  1 root     wheel       9516 Apr 16  1995 passwd
となっている。このプログラムは owner の許可モードが rws となっているから実行者に依らず root のプロセスとして実行される。/bin/passwd/etc/passwd を書き換える必要がある。他方 /etc/passwd
	-rw-r--r--  1 root     wheel        602 Jan 14  1996 passwd
となっているから root によってしか変更を許されない。従って /bin/passwd は root のプロセスとして実行される必要があり、 SUID ビットが立てられているのである。

同様に group に関しても s が指定でき、同様な意味を持つ。
others に対する実行ビットにも s が指定できるが、これは全く別の意味である。

SUIDビットは主に root の所有するファイルに対して設定される。即ちユーザ権限ではできない処理を root にお願いして代行して貰うのが SUID ビットの主旨なのである。

SUIDビットを立てたファイルによって生成されるプロセスの動作は、実はここに解説した以上に変化に富んでいる。SUID ファイルは危険極まりないものであり、(作成にも、管理にも、その存在自体にも)細心の注意を払う必要がある。一般のユーザは(悪意を持たぬ限り) SUID ファイルを持つ必要はない。
bob の悪意と alice の不注意によって、alice を所有者とした SUID ファイルを bob が手に入れる事がありうる。その場合には alice のファイルは bob の意のままなっていると考えた方が良い。(そのようなファイルはたぶん人の目に留まる所には置かれていないであろう。)

SUID によって UNIX は柔軟で強力な仕組みを持つ事になった。困った時の神頼み( root 頼み)の SUID である。同時に SUID は(特に root 特権との組み合わせで)セキュリティホールの源泉ともなってきた。

強力で柔軟なメカニズムは魅力的ではあるが必要以上のものを持つ事は災いの源である。読者はプログラミング工学における goto 文の問題を思い起こすべきである。

root 特権

誤解を避けるために最初に強調しておこう。root 特権と言うのは管理者特権の事ではない。
如何なるコンピュータシステムであれ管理者は一般ユーザに対していろいろな特権を持っている。でないとシステムを構築し維持する事は不可能である。
root 特権とは root のプロセスの持っている特権の事である。管理者である root が実行するプログラムは通常 root のプロセスを生成し、それによって root 特権を行使できる。root 特権を行使するのは管理者とは限らない。 SUID が付与されている root 所有のプログラムが実行されれば root 特権が行使される。

root のプロセスは絶対的な権限を持っている。無条件に無制限の権利を行使できる。例えば

  1. 全てのプロセスをコントロールできる
  2. ファイルのアクセス権の設定を無視して任意のファイルにアクセスできる
  3. 任意のユーザに変身できる
などである。これを root 特権と言う。

管理者は root として行動する場合には細心の注意が必要である。ちょっとした不注意がシステムを壊滅させる。root 特権はシステムの構築と解体に必要な特権であり、日常的な管理に使うには強力すぎるのである。

root 特権を行使するプログラムは本来は OS の機能を補完するためのものである。ところが物事は易きに流れるのであり、ネットワークの導入に伴って、現在では root 特権を抱えた多数のサービスプログラムが動いている。これらのサービスプログラムにバグが無く、管理の手落ちが無ければ問題は理論的には発生しないはずだが現実は理想通りには行かない。

ネットワークからの侵入者の目標は root 特権を手に入れる事である。root 特権を手に入れる事によって彼らが得るものは、お金に換算可能なものかも知れないし、単なる快感かも知れない。いずれの場合もシステムは再構築を余儀なくされるであろう。

サービスプログラムの殆どはその内容からして root 特権を必要とする程のものではない。それにも関わらず root 特権でスタートする。何故そのようなことを... そうなってしまったのだ。