ユーザ権限とアクセス制御
ユーザと権限
おおよそ今時のコンピュータシステムはユーザが利用しようとするにはユーザ 認証を必要とします。UNIXではアカウント名とパスワードの組合せでユーザ認 証を行うのが基本となっています。オペレーティングシステム内部ではユーザ の違いをアカウント名ではなくユーザID(UID / User IDentifier)による数値 で認識しています。またユーザは1つデフォルトのグループID(GID / Group IDentifier)がつけられています。
唯一例外的なのはユーザIDが0、グループIDが0のユーザrootです。 スーパーユーザーと呼ばれ、 UNIXにおいてはオールマイティーな権限を持つ特別なユーザです。 管理者権限として説明される場 合が多いのですが「オペレーティングシステム上で何でもできてしまう権限」 と説明した方が適切でしょう。
ユーザIDとグループID
オペレーティングシステムの中での利用権限を意味するのがユーザIDです。た とえばファイルには所有者(Owner)が設定されていますが、その所有者情報と はユーザIDのことです。また、プロセスが動作している時には、いずれかのユー ザIDとグループIDを持っており、そのユーザIDに付加された権限の範囲内にお いてプロセスは資源にアクセスできます。グループIDは、そのグループにユー ザが登録されている場合、そのユーザに与えられるグループ権限です。UNIXの 基本的な権限は、このユーザIDの違いによるユーザ権限と、グループID の違 いによるグループ権限の2つから成り立っています。ファイルやプロセスの資 源は次の3つに対しての許可によってアクセスコントロールされます。
まずファイルに対するユーザIDとグループIDを見てみましょう。ファイルには
ユーザIDとグループIDが設定されています。ユーザIDは、このファイルの所有
者、もう少し正確にいうと、このファイルの属性を設定できるユーザが誰であ
るかを意味しています。所有者がファイルの属性を変更し、そのファイルのア
クセス権限などをコントロールすることができます。ls -lをみてみましょう。
尚、表示される際は、ユーザIDは/etc/passwdで設定されているユーザIDに対
応するアカウント名、グループIDは/etc/groupで設定されているユーザIDに対
応するグループ名に変換されて表示されます。
- アクセス権限 : 読み込み / 書き込み / 実行
- ユーザに対して : 許可 / 不許可
- グループに対して : 許可 / 不許可
- それ以外に対して : 許可 / 不許可
$ ls -l memo.txt -rw-r--r-- 1 hironobu hironobu 44 Sep 20 19:17 memo.txt $ ls -l /var/mail/hironobu -rw-rw---- 1 hironobu mail 0 Dec 9 19:39 hironobu
memo.txtはユーザIDがhironobu、グループIDがhironobuになっており、所有者
は読み書き、同じグループには読み込み、その他の権限でも読み込みができま
す。正確には、所有者と同じユーザIDを持ったプロセス、設定されたグループ
と同じグループに属するユーザIDを持つプロセス、それ以外のユーザIDを持つ
プロセスとなります。
/var/mail/hironobuというファイルのユーザIDはhironobuになっており、グルー
プIDはmailです。mailのグループ権限を持つプロセスから読み書き可能になっ
ています。具体的には、メールサーバなどのプロセスが読み書きできるように
なっています。
グループID利用の方法
ここにファイルgroup_share.datがあるとします。これをユーザtaroとユーザhanakoが共通に読み書きのアクセスでき、 他のユーザはアクセスできないようなパーミッションにしたいとします。
$ ls -l 合計 56 -rw-r--r-- 1 taro taro 51200 2005-11-23 18:33 group_share.dat
まずgroup_share.datを所有者とグループにはrw、それ以外には読み書き禁止にします。
chmodを使いますが、2度に分けてオプションを使ってもいいですし、モードを数字で与えてもかまいません。
$ chmod o-wr group_share.dat $ chmod g+wr group_share.dat
あるいは
$ chmod 660 group_share.dat
結果は次のようになります。
$ ls -l 合計 56 -rw-rw---- 1 taro taro 51200 2005-11-23 18:33 group_share.dat
次にroot権限でtaroとhanakoの共通に使えるグループtaro-hanakoを作ります。
そしてtaro とhanakoをグループtaro-hanakoに加えます。
# groupadd taro-hanako # gpasswd -a taro taro-hanako # gpasswd -a hanako taro-hanako
taroが新しいグループに加わった時、taroが再度ログインした時からその新しいグループ (この場合taro-hanako)が有効になります。
再度ログインした状態で、taroはgroup_share.datのグループIDをtaro-hanakoにします。
$ chgrp taro-hanako group_share.dat ... -rw-rw---- 1 taro taro-hanako 51200 2005-11-23 18:33 group_share.dat
これでgroup_share.datはtaro-hanakoのグループに属しているtaroとhanakoが読み書きが出来るようになります。
- 考えてみよう
- apacheはユーザwww-dataの権限で動作しています。cgi-binなどでコマンドを動かしファイルinfo.datに情報を書き込む必要があります。しかし、info.dataの中身に関してはセキュリティ上の問題のためユーザfoo以外には読ませたくありません(www-dataにも許可しません)。さて、この場合、info.datの適切なファイルの所有者、適切なパーミッションはどのようなものでしょうか。
プロセスのユーザIDとグループID
まずログインした時に、そのアカウント名に割り振られたユーザIDとグループIDの権限でログインシェルが動き始めます。 そのシェルから起動されるプロセスにはデフォルトで親プロセスのユーザIDとグループIDが受け継がれます。 root権限(注)でsetuid(2)やsetgid(2)を使うとプロセスのユーザIDを変更することができます。
- 調べてみよう
- setuid(2)やsetgid(2)の利用にはもう少し限定した条件があるので調べてみよう。
$ ps aux USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 1 0.0 0.0 1272 432 ? S Aug23 1:49 init [2] ... daemon 126 0.0 0.0 1384 296 ? S Aug23 0:00 /sbin/portmap canna 2799 0.0 2.7 19152 17568 ? S Aug23 13:02 /usr/sbin/cannase root 23439 0.0 0.1 2936 660 ? S Nov24 0:17 /usr/sbin/apache www-data 23474 0.0 0.0 2948 632 ? S Nov24 0:00 /usr/sbin/apache hironobu 20287 0.0 0.0 2464 224 pts/0 S Oct16 0:00 bash hironobu 2796 0.0 1.0 8752 6716 ? R 12:14 0:05 emacs20 -geometry ...
現在の権限管理
古典的なUNIXはUIDとGIDだけで説明は済みますが、Linuxも含めBSD 4.3以降では、もっと複雑な設定ができます。 Linuxでは4つタイプのUIDと4つのGIDのタイプを持っています。
- ユーザID、グループIDの種類
- UID / GID : 今まで通りのUID / GID
- RUID / RGID : 実UID / 実GID --- UIDやGIDと同じ役割 (RはReal)
- EUID / EGID : 実効UID / 実効GID --- 権限があるかどうかをチェックする時に使う (EはEffective)
- SUID / SGID : 保存UID / 保存GID --- 有効化・無効化を行うための保存 (SはSaved)
- FSUID / FSGID : ファイルUID / ファイルGID --- Linux独自のファイルのアクセス権限のチェック
setuid
これらはプロセスが、どのような権限で動作するかを規定するものです。 UNIXには実行ファイルの属性に(モードに)setuid bitを設定しておくと、 その実行ファイルはファイルの所有者の権限で動作します。 setgid bitは実行ファイルのグループの権限で動作します。 コマンドfindを使って探してみましょう。
$ ls -l `find /bin -perm +a+s -print` -rwsr-xr-x 1 root root 35464 Nov 3 04:56 /bin/login -rwsr-xr-x 1 root root 72488 Dec 24 2002 /bin/mount -rwsr-xr-x 1 root root 15244 Nov 19 2001 /bin/ping -rwsr-xr-x 1 root root 23112 Nov 3 04:56 /bin/su -rwsr-xr-x 1 root root 36904 Dec 24 2002 /bin/umount
最初の表示にある-rwsr-x-rxのsがsetuid bitの意味です。
つまり、これらのコマンドは所有者がrootであり、かつ、
このコマンドを動かすとrootの権限で動かすことができるという意味です。
この実行時は、ruidは利用者、euidがrootとなり、
root権限のファイルなどに書き込むことができるようになります。
一般ユーザでも何でもできる権限を手に入れてしまうということで、
このようなプログラムに誤りがあると大きなセキュリティ上の問題になります。
setgid
setgidは、set group id bitの意味です。そのファイルのグループIDと同じ権限で実行できます。
$ ls -l `find /usr/bin -perm +g+s -print` ....
ruidがrootの時、つまりrootがファイルを実行した時は何でもできるので、euidをプロセス内で制限なく変更できます。 たとえばapacheは唯一1つrootでのプロセスがあり、 そこから生成し子プロセスがwww-data(あるいは他の)euidで動作します。 外部からのアクセスはすべてwww-dataのeuidで動いている子プロセスで動作しているので、 万が一、外部からの入力によりapache誤った動作をしても、 その影響範囲を無制限にはしない(root権限ではない)ようにしています。
RUID/RGID、EUID/EGID、SUID/SGIDを上手に変更することによって、どのユーザ権限で、
あるいはどのグループ権限でプロセスを動かし、適切にファイルや資源にアクセスできるようになることで、
セキュリティを保つことができるようになります。
これらの値のセットにはルールがあるので、全部はかけないですが、典型的なものを書き出してみます。
- RUID / EUID / SUIDの設定ルール
- RUID の値を EUID にセットできる
- EUID の値を RUID にセットできる
- 実行時のEUIDがSUIDにコピーされていて、SUIDの値をEUIDにセットできる
- rootはRUIDもEUIDも自由にセットできる
このように実行時のユーザIDを変えることができ、また一般ユーザでも実行ファイルに権限が附加されていれば、
root権限でプロセスを動かすこともできるなどかなり複雑な権限のコントロールが可能です。
もちろん、Linuxがコントロールが可能であることと、
アプリケーションがきちんと矛盾なく利用できるように設計できることとはまったく別のことです。
アプリケーションの設計が正しくなかったり、実装で間違えていると、セキュリティ侵害が発生することはいうまでもありません。
パスワードファイル
ユーザIDとアカウント名を対応させているのがパスワードファイル /etc/passwdです。パスワードファイルのフォーマットは次の通りです。
- パスワードエントリのフォーマットのフィールドは":"で区切られる
- アカウント名 : ログイン時に使用するアカウント名
- パスワード : パスワードをハッシュ値に置き換えたもの
- ユーザID : ユーザを認識するための数値
- グループID : グループを認識するための数値
- コメントフィールド : 名前等の情報を記述するフィールド
- ホームディレクトリ : ホームディレクトリ
- シェルパス : 利用するシェルのパス、もしくはシェルに相当するコマンド
/etc/passwd の エントリー例 hironobu:x:1825:2000:Hironobu SUZUKI,,,:/home/hironobu:/bin/bash
このエントリー例は実際運用しているシステムのパスワードファイルから抜き出したものです。
パスワードのフィールドは"x"が入っています。
これは利用しているシステムがシャドーパスワードを導入しているからです。
元々のパスワードファイルには2つの情報が入っています。
一つは公開して誰でも知って良い情報、もう一つは知られてはいけない情報です。
その知られてはいけない情報とはパスワードの情報です。
パスワードの保管
もちろんこのパスワードは、すでに一方向性ハッシュ関数によって撹拌されている値となってなっています。 したがって、パスワードファイルの中にあるすでに撹拌されているパスワードの値だけ持っていても、 そこから元のパスワードを逆算することはできません。 いろいろな入力値を一方向性ハッシュ関数に与えて、 その出力結果と手元にあるパスワードファイルの内容とを比較する方法、 つまり、総当たり攻撃でしか探すことはできません。
実際のパスワードの生成は入力された文字列にシステムが用意したSalt(塩)と呼ぶ初期値を加えたものを一方向性ハッシュ関数に与え、 何度か繰り返し計算をしてビットのパターンを何度も撹拌します。 一方向性ハッシュ関数には、暗号化するためのDESを一方向性ハッシュ関数として代用するもの(UNIX オリジナルの方法)、 一方向性ハッシュ関数MD5やSHA1を使うものがあります。 DESを使う場合は25回繰り返して計算します。 一方向性ハッシュ関数を使う場合は最低1000回繰り返して計算します。 [1] 現在のGNU/Linuxで標準的に使われるパスワード認証のための環境Linux-PAMではMD5/SHA1を使っての撹拌が行われています。 いずれも暗号学的には十分な強度が得られていると言えます。
撹拌のモデル (Cipher-Block-Chain方式) +----------+ V |(回数分) パスワード---->[ハッシュ関数]-->+----------> 暗号化されたパスワード
- 補足
- 2010年12月現在最新であるglibc2.9 をチェックすると、一方向性ハッシュ関数にMD5、SHA256、SHA512が使えるようになっています。
しかし、ある文字列を暗号化して、その出力をパスワードファイルの中にある変換後のパスワードと比較することはできます。
かくして、大量の文字列を処理し、パスワードと同じ文字列を探すことが可能になります。
そこで変換後のパスワードを一般ユーザが直接は参照できない別ファイルに取っておき、
認証するコマンドやメンテナンスのコマンドのみがアクセスできるようにしました。これがシャドーパスワードです。
$ ls -l /etc/shadow -rw-r----- 1 root shadow 789 Oct 22 2003 /etc/shadow $ ls -l /usr/bin/passwd -rwsr-xr-x 1 root root 24616 Nov 3 04:56 /usr/bin/passwd $ ls -l /usr/bin | grep shadow -rwxr-sr-x 1 root shadow 32584 Nov 3 04:56 chage -rwxr-sr-x 1 root shadow 15976 Nov 3 04:56 expiry -rwxr-sr-x 1 root shadow 6628 Jun 28 05:20 kcheckpass
ACL (作業中)
脚注
- ↑ 暗号学的には繰り返す必要はありません。
目次へ