マシンがたくさん設置できる場合は, 侵入されても構わない犠牲マシンを置き, 対外サービスは主に犠牲マシン上で提供するようにする。 犠牲マシンは踏み台として利用されないようにするため, 犠牲マシンから他のマシンへ絶対に侵入出来ないようにしておく。 間にルーターを置いて犠牲マシンからのパケットを すべて遮断するのが安全確実である(図6)。
こうすることにより, 万一侵入されても被害を犠牲マシンだけに限定することが可能になり, 復旧作業が容易になる。 犠牲マシンのハード・ディスクの内容をどこか安全な場所へ保存しておけば, 侵入経路をふさぎ次第即座に元の状態へ戻すことも可能である。
犠牲マシンをサービスごとに設置できればそれが理想なのであるが, 個人でインターネットに接続する場合, 何台もマシンを動かしておくわけにはいかない。 第一, 電気代がばかにならないし, 狭い家だとマシンを設置している部屋で寝ることになるわけで, 騒音も無視できない。 1台のマシンで被害を限定するためのツールがchrootである。
chroot を使うと, 任意のディレクトリをルート・ディレクトリに設定して サーバー・プログラムを実行できる。 こうするとサーバー・プログラムは設定されたルート・ディレクトリの外にある ディレクトリにアクセスすることができない。 もちろんルート・ディレクトリを元のルートに戻すことは不可能である (カーネルにバグがなければ。(図7))。
したがってこのサーバー・プログラムが侵入に利用されたとしても, 侵入者が自由にアクセスできるのはルート・ディレクトリとして設定された ディレクトリの中だけであり, もしこのディレクトリが, sh やperl など侵入者が喜びそうなものは一切置かないパーティションであれば 被害をこのパーティション内に限定することができる。
例えば, 不特定多数にサービスを行なうための犠牲パーティション /alt-root を作り, そこにインストールした http サーバー・プログラム(図8)を立ち上げるには, 次のように実行すればよい。
犠牲「パーティション」と書いたが, /alt-root はパーティションでなく普通のディレクトリであってもよい。 ただしその場合, 侵入者が /alt-root 下に大量のファイルを置いて,/ alt-root を含むパーティション(この場合はルート・パーティション)をあふれさせ, マシンの他の機能に影響を及ぼすことが可能になってしまう。 であるから, chroot する先はあふれてもあまり困らないパーティションにすべきである。
さて, 犠牲パーティションである /alt-root には, httpd の実行に必要な最低限のファイル/ディレクトリだけを整えておく。 もしCGI の実行にどうしても perl が必要なら /alt-root/bin に インストールしても良いが, perl のような汎用インタープリタは侵入者にとっても非常に便利なツールである, ということを忘れないでほしい。 もし CGI のプログラムをすべてC言語等で書くことが可能ならそうすべきである。
/alt-root/etc/passwd 等は, /etc/passwd 等と同じにする必要はない。 httpd の実行に必要な内容に限定すべきであり, もちろんパスワード・フィールドは「*」などで埋めておく。
犠牲パーティションを作ることは難しいことではないが, 1つ注意すべき点がある。 それはsyslog の扱いである。 多くのサーバー・プログラムは /dev/log へlog を出力する。 /dev/log はunix-domain socket と呼ばれる特殊ファイルで, サーバー・プログラムが書き出した log データをsyslogd が/dev/log から読み込み, /etc/syslog.conf の設定にしたがって/var/adm/syslog 等のlog ファイルへ出力する。
当然, /alt-root へ chroot してから実行したサーバー・プログラムは /alt-root/dev/log に log を出力しようとするので, syslogd は /dev/log と /alt-root/dev/log の両方からlog を読み込む必要がある。 犠牲パーティションが複数ある場合は, それぞれのパーティションの /dev/log を読まなければならない。 sysklogd-1.3-31 に含まれている syslogd は -a オプションで読み込む unix-domain socket を19個まで追加できる。 例えば次のように syslogd を実行すれば良い。
古いディストリビューションを使っている場合, syslogd が-a オプションをサポートしていないかも知れない。 実は, 私が犠牲パーティションを使ったサーバーを立ち上げた時は sysklogd-1.3-25 が 最新バージョンで, この時点では -a オプションがサポートされておらず, syslogd が読み込める unix-domain socket は1つだけだった。 仕方ないので syslogd.c に手を加えて使っていたのだが, 1998年10月に named を犠牲パーティションで走らせるために -a オプションがサポートされた。
(最後の砦)
本稿は日経Linux 創刊 2 号 (1999 年 11 月号) に掲載された、 特集 2: Linux サーバのセキュリティを高める, PART 2「フリーの定番ソフトを利用した 4 段階 Linux サーバ防御法 ---4 つの砦でクラッカーを撃退せよ---」を日経BP 社の許可を得て転載したものです。
Copyright(C)1999 by 仙石浩明 <sengoku@gcd.org>
無断転載を禁じます