LIDS Part3

面 和毅

LIDS Part3



ファイル制限

Linux では、ファイル制限として、

  1. 通常のUnix でのファイル制限。chmod , chown で管理する。
  2. ext2(ext3) ファイルシステム上のファイル制限。chattr で管理する。
が通常使用されています。LIDS はオリジナルのファイル制限を提供します。



LIDS でのACL

LIDS では、VFS(Virtual File System) レイヤーに統合されている、カーネルに 直結しているACL を使用します。これを用いているため、ファイルシステムの種 類(ext2, ext3, reiserFS) に関わらず、同じACL が使えると言うことになりま す。

また、NFS でマウントしたパーティションに対しても、ACL が適用できます。


NFS でのACL の例

例を見てみましょう。

NFS ServerとNFS クライアントを用意します。NFS Server からは、RW(Read, Write)でexport し、クライアントもRW でマウントします。組み合わせは、

NFS Server ReadOnly NFS Server Write
NFS Client ReadOnly NFS Client ReadOnly
NFS Server ReadOnly NFS Server Write
NFS Client Write NFS Client Write
の四通りです。Server, Client が共にWrite になっている場合は、 通常のNFS と同じですので、それ以外の3つで調べてみましょう。

NFS サーバーは/home/omok/src をエクスポートしていて、NFS クライアントは それを/disk にマウントしているとします。


Server RO - Client Write

図 1: ServerはLIDSによりRO, ClientはLIDSの制限は掛かっていない
\includegraphics[width=14cm,clip]{/home/omok/doc/koedo_jan_2004/lidsnfs-lids.eps}
この状態で、NFS Server上で/home/omok/srcディレクトリ以下にm, mmm と いうファイルを、touch コマンドで作成しようとすると、下のエラーが出て、 ファイルを作成できません。
NFS-Server)

Nov 28 12:56:35 nemesis rpc.mountd: authenticated mount request from 
lids.internal.honto.info:625 for /home/omok/src (/home/omok/src) 
Nov 28 12:57:57 nemesis kernel: LIDS: touch (dev 3:68 inode 289135) 
pid 2345 ppid 2302 uid/gid (0/0) on (pts) : Attempt to open mmm for 
writing,flag=35138 
Nov 28 12:57:59 nemesis kernel: LIDS: touch (dev 3:68 inode 289135) 
pid 2346 ppid 2302 uid/gid (0/0) on (pts) : Attempt to open m for 
writing,flag=35138  - logging disabled for (60)s

しかし、NFS クライアント上で/disk 以下にmm というファイルは作成すること が出来ます。

NFS-Client)

[root@localhost src]# touch mm


Server RO - Client RO

図 2: ServerはLIDSによりRO, ClientもLIDSによりRO
\includegraphics[width=14cm,clip]{/home/omok/doc/koedo_jan_2004/lids-lidsdi.eps}
この状態で、NFS Server上で/home/omok/srcディレクトリ以下にo, ooo と いうファイルを、touch コマンドで作成しようとすると、下のエラーが出て、 ファイルを作成できません。

NFS-Server)

Nov 28 13:07:31 nemesis kernel: LIDS: touch (dev 3:68 inode 289135) 
pid 2351 ppid 2302 uid/gid (0/0) on (pts) : Attempt to open o for 
writing,flag=35138 
Nov 28 13:07:34 nemesis kernel: LIDS: touch (dev 3:68 inode 289135)
pid 2352 ppid 2302 uid/gid (0/0) on (pts) : Attempt to open ooo for
writing,flag=35138  - logging disabled for (60)s
同様に、NFS クライアント上で/disk 以下にoo というファイルを、touch コマンドで作成しようとすると、下のエラーが出て、ファイルを作成でき ません。
NFS-Client)

Nov 28 13:08:26 lids kernel: LIDS: touch (dev 3:1 inode 16647) 
pid 1372 ppid 1153 uid/gid (0/0) on (pts) : Attempt to open oo 
for writing,flag=35138


Server Write - Client RO

図 3: ServerはLIDSの制限は掛かっていない、ClientはLIDSによりRO
\includegraphics[width=14cm,clip]{/home/omok/doc/koedo_jan_2004/lidsnonfs-lidsho.eps}
この状態では、NFS Server上で/home/omok/srcディレクトリ以下にp, ppp と いうファイルを、touch コマンドで作成できます。

NFS-Server)

[root@nemesis src]# touch p 
[root@nemesis src]# touch ppp
しかし、NFS クライアント上で/disk 以下にpp というファイルを、touch コマンドで作成しようとすると、下のエラーが出て、ファイルを作成でき ません。

NFS-Client)

Nov 28 13:14:21 lids kernel: LIDS: touch (dev 3:1 inode 16647)
pid 1375 ppid 1153 uid/gid (0/0) on (pts) : Attempt to open pp 
for writing,flag=35138


LIDS でのファイル制限

LIDS で設定できるACL は、次の四つになります。

  1. DENY - オブジェクトへのアクセスは完全にDENY になり、プログラムが アクセスしようとしても、見付けることすら出来なくなります。
  2. READONLY - オブジェクトはRead Only になり、変更などは出来なくなります。
  3. APPEND - オブジェクトはREAD 及びAppend(追加) が出来るようになりま す。この権限は、システムログなど、通常編集はしないが書き足され続けて 行くファイルに対して、非常に便利です。
  4. WRITE - この権限を与えられたオブジェクトは、何でも出来る状態、 つまりLIDS を適用していない状態と同じになります。



LIDS ACL の例

LIDS ACL は、ファイルに対しても、ディレクトリに対しても適用することが出 来ます。ディレクトリに対して適用した場合には、そのディレクトリ内に入って いる全てのファイル/ディレクトリに対して適用されます。ACL を適用するには、 lidsconfコマンドを用いて、次のように記述します。

lfs# lidsconf -A -o /etc -j READONLY
上記のコマンドにより、/etc 以下をRead Onlyにして保護することが出来ます。 上記設定の後、
lfs# lidsadm -S -- +RELOAD_CONF
として設定を更新してから、LIDS を有効にすると、/etc ディレクトリ以下が書 き込み不能になっています。例として、/etc/testfile を作成しようとすると
#touch /etc/testfile
cp: cannot create regular file 'testfile': Operation not permitted
となって、作成が出来ない状態になっています。

しかし、/etc ディレクトリ以下の、ある特定のファイルのみを隠してしまいた い(DENY にする)場合があるとします。逆に、あるファイルに対してのみ、書き 込みを許可したいようなときがあると思います。そのような時には、そのディレ クトリイ以下の、個々のオブジェクトに対して権限を与えて行きます。

例として、/etc/shadow ファイルを隠し、/etc/hoge ファイルを書き込みが出来 るようにするとします。/etc/shadow ファイルを隠しておけば、万が一、root アカウン トが乗っ取られたとしても、他のパスワードを推定されにくいので安全です。

lfs# lidsconf -A -o /etc -j READONLY
lfs# lidsconf -A -o /etc/shadow -j DENY
lfs# lidsconf -A -o /etc/hoge -j WRITE

とすれば、/etc をRead Only に保ちつつ、/etc/hoge ファイルのみを変更するこ とが可能になります。

しかし、このままでは、例えばSSH を用いてシステムにログインをしたいとして も、sshd プログラムから、/etc/shadow ファイルが見えないため、 ログインができない状態になってしまいます。

そこで、LIDS では、各プログラム(サブジェクトと言います)により、そのオブジェクトに 対しての動作を細かく設定することが出来ます。

上記のSSH では、

lfs# lidsconf -A -o /etc/shadow -j DENY
lfs# lidsconf -A -s /usr/sbin/sshd -o /etc/shadow -j READONLY

とすれば、shadow ファイルは通常でDENY になり、sshd からは、読み出しのみ でその他の(書き込みなどの)権限を持っていないので、必要最小限の権限をプロ グラムに与えられた事になります。

また、LIDS では、このとき、sshd プログラムも保護されている必要があります。 例えば、/usr ディレクトリや、/usr/sbin ディレクトリがREADONLY で保護され ていないと、上記のACL を設定するときに、エラーが出て、設定出来ません。

したがって、より詳しく書くと、

lfs# lidsconf -A -o /etc/shadow -j DENY
lfs# lidsconf -A -o /usr -j READONLY
lfs# lidsconf -A -s /usr/sbin/sshd -o /etc/shadow -j READONLY

あるいは、より限定的に書けば

lfs# lidsconf -A -o /etc/shadow -j DENY
lfs# lidsconf -A -o /usr/sbin/sshd -j READONLY
lfs# lidsconf -A -s /usr/sbin/sshd -o /etc/shadow -j READONLY

となっている必要があります。

「保護されているプログラムのみが、保護されているファイルにアクセスできる」 ということです。

その他の例として、Web サーバーを設定するときは、

lfs# lidsconf -A -o /usr -j READONLY
lfs# lidsconf -A -o /var/www/htdocs -j DENY
lfs# lidsconf -A -s /usr/local/apache/bin/httpd -o /var/www/htdocs -j READONLY
lfs# lidsconf -A -s /usr/local/apache/bin/httpd -o /var/www/cgi-bin -j READONLY

として、httpd のみに/var/www/htdocs 以下の読み出しを許可 し、他のプログラムに対しては隠すことが出来ます。



LIDS ACL の実際の動作

では、LIDS は、どのような動作でACL を適用して行くのでしょうか?

LIDS で保護されているオブジェクトに対して、なんらかのアクションが行われ たとします。そのときのLIDS 上での処理の流れをフローチャートで示します。

LIDS が有効になっているシステム上で、あるプロセスからオブジェクトにたい してのアクションがあったとします。

このとき、

  1. LIDS はデフォルトのルールをチェックし、そのアクションが許可されて いるかどうかを調べる。もし許可されているなら、その動作を許可する。 それ以外の場合には、次に飛ぶ
  2. プロセスが、そのアクションを行うようなACL を設定されているかどうか を調べる。もし無ければ、リジェクトする。それ以外では、許可する。

となります。

図 4: LIDS ACL上での処理の流れ
\includegraphics[width=11cm,clip]{/home/omok/doc/koedo_jan_2004/lids_acl_flowchart.eps}



LIDS ACL とi-node

前回のLIDS 設定ファイルのうち、lids.conf ファイル内に、i-node が 書かれていたことを思いだしてください。LIDS では、ACL の管理にi-node 番号 を用いています。

したがって、ファイルを更新した際にi-node が変更されてしまうと、ACL が壊 れてしまいます。そのため、ファイルの変更などを行った後には、

lfs# lidsconf -U

でLIDS のi-node テーブルをアップデートしてあげる必要があります。この後、

lfs# lidsadm -S -- +RELOAD_CONF

でLIDS 設定ファイルを再読込みしてあげる必要があります。


Linux のCapablity について

Linux のCapability については、
(1/3):http://japan.linux.com/security/03/08/06/0941214.shtml(ケーパビリティとケーパビリティバウンディングセット)
(2/3):http://japan.linux.com/security/03/08/20/0750202.shtml(プロセスケーパビリティ)
(3/3):http://japan.linux.com/security/03/10/06/0723217.shtml(プロセスケーパビリティを調整する)
に詳しく紹介されています。 プロセスに対して、特権を細かく分けて与えることにより、プロセスが必要最小 限の特権を持つようにして安全性を高めるものです。この、細分化された特権を、 「ケーパビリティ」と言います。



Linux でデフォルトで定義されているCapablity

CAP_CHOWN
ファイルのUID とGID を任意に変更することを許可する
CAP_DAC_OVERRIDE
ファイルの読込み、書き込みと実行権限のチェックをバイパスする
(DAC = "discretionary access control(任意のアクセス制御)")。
CAP_DAC_READ_SEARCH
ファイルの読込み権限のチェックとディレクトリの読込みおよび
実行権限のチェックをバイパスする。
CAP_FOWNER
通常、
CAP_DAC_OVERRIDE
と
CAP_DAC_READ_SEARCH
がカバーしてる操作をのぞいて、プロセスのファイルシステムUID が
ファイルのUID (例えば、
utime (2))
にマッチするかどうかが要求される操作に関する権限チェックをバイパスし、
ファイル削除の際にスティッキービットを無視する。
CAP_FSETID
ファイルが変更されたときにset-user-ID とset-group-ID ビットをクリア
しない-
ファイルシステムにマッチしないGID やプロセス呼出の際に付加されたGID の
ファイルに対して、set-group-ID ビットの設定を許可する。
CAP_IPC_LOCK
メモリーロック( mlock (2), mlockall (2), shmctl (2))
を許可する。
CAP_IPC_OWNER
System V IPC オブジェクトの操作に対しての権限チェックをバイパスする。
CAP_KILL
シグナル送信に対する権限チェックをバイパスする(kill (2)) 参照。
CAP_LEASE
(Linux 2.4 以前) 任意のファイルに対して、確立させる為の
ファイルリースを許可する(fcntl (2) 参照)。
CAP_LINUX_IMMUTABLE
EXT2_APPEND_FL と EXT2_IMMUTABLE_FL の、ext2 に関する拡張されたファイル属性の設定を許可する。
CAP_MKNOD
(Linux 2.4 以前) mknod (2)
を使用してスペシャルファイルを作成することを許可する。
CAP_NET_ADMIN
様々なネットワークに関係する操作(例えば、特権を持ったソケット
オプションの設定や、マルチキャストを可能にすることや、インターフェース
の設定や、ルーティングテーブルを変更すること)を許可する。
CAP_NET_BIND_SERVICE
インターネットドメインで予約されているソケットポート番号
(1024 番以下のポート番号)へのバインディングを許可する。
CAP_NET_BROADCAST
ソケットのブロードキャストと、マルチキャストのリスニング
を許可する。
CAP_NET_RAW
RAW ソケットと PACKET ソケットの使用を許可する。
CAP_SETGID
プロセスのGID と追加されたGID リストに対する任意の操作
 を許可する。
Unix ドメインソケットを通して、ソケットの資格をパスしたときに、偽造されたGID を許可する
CAP_SETPCAP
Call 元が持っている許可されたケーパビリティセットを、そ
の他のプロセスに与えたり、プロセスから削除したりする
CAP_SETUID
プロセスUID に対しての任意の操作
( setuid (2), など)
を許可する。
Unix ドメインソケットを通して、ソケットの資格をパスしたときに、偽造されたUID を許可する
CAP_SYS_ADMIN
システム管理用に、下記の操作を許可している
quotactl (2), mount (2), swapon (2) , sethostname (2), setdomainname (2)。 IPC_SET と IPC_RMID は、任意のSystem V IPC オブジェクトに対して、 偽造されたUIDがソケットの資格をパスしたときに、許可している。
CAP_SYS_BOOT
reboot (2) をコールすることを許可する。
CAP_SYS_CHROOT
chroot (2) をコールすることを許可する。
CAP_SYS_MODULE
カーネルモジュールをロード/アンロードすることを許可する。
ケーパビリティバウンディングセットの変更を許可する。
CAP_SYS_NICE
プロセスのnice 値( nice (2), setpriority (2))
の引き上げや、任意のプロセスのnice 値の変更を許可する。
プロセスをコールするときのリアルタイムスケジュールポリシーの設定と、任 意のプロセスに対する ( sched_setscheduler (2), sched_setparam (2)) の優先順位付けを許可する。
CAP_SYS_PACCT
acct (2) のコールを許可する。
CAP_SYS_PTRACE
任意のプロセスに対して、ptrace (2)
を用いたトレースを許可する。
CAP_SYS_RAWIO
I/O ポート操作
( iopl (2), ioperm (2))
を許可する。
CAP_SYS_RESOURCE
以下を許可する
・ext2 ファイルシステム上で、予約されているスペースを使用すること
・ioctl (2) が、ext3 ジャーナルファイルシステムの制御を呼出すこと
・ディスククオーターリミットを無効にすること
・リソースリミット( setrlimit (2) 参照 )の増加
・RLIMIT_NPROCによるリソースリミットを無効にすること
・メッセージキューのリミットmsg_qbytes を/proc/sys/kernel/msgmnb に指定されているものよりも増やすこと ( msgop (2), msgctl (2) を参照)
CAP_SYS_TIME
システムクロックの変更を許可( settimeofday (2), adjtimex (2))
リアルタイム(ハードウェア) クロックの変更を許可する。
CAP_SYS_TTY_CONFIG
vhangup (2) を呼び出すことを許可する。



LIDS で新たに定義されるCapablity

 CAP_HIDDEN
ps コマンドなど、/proc からプロセスを隠すために使用する
CAP_PROTECTED
シグナルからプロセスを保護する
CAP_KILL_PROTECTED
保護されているプログラムにシグナルを送ること
 を許可する(旧CAP_INIT_KILL) 


LIDS でのCapablity 設定

通常のLinux カーネルでのケーパビリティ設定に比べて、LIDS では次の特色を 持っています。
  1. ケーパビリティを無効にするだけでなく、有効にすることが出来る
  2. プロセスを考えること無く、プログラムベースでケーパビリティを設定する ことが出来る
これらにより、LIDS ではシステムに合わせて柔軟にケーパビリティを設定する ことが可能になります。

システムのデフォルトのケーパビリティ

システムでの、デフォルトのケーパビリティは、

/etc/lids/lids.pcap
で設定されています。ファイルの形式は、

[+-]#: ケーパビリティの名前
となっており、インストール直後は次のようになっています(コメントは省略してあります)。

-0:CAP_CHOWN
-1:CAP_DAC_OVERRIDE
-2:CAP_DAC_READ_SEARCH
-3:CAP_FOWNER
-4:CAP_FSETID
-5:CAP_KILL
-6:CAP_SETGID
-7:CAP_SETUID
-8:CAP_SETPCAP
-9:CAP_LINUX_IMMUTABLE
-10:CAP_NET_BIND_SERVICE
-11:CAP_NET_BROADCAST
-12:CAP_NET_ADMIN
-13:CAP_NET_RAW
-14:CAP_IPC_LOCK
-15:CAP_IPC_OWNER
-16:CAP_SYS_MODULE
-17:CAP_SYS_RAWIO
-18:CAP_SYS_CHROOT
-19:CAP_SYS_PTRACE
-20:CAP_SYS_PACCT
-21:CAP_SYS_ADMIN
-22:CAP_SYS_BOOT
-23:CAP_SYS_NICE
-24:CAP_SYS_RESOURCE
-25:CAP_SYS_TIME
-26:CAP_SYS_TTY_CONFIG
-27:CAP_MKNOD
-28:CAP_LEASE
-29:CAP_HIDDEN
-30:CAP_KILL_PROTECTED
-31:CAP_PROTECTED
頭に"-"が付いているものは、そのケーパビリティが無効になっていると 言うことを意味しています。
lidstools をインストールした直後では、全てのケーパビリティが無効になっています。 この状態では、root 権限で走っているプロセスでさえも、どのケーパビリティ も持っていないことになり、例えば

-10:CAP_NET_BIND_SERVICE
になっているので、プロセスが1024 番以下のポート番号へのバインディングを することは出来なくなっています。

ケーパビリティがシステムで有効になるタイミング

lids.cap ファイルが参照されるのは、カーネルを封印するタイミングです。つ まり、カーネルを封印する前に起動されたプログラムに関しては、何もしてい ないときと同じケーパビリティが与えられます。

通常、スタートアップで起動するプログラムに関しては様々なケーパビリティを 必要とするために、カーネル封印後にケーパビリティが有効になるようになって います。


Capablity 設定の例

コンソールからログインするために使うlogin の場合には、 CAP_SETUID とCAP_SETGID がログインするときに必要なケーパビリティです。 また、CAP_SYS_TTYCONFIG 、CAP_CHOWN とCAP_FSETID がtty 関連のために必要で す。したがって、下記のようになります。
lfs# /sbin/lidsconf -A -s /bin/login -o CAP_SETUID -j GRANT
lfs# /sbin/lidsconf -A -s /bin/login -o CAP_SETGID -j GRANT
lfs# /sbin/lidsconf -A -s /bin/login -o CAP_CHOWN -j GRANT
lfs# /sbin/lidsconf -A -s /bin/login -o CAP_FSETID -j GRANT
lfs# /sbin/lidsconf -A -s /bin/login -o CAP_SYS_TTYCONFIG -j GRANT
/bin/su プログラムを使用したい場合には、ファイルACL として
lfs# /sbin/lidsconf -A -o /bin -j READONLY
lfs# /sbin/lidsconf -A -s /bin/su -o /etc/shadow -j READONLY
を設定する他に、
lfs# /sbin/lidsconf -A -s /bin/su -o CAP_SETUID -j GRANT
lfs# /sbin/lidsconf -A -s /bin/su -o CAP_SETGID -j GRANT
を与えてあげる必要があります。

システムを停止するために、

lfs# /sbin/lidsconf -A -s /sbin/init -o CAP_KILL_PROTECTED -j GRANT
lfs# /sbin/lidsconf -A -s /sbin/init -o CAP_KILL -j GRANT

を与えてあげる必要があります。

シリアルからログインするために使うgetty の場合には、 CAP_SETUID とCAP_SETGID がログインするときに必要なケーパビリティです。 また、CAP_FOWNER 、CAP_CHOWN とCAP_DAC_OVERRIDE がtty 関連のために必要で す。したがって、下記のようになります。

lfs# /sbin/lidsconf -A -s /sbin/getty -o CAP_SETUID -j GRANT
lfs# /sbin/lidsconf -A -s /sbin/getty -o CAP_SETGID -j GRANT
lfs# /sbin/lidsconf -A -s /sbin/getty -o CAP_FOWNER -j GRANT
lfs# /sbin/lidsconf -A -s /sbin/getty -o CAP_CHOWN -j GRANT
lfs# /sbin/lidsconf -A -s /sbin/getty -o CAP_DAC_OVERRIDE -j GRANT

X サーバには CAP_SYS_RAWIO 権限が必要です。

lfs# /sbin/lidsconf -A -s /path/to/your/X_server -o CAP_SYS_RAWIO -j GRANT


LIDS での特殊なCapablity

LIDS では、ケーパビリティを独自に拡張しています。 通常のケーパビリティでは、CAP_BIND_NET_SERVICE のケーパビリティを持って いると、1024 番以下の全てのポートに対してバインドが許可されます。しかし、 LIDS では、よりセキュアにするために、バインドできるポートの範囲を制限す ることが出来ます。 たとえば、Apache にポート80 と443 だけを使用させたいときには、
lfs# lidsconf -A -s /usr/local/apache/bin/httpd -o CAP_BIND_NET_SERVICE
80,443 -j GRANT
と指定します。これにより、本当に必要なポートにのみバインドを許可するとい う、きめ細やかな設定が可能になります。 LIDS で新たに定義されたケーパビリティです。このケーパビリティを与えられ たプロセスは、どのような手段によってもプロセスをkill することが出来なくな ります。

これにより、侵入に成功した攻撃者が、syslog や、ログ監視用のツールを止め ることを出来なくすることが出来ます。

LIDS で新たに定義されたケーパビリティです。このケーパビリティを与えられ たプロセスは、CAP_PROTECTED で保護されたプロセスをkill することが出来ま す。 LIDS で新たに定義されたケーパビリティです。このケーパビリティを与えられ たプロセスは、/proc (したがってps 、top など) から見えなくなります。 ただし、プロセスを完全に隠すわけではありません。たとえば、sshd を隠した としても、
netstat -an
を使用すると、何かが22 番をListen していることは、ばれてしまいます。 しかし、snort や、その他のIDSを隠しておくということは、攻撃者に対して ある程度有効な手段でしょう。

次回予告

以上で、今回は終りです。次回は、ACL の継承と、具体的な設定に付いて説明します。

Kazuki Omo 平成16年1月2日