Syntax: compartment [options] /full/path/to/program Options: --chroot path chroot to path --user user change UID to this user --group group change GID to this group --init program execute this program before doing anything --cap capset set capset name. You can specify several --verbose be verbose --quiet do no logging (to syslog) |
つまり下記のようにすれば、より安全な anonymous ftp サーバが運用できます。
compartment --chroot /home/ftp --cap CAP_NET_BIND_SERVICE anon-ftpd |
このドキュメントを書いている時点では、まだ未完成で、代表的な Linux ディストリビューションでは利用できません。しかし状況はすぐに変わるでしょう。 このプログラムは、 http://www.suse.de/~marc から からダウンロードできます。
すべての Unix ライクなシステムが POSIX ケイパビリティを実装しているわけでは ない点と PR_SET_KEEPCAPS は現状では Linux 独自の拡張である点に注意してください。 つまり、この解決方法は移植性がありません。 しかし、利用できる環境下でオプションの安全策の単なる 1 つとして利用するなら、 この方法を採用することによって、実際には移植性は損なわれません。 また、Linux カーネルが 2.2 より新しいバージョンなら、低レベルのシステムコール は用意してあります。しかし、利用しやすい C レベルのライブラリをインストール していないディストリビューションもありますので、アプリケーションで使うには ちょっと面倒です。 Linux の POSIX ケイパビリティについてさらに詳しい情報は、 http://linux.kernel.org/pub/linux/libs/security/linux-privs を見てください。
FreeBSD には jail()という関数があり、これで特権を制限しています。 詳しい情報は、 jail documentation を見てください。 特権を制限するのに、特別なツールや機能拡張がたくさんあります。 Section 3.10を見てください。
既知のバグで気をつけなければいけないものに、POSIX ケイパビリティを利用して、 権限の最小化を妨げるものがあります。 このバグは、Linux カーネルの 2.2.0 から 2.2.15 に影響があり、POSIX ケイパビリティを持っている他の Unix ライクなシステムの多くにもおそらく影響が あると思います。 http://www.securityfocus.com にある Bugtraq の id 1322 にさらに詳しい情報 があります。 要約を挙げておきます。
sendmail が使っている解決方法の一つに setuid(getuid())した後には setuid(0) を試みる、というものもあります。通常これは失敗するはずです。 成功したとしても、プログラムは停止してしまうでしょう。 さらに詳しい情報は、http://sendmail.net/?feed=000607linuxbug を見てください。 他のプログラムであれば、短期的には良いアイディアだと思いますが、長期的に みれば、信頼あるシステムへのアップグレードが好ましいのに違いありません。
オペレーティングシステムには、信頼性を複数の層にするコンセプトを持って いるものがあります。たとえば、Multics のリング構造がこれに当たります。 標準的な Unix や Linux には単独のプロセス中で機能毎に複数のレベルで信頼性 を持つ手段を持ち合わせていません。下記のような感じになっています。 カーネルに呼び出しをかけるには特権を上げますが、そのプロセスはたった 1 つの 信頼性のレベルしか持っていません。 これが Java 2 や C#(Java のやり方のまね)、Fluke(セキュリティ強化版 Linux の基盤)の長所になっています。 たとえば、Java 2 はある特定のファイルだけをオープンするパーミッションと いうような、きめの細かいパーミッションを指定できます。 しかし、汎用的なオペレーティングシステムでは、現状一般的にそういった機能を 備えていません。これは近い将来にかわるかもしれません。 Java についての詳しい話は Section 9.6 を見てください。
プログラムが root の特権を獲得できてしまうと、chroot は効果がなくなって しまいます。 たとえば、プログラムが mknod(2)のような関数を呼び出すと、物理メモリが見られる デバイス・ファイルを作成できてしまいます。こうなってしまうと、カーネルメモリを いじってプログラムに望みの特権を与えられます。 root の特権を持ったプログラムが、chroot を抜け出してしまう他の例を http://www.suid.edu/source/breakchroot.c で例示しています。 ここの例を挙げてみます。プログラムがあるファイルディスクリプタをカレント ディレクトリ用にオープンします。サブディレクトリを作り、そこに chroot します。 カレントディレクトリに先程オープンしたカレントディレクトリを設定します。再び カレントディレクトリから上位ディレクトリに cd します(こうすると、現状の chroot の外に出て、実際のファイルシステムの root に移動してしまいます)。そして移動 した先で chroot します。 ここを読むまでに、これらの脆弱性は塞がれているかもしれません。しかし root の 特権は、もともと「特権すべて」を意味しているのは事実で、それを奪い去るのも 困難が伴います。 プログラムが root の特権を継続して必要な場合、chroot()を使用すると少しは 役に立つ、という程度に考えていた方が良いでしょう。 もちろん、プログラムを複数の部分に分けて、少なくともその一部を chroot jail に入れられます。
プロセスが利用できるコンピュータのリソースを最低限にするように配慮して ください。そうすれば、あるプロセスが「めちゃくちゃ」になってもダメージの範囲 が狭くなります。 これは、サービス拒否攻撃を防ぐのに必須の方法です。 ネットワーク系のサーバでは、それぞれのセッションに対して独立したプロセスを 設定するのが一般的なやり方です。それぞれのプロセスはセッションが使える CPU 利用時間等の総量に制限をかけます。 こうすれば、攻撃者がメモリを食い潰すような要求をだしたり、CPU を 100% 使い 切ったりしようとしても、制限が働いて単独のセッションが他のタスクに支障を来す のを防ぎます。 もちろん、攻撃者はたくさんのセッションを張れますが、これは少なくとも攻撃に とって障害となります。 どのように制限をかけるかについては Section 3.6 に詳しい情報が あります(たとえば、ulimit(1))。