断っておきますが、私はコンピュータセキュリティの専門家ではありません。 しかしセキュリティに関して多少は役に立つアドバイスをすることがで きると思います。でも注意して下さい。ここに書いてあることは NFS の問 題をすべてリストアップしたものではないのです。もしここに書いてあること を実行しただけで「もう安心だ」と思った方は、とんだお人好しというもので す。「幸運を呼ぶツボ」とかを売りつけられないように気を付けた方が良いで すよ :-)。
以下のような状況なら、この章の内容は必要ありません:あなたのホスト が所属しているのが閉じたネットワークで、そこにいる全てのユーザは 信用がおけ、そうでない人はネットワーク上のマシンにアクセスできないよう になっている場合です。つまりネットワークに対するダイアルアップ接続は禁 止、他のネットワークにへの接続も禁止 (そのネットのユーザが全員信頼でき て、同様のセキュリティを確保している場合は別) です。偏執に過ぎると思 いますか?全然そんなことはないんですよ。これはセキュリティに関するごく 基本的な考え方に過ぎません。それに、覚えておいて下さい、私がこれから述 べることはごく基本的なことなのです。安全なサイトを構築するには、 熱心で知識が深く、潜在的なセキュリティ上の問題点に関する最新情報の入手 先を知っているような管理者が不可欠です。
NFS の基本的な問題点は、特に指定をしなければクライアントとサーバが お互いを信頼しあってしまうところにあります。これはまずいわけで、例えば サーバの root アカウントが破られたら、クライアントの root アカウントを 破るのも非常に簡単になってしまうわけです (逆もまたしかり)。この問題を 避ける方法はいくつかあり、後で説明する予定です。
CERT のセキュリティに関する勧告を読んでおくようにしましょう。この文 書の以下のほとんども、CERT が勧告した内容を扱っています。最新の勧告の リストは ftp.cert.org:/01-README で見ることができます。 NFS 関連の勧告を以下にいくつか挙げておきます。
CA-91:21.SunOS.NFS.Jumbo.and.fsirand 12/06/91 Vulnerabilities concerning Sun Microsystems, Inc. (Sun) Network File System (NFS) and the fsirand program. These vulnerabilities affect SunOS versions 4.1.1, 4.1, and 4.0.3 on all architectures. Patches are available for SunOS 4.1.1. An initial patch for SunOS 4.1 NFS is also available. Sun will be providing complete patches for SunOS 4.1 and SunOS 4.0.3 at a later date. CA-94:15.NFS.Vulnerabilities 12/19/94 This advisory describes security measures to guard against several vulnerabilities in the Network File System (NFS). The advisory was prompted by an increase in root compromises by intruders using tools to exploit the vulnerabilities. CA-96.08.pcnfsd 04/18/96 This advisory describes a vulnerability in the pcnfsd program (also known as rpc.pcnfsd). A patch is included.
クライアント側では、サーバを信頼しすぎないように設定することが可能
で、これはマウント時のオプションで指定します。例えば NFS ファイルシス
テムにある suid されたプログラムを動作させないようにするには
nosuid
オプションを使います。これは良い設定で、NFS マウントする全
てのディスクに導入を考えるべきだと思います。これを用いないと、サーバの
root ユーザがクライアントでも root 権限を奪うことができてしまいます。
suid プログラムをサーバのファイルシステムに作り、クライアントに一般ユー
ザでログインして先ほどの suid プログラムを実行すれば... おわかりですね?
マウントしたファイルシステム上のファイルの実行をすべて禁止することもで
きます。これには noexec
オプションを用います。ただ、これは実際に
は nosuid
に比べてだいぶ不便になってしまうでしょう。どんなファイ
ルシステムにも実行しなければならないスクリプトやプログラムの類がいくつ
かは入っているでしょうから。これらのオプションは /etc/fstab
のオプションの列に、 rsize
や wsize
などと一緒にコンマで区切っ
て記述します。
サーバ側では、クライアントの root アカウントを信頼しないように設定
することができます。これには exports
に記述する際、
root_squash
オプションを用います。
/mn/eris/local apollon(rw,root_squash)
こうすると、クライアントで UID 0 のユーザがファイルにアクセス (read,
write, delete) しようとすると、サーバは UID をサーバにおける
"nobody" アカウントのものと置き換えます。つまりサーバの
root だけにアクセスや変更が許されているファイルに対して、クライアント
の root がアクセスや変更を行うことができなくなるのです。これも良い設定
で、 export する全てのファイルシステムに root_squash
を用いるべき
だと思います。「でもクライアントの root ユーザは `su' を使って他のユー
ザになって、そのユーザのファイルを変更できちゃうじゃないですか!」と言
う意見があるかもしれません。その通り、それが Unix や NFS の流儀なので
す。この意見には重要な側面があります。重要なバイナリやファイルなどは
root
によって保有されるべきで、 bin
などの root 以外のアカウ
ントにするべきではありません。なぜならクライアントの root ユーザがアク
セスできないのはサーバの root アカウントのファイルだけだからです。
nfsd の man ページには他にも何種類かの排他オプションが記述されています。
これらを用いれば、好きな (あるいは嫌いな) クライアントユーザを信頼しな
いように設定できます。また UID や GID の範囲によって排他機能を設定する
こともオプションで指定できます。これは Linux の nfsd の man ページに
記述されています。
root_squash
は実は Linux の NFSd ではデフォルトになっています。
ファイルシステムへの root のアクセスを許可するには no_root_squash
を指定して下さい。
もう一つ重要なことは、 nfsd に対する特権ポートからの接続要求がチェッ クされているかどうかを確認しておくことです。もしクライアントからの要求 をどんなポートからでも受け入れてしまうと、 NFS プロトコルを話す適当な プログラムを用いて、特権を持たないクライアントユーザが他のユーザに成り すますことができてしまいます (このようなプログラムはインターネットで容 易に入手できます)。 Linux の nfsd はデフォルトでこのチェックをするよう になっていますが、他の OS では手動でこのチェックを指定しなければならな いかもしれません。この作業はその OS の nfsd の man ページに記述されて いるはずです。
最後にもう一つ。ファイルシステムを `localhost' や 127.0.0.1 に対し て export してはなりません。私を信じて下さい。
ベーシックなポートマッパと nfsd の組み合わせには設計上の問題があり、 NFS サーバのファイルへのアクセスが特権無しに可能になってしまっていました。 幸いなことに、ほとんどの Linux ディストリビューションが用いている ポートマッパは、この攻撃に対して比較的安全になっています。 また二つのファイルを用いたアクセスリストを設定することによって、 さらに安全にできます。
Linux ディストリビューションは、すべて同じではありません。
最近更新されたように見えるディストリビューションでも、
安全なポートマッパを使っていないことがあります。
この危険性が指摘されたのは何年も前のことで、
既に常識となっているはずなんですけど。
少なくとも一つのディストリビューションでは、
安全なポートマッパの man ページが入っているにもかかわらず、
実際のポートマッパは安全なものではありませんでした。
ポートマッパが安全なものかどうかをチェックするためには、
strings(1) コマンドを実行し、その出力に関連するファイル名が含まれているか、
具体的には /etc/hosts.deny
と /etc/hosts.allow
が含まれているかを調べるのが簡単です。お使いのポートマッパが
/usr/sbin/portmap
でしたら、これを行うには
strings /usr/sbin/portmap | grep hosts
というコマンドを
実行します。私のマシンでは結果は以下のようになります。
/etc/hosts.allow /etc/hosts.deny @(#) hosts_ctl.c 1.4 94/12/28 17:42:27 @(#) hosts_access.c 1.20 96/02/11 17:01:27
さて、設定を行うには、まず /etc/hosts.deny
を編集します。
以下の行を書き込みます。
portmap: ALL
こうすると全てのアクセスを受け付けなくなります。
このようにして閉じているあいだ、 rpcinfo -p
を実行し、
ポートマッパが実際にこのファイルを読んで、その記述に従っているかを
チェックしてみましょう。 rpcinfo
はなんの出力も出さないか、
あるいはエラーメッセージを出すでしょう。ポートマッパの再起動は
必要ないはずです。
ポートマッパを誰からも閉じてしまうのはちょっと極端にすぎるので、
/etc/hosts.allow
を編集してポートを再び開けることになります。
まずどのクライアントに開けるかを決める必要があります。
サーバのポートマッパにアクセスする必要のあるマシンをリストアップします。
しっかりと設定されたシステムでは、ポートマッパのあらゆるポートに
アクセスが必要なマシンというのは非常に少ないはずです。ポートマッパは
nfsd と mountd、 ypbind/ypserv, pcnfsd, そして ruptime や rusers な
どの 'r' コマンド群を管理します。このうち nfsd と mountd,
ypbind/ypserv そして pcnfsd のみが問題の対象となるものです。
ホストマシンのサービスにアクセスが必要なマシンには
許可を与えなければなりません。例えばサーバのアドレスが
129.240.223.254 で、サブネット 129.240.223.0 にある
クライアントホストにアクセス許可を与えるとします
(これは networking HOWTO と同じ例です。
必要があったら networking HOWTO をもう一度見に行って、
あなたの脳のメモリをリフレッシュして下さい)。
この場合は hosts.allow
に以下のように書きます。
portmap: 129.240.223.0/255.255.255.0
これは route
コマンドで用いたネットワークアドレス及び
ifconfig
で用いたサブネットマスクと同じです。この場合 eth0
デバイスに対する ifconfig
の結果は以下のようになっているはずです。
... eth0 Link encap:10Mbps Ethernet HWaddr 00:60:8C:96:D5:56 inet addr:129.240.223.254 Bcast:129.240.223.255 Mask:255.255.255.0 UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:360315 errors:0 dropped:0 overruns:0 TX packets:179274 errors:0 dropped:0 overruns:0 Interrupt:10 Base address:0x320 ...
同様に netstat -rn
とすると以下のようになるはずです。
Kernel routing table Destination Gateway Genmask Flags Metric Ref Use Iface ... 129.240.223.0 0.0.0.0 255.255.255.0 U 0 0 174412 eth0 ...
(先頭の列はネットワークアドレスになります)
hosts.deny
と hosts.allow
ファイルに関しては同名の man ペー
ジに記述があります。
訳注: 訳者のところでは "man 5 hosts_access"
でした。
重要: portmap
の行には IP 番号以外のものは書かないで下さ
い。ホストネームの問い合わせは間接的にポートマッパを呼び出すことがあり、
するとまたホストネームの問い合わせが生じてポートマッパが呼び出されホス
トネームの問い合わせが...
以上であなたのサーバは随分しっかりしたはずです。最後の問題は (そう、 最後の!)、信頼しているマシンで root が破られた場合(あるいは MS-DOS がブートされた場合) くらいです。このとき root 権限を利用すると 信頼したポートを通して他のユーザに成りすますような要求を出すことが可能 になってしまいます。
ルータやファイアウォールを用いて NFS やポートマッパのポートを塞ぐのは
非常に良い考えです。 nfsd は通常ポート 2049 の tcp/udp を用います。ポー
トマッパはポート 111 の tcp/udp、 mountd は 745 と 747 の tcp/udp を使
います。これらのポートは rpcinfo -p
で調べる事ができます。
逆に NFS にファイアウォールを越えさせたい場合は、最近の nfsd や mountd にあるオプションを使って特定の (非標準な) ポートを用いるようにし、その ポートをファイアウォールで開ければ良いでしょう。
hosts.allow/deny
, root_squash
, nosuid
そして
portmapper/nfs ソフトの特権ポート関連の機能を用いれば、
現在知られているポートマッパと NFS に関連したほとんどの問題に対処する
ことができ、少なくとも多少は安心することができます。しかし
/home
や /var/spool/mail
が NFS マウントされていると、
あなたのネットワークへの侵入者は .forward
やメールボックスのファ
イルに特殊なコマンドを埋め込んでしまうことができます。同じ理由から、
PGP の秘密鍵を NFS アクセスできるようにするべきではありません。あるい
は少なくとも危険性を知っていなければなりません (今や知ったわけですが)。
NFS とポートマッパは複雑なシステムの組み合わせからなっているので、 将来にわたって基本設計や実装にバグが発見されないとは限りません。あるい は現時点においても穴が存在していて、誰かが悪用しているかもしれないので す。まあそれが人生と言うものです。このように物事に遅れないためには、少 なくとも comp.os.linux.announce や comp.security.announce などには目を通しておく必要があるでしょう。