ユーザ権限とアクセス制御

提供:UnixClassWiki
2007年12月6日 (木) 14:37時点におけるHironobu (トーク | 投稿記録)による版 (→‎ACL (作業中))
ナビゲーションに移動 検索に移動

ユーザと権限

おおよそ今時のコンピュータシステムはユーザが利用しようとするにはユーザ 認証を必要とします。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] 現在のLinuxで標準的に使われるパスワード認証のための 環境Linux-PAMではMD5/SHA1を使っての撹拌が行われています。いずれも暗号 学的には十分な強度が得られていると言えます。

 撹拌のモデル (Cipher-Block-Chain方式)
                      +----------+
                      V          |(回数分)
 パスワード---->[ハッシュ関数]-->+----------> 暗号化されたパスワード


しかし、ある文字列を暗号化して、その出力をパスワードファイルの中にある 変換後のパスワードと比較することはできます。かくして、大量の文字列を処 理し、パスワードと同じ文字列を探すことが可能になります。


そこで変換後のパスワードを一般ユーザが直接は参照できない別ファイルに取っ ておき、認証するコマンドやメンテナンスのコマンドのみがアクセスできるよ うにしました。これがシャドーパスワードです。


$ 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 (作業中)

脚注

  1. 暗号学的には繰り返す必要はありません。

目次