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

提供:UnixClassWiki
2015年7月27日 (月) 17:18時点におけるHironobu (トーク | 投稿記録)による版 (→‎グループID利用の方法)
ナビゲーションに移動 検索に移動

ユーザと権限

オペレーティングシステム内部ではユーザの違いをアカウント名ではなく ユーザID(UID / User IDentifier)による数値で認識しています。 またユーザは1つデフォルトのグループID(GID / GroupIDentifier)がつけられています。 そのユーザIDやグループIDが条件に合致するかどうかでユーザに権限があるかどうかを判断しています。


補足
ユーザやグループの追加、更新などオペレーションに関してはユーザやグループの管理を参照してください。


唯一例外的なのはユーザIDが0、グループIDが0のユーザrootです。 スーパーユーザーと呼ばれ、 UNIXにおいてはオールマイティーな権限を持つ特別なユーザです。 管理者権限として説明される場合が多いのですが、 管理者として何かするという表現よりも「オペレーティングシステム上で何でもできてしまう権限」 と説明した方が分かり易いかと思います。


ユーザIDとグループIDによるアクセス制御

オペレーティングシステムの内部では、ユーザは名前で管理されているのではなくユーザID(UID)で管理されています。 たとえばファイルにユーザ(所有者)が設定されていますが、その所有者情報とはファイルの情報(ディレクトリ情報のなかにあるメタ情報)に付加されているユーザIDのことです。 また、プロセスが動作している時には、いずれかのユーザIDとグループIDを持っており、そのユーザIDに付加された権限の範囲内においてプロセスは資源にアクセスできます。 グループID(GID)は、そのグループにユーザが登録されている場合、そのユーザに与えられるグループ権限です。 UNIXの基本的な権限は、このユーザIDの違いによるユーザ権限と、グループIDの違いによるグループ権限の2つから成り立っています。 ファイルやプロセスの資源へのアクセス制御はユーザID・グループID [1] を使っての許可・不許可によって行われるというのが基本的な考え方です。


まずファイルに対するユーザIDとグループIDを見てみましょう。 ファイルには、ユーザIDとグループIDが設定されています。 ユーザID=このファイルの所有者です。 なお、本章の範囲では、所有者とユーザと同じ意味で使っています。 ユーザが自分の所有するファイルの属性を変更し、そのファイルのアクセス権限などをコントロールすることができます。 ただしroot権限だけは例外で、システムのすべてに無制限にアクセスできます。


尚、ユーザIDが数字ではなくユーザ名として表示されるのは、ユーザIDは/etc/passwdで設定されている対応するアカウント名、 グループIDは/etc/groupで設定されている対応するグループ名に変換されて表示されるからです。


基本的なファイルへのアクセス権限は、「読み込み」「書き込み」「実行」です。 ディレクトリの場合は実行の部分の意味が「ディレクトリとしてアクセスできるか」ということとして扱われます。


  • アクセス権限 : 読み込み / 書き込み / 実行
  • ユーザ・所有者(User)に対して : 許可 / 不許可
  • グループ(Group)に対して : 許可 / 不許可
  • それ以外(Other)対して : 許可 / 不許可


 $ 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のグループ権限を持つプロセスから読み書き可能になっています。具体的には、メールサーバなどのプロセスが読み書きできるようになっています。


変更はコマンドchmodを使います。chmodのオプションではユーザ(所有者)はu、グループはg、それ以外の利用者はoという表現を使います。 パーミッションの許可は"+"、パーミッションの不許可は"-"を使います。 chmodのオプションで"go-rw"はグループとその他ユーザからの読み書きは不許可となります。


 $ chmod go-rw memo.txt
 $ ls -l memo.txt 
 -rw-------    1 hironobu hironobu       44 Sep 20 19:17 memo.txt


ユーザ(所有者)、グループ、その他ユーザの読み取り許可・不許可、書き込み許可・不許可、実行の許可・不許可は3ビットで表すので、この部分を8進数で表現することもできます。 その場合"rw-------"はビットの設定がuが110、gが000、oが000となるので、8進数表現をするモードでは600となります。


 $ chmod 600 memo.txt
 $ ls -l memo.txt 
 -rw-------    1 hironobu hironobu       44 Sep 20 19:17 memo.txt

グループ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を使って探してみましょう。


$ find /bin  -perm +a+s -exec ls -l {} \;
-rwsr-xr-x 1 root root 26252 Mar  3  2012 /bin/fusermount
-rwsr-xr-x 1 root root 88760 Mar 30  2012 /bin/mount
-rwsr-xr-x 1 root root 34740 Nov  8  2011 /bin/ping
-rwsr-xr-x 1 root root 39116 Nov  8  2011 /bin/ping6
-rwsr-xr-x 1 root root 31116 Sep 13  2012 /bin/su
-rwsr-xr-x 1 root root 67720 Mar 30  2012 /bin/umount


最初の表示にある-rwsr-x-rxのsがsetuid bitの意味です。 つまり、これらのコマンドは所有者がrootであり、かつ、 このコマンドを動かすとrootの権限で動かすことができるという意味です。 この実行時は、ruidは利用者、euidがrootとなり、 root権限のファイルなどに書き込むことができるようになります。 一般ユーザでも何でもできる権限を手に入れてしまうということで、 このようなプログラムに誤りがあると大きなセキュリティ上の問題になります。

setgid

setgidは、set group id bitの意味です。そのファイルのグループIDと同じ権限で実行できます。

$ find /bin  -perm +g+s -exec ls -l {} \;
....

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がコントロールが可能であることと、 アプリケーションがきちんと矛盾なく利用できるように設計できることとはまったく別のことです。 アプリケーションの設計が正しくなかったり、実装で間違えていると、セキュリティ侵害が発生することはいうまでもありません。

ACL

Access Control Lists(ACL)は元々のUNIXにはないアクセス制御方式で、その仕様に関してはPOSIXで定義されています。Linuxカーネル2.6以降で採用されています。Linuxカーネル2.6以降ではLinuxの主要ファイルシステムで利用可能です。

UNIXでは自分以外のユーザにアクセスを許可する場合は、グループに許可するか、それともすべてのユーザに許可するかの大まかな条件でアクセス制御をしています。一方、ACLではアクセス許可を特定のユーザの単位で、あるいはグループ単位で設定できます。ACLの導入により、これまでのUNIXのアクセス制御よりも複雑な設定をすることが可能になります。

次のようなファイルがあるとします。

$touch foo.txt
$ ls -l foo.txt
-rw-rw-r-- 1 hironobu hironobu 0 Aug 31 08:15 foo.txt

コマンドgetfaclを使ってパーミッションを表示すると次のようになります。

$ getfacl foo.txt 
# file: foo.txt
# owner: hironobu
# group: hironobu
user::rw-
group::rw-
other::r--

次に自分以外のユーザが読み書きできないようにしてみます。

$ chmod go-rw foo.txt
$ ls -l foo.txt
-rw------- 1 hironobu hironobu 0 Aug 31 08:15 foo.txt

この状態でwww-dataユーザのみにfoo.txtの読み込みを許諾するとなると、グループを使う方法だとwww-dataとhironobuだけのグループを作り、そのグループを設定し、グループの読み込みを許可する、といったことをしなければなりません。しかしACLの機能を使えばwww-dataのみに読み込みを許諾することができます。属性を設定にはコマンドsetfaclを使用します。

ACLの設定

コマンドsetfaclはaclをセットするためのものです。ユーザwww-dataに"r"だけ許可をしてみます。

$ setfacl -m user:www-data:r foo.txt 

ではコマンドgetfaclを使って、どう変化したか見てみましょう。

$ getfacl foo.txt
# file: foo.txt
# owner: hironobu
# group: hironobu
user::rw-
user:www-data:r--
group::---
mask::r--
other::---

先ほどの内容から2点変わっているのがわかるはずです。まず1点はuserの表示が増えたこと、そしてmaskという新しい項目ができたことです。maskは所有するユーザ以外に与えることのできる最大限の権限です。この場合はmaskに対して指定していないのでデフォルトの"r"が設定されています。

ここではwww-dataのみですが、複数のユーザに対しても同様に個別の設定をすることができます。

ここではユーザのみに関して説明していますが、グループに対しても複数のグループを割り当てたりすることが可能です。

さらに詳しく知るためには openSUSE [2] やRadHat [3] やTurbolinux [4] などのACLに関する運用ドキュメントが参考になります。


さて、この状態でls -lでファイルのパーミッションの状況をみてみましょう。

% ls -l foo.txt
-rw-r-----+ 1 hironobu hironobu 0 Aug 31 08:15 foo.txt

最後に"+"と表示されているのは、ACLが設定されているということを意味しています。

脚注

  1. 自分のユーザIDやグループIDを確認するにはコマンドidを使う。詳しくはユーザやグループの管理を参照のこと。
  2. openSUSE ドキュメンテーショ 第9章 Linux におけるアクセス制御リスト http://opensuse-man-ja.berlios.de/opensuse-html/cha.security.acls.html
  3. Storage Administration Guide 第19章 アクセス制御リスト https://access.redhat.com/site/documentation/ja-JP/Red_Hat_Enterprise_Linux/6/html/Storage_Administration_Guide/ch-acls.html
  4. Turbolinux 11 Server: ユーザーガイド 第 40章Posix ACL(Access Control List) http://www.turbolinux.co.jp/products/server/11s/user_guide/c15067.html

目次