EN JA
SECURITY(7)
SECURITY(7) FreeBSD Miscellaneous Information Manual SECURITY(7)

名称

securityFreeBSD におけるセキュリティ入門

解説

セキュリティは、システム管理者とともに始まり、システム管理者とともに終る機能です。 BSD マルチユーザシステムは、昔ながらのセキュリティをいくらかは備えていますが、さらなるセキュリティ機構を組み込んで維持していくことで、ユーザを“正直に”し続ける仕事は、システム管理者の最も大きな責務の一つでしょう。マシンは、管理者が設定しただけのセキュリティしか示しません。セキュリティに関する問題は、むしろ、便利さを求める人間との競合問題です。一般に、 UNIX システムは、莫大な数のプロセスを同時に実行させることができ、それも、サーバとして動作するものが多いのです。つまり、外部の何者かが接続してきて、サーバプロセスと会話することができるということなのです。昨日まで使われていたミニコンピュータやメインフレームは、今日ではデスクトップコンピュータが取って代わり、しかも、それらは、ネットワークで結ばれてインターネットと接続されるようになりました。これにより、セキュリティは、昔と比べてはるかに大きな問題となっています。

セキュリティは、タマネギの階層のようなアプローチを通すと最もよく実装できます。手短に言って、やりたいことは、便利さを損ねない程度にできるだけ多くの階層を作り、システムに侵入されていないかを注意深く監視することです。

システムセキュリティには、さまざまな形での攻撃に対処することもついて回ります。攻撃には、root を破ろうとはしないが、システムをクラッシュさせたり、さもなければ、システムを使用不能にしたりしようとするものも含まれています。セキュリティに関する問題は、いくつかのカテゴリに分類することができます:

  1. サービス不能攻撃 (DoS)
  2. ユーザアカウントにかかる危険
  3. アクセス可能なサーバを経由した root 権限にかかる危険
  4. ユーザアカウントを通した root 権限にかかる危険
  5. 裏口の作成

サービス不能攻撃とは、マシンから必要な資源を奪う行為です。サービス不能攻撃は、普通は、そのマシンで実行されるサーバやネットワークスタックを圧倒して、マシンをクラッシュさせたり、さもなければマシンを使えなくしたりするような力任せの方法です。サービス不能攻撃のいくつかは、ネットワークスタックのバグを利用して、パケット一つでマシンをクラッシュさせようとします。後者は、カーネルにバグ修正を施すことによってのみ修正することができます。サーバプロセスに対する攻撃は、オプションを適切に指定して、不利な状況にあるシステムにおいて、サーバプロセスが引き起こす負荷に限界を設けることで修正することができます。これらに比べると、ネットワークへの力任せの攻撃への対応はずっと難しくなります。たとえば、偽造パケットによる攻撃 (spoof-packet attack) は、インターネットからシステムを切り離す以外の方法で防ぐことはほとんど不可能です。それによって、マシンを落としてしまうことはできないかもしれませんが、利用者のインターネット回線をいっぱいにしてしまうことはできます。

ユーザアカウントを危険に晒してしまう問題は、サービス不能攻撃よりもずっとよくある問題です。このご時勢でも、自分たちのマシンで標準の telnetd(8), rlogind(8), rshd(8), ftpd(8) サーバを実行させているシステム管理者は多いのです。これらのサーバは、デフォルトでは、暗号化されたコネクション上で動作していません。その結果、抱えているユーザ数が標準くらいであれば、リモートログイン (そのシステムにログインするには最も普通で便利な方法です) しているユーザのうち一人以上は、パスワードを覗き見られてしまうでしょう。システム管理者が注意深い人ならば、たとえログインが成功していたとしても、リモートアクセスログを解析して、疑わしいソースアドレスを探すものです。

ひとたび攻撃者がユーザアカウントへのアクセス権を入手すると、攻撃者が root の権限を破る可能性があることを仮定するべきです。しかし、セキュリティを十分維持し、手入れの行き届いたシステムにおいては、あるユーザアカウントへのアクセスが可能となっても、攻撃者に必ずしも root へのアクセス権を与えるとは限らないのが現実です。この違いは、重要です。というのは、root へのアクセス権がなければ、一般的に、攻撃者は、自分の侵入の痕跡を隠蔽することができませんし、そのユーザのファイルを引っかき回したり、マシンをクラッシュさせたりできるのがせいぜいです。ユーザアカウントが危険に晒されるということは、たいへんよく起こることです。なぜなら、ユーザは、システム管理者ほどには前もって注意を払わない傾向があるからです。

システム管理者は、あるマシン上で root の権限を破る方法は、潜在的に何通りもあるのだということを心しておかねばなりません。攻撃者が root のパスワードを知ってしまうかもしれません。攻撃者が root の権限で実行されるサーバのバグを見つけ、ネットワークからそのサーバへ接続して root の権限を破ることができるかもしれません。ひとたびユーザアカウントを破ると、ユーザアカウントから root の権限を破ることが可能であるというバグを持つ SUID-root プログラムの存在を、攻撃者は、知っているかもしれません。あるマシン上で、攻撃者が root の権限を破る方法を知ったとすると、攻撃者は、裏口を作る必要などないかもしれません。発見され、ふさがれた root の穴の多くには、攻撃者が侵入した跡を消そうとしてたくさん仕事した結果が含まれています。そのためにこそ、多くの攻撃者は、裏口を作るのです。この裏口は、攻撃者の検出をするのに便利なやり方です。攻撃者が裏口を取り付けることを不可能にすることは、元々押し入るために攻撃者が使用するホールをふさがないので、実際にセキュリティに有害であるかもしれません。

セキュリティを改善する方法は、常に、“タマネギの皮剥き”のように複数の層のアプローチで実装されるべきです。これらは、次のように分類できます:

  1. root とスタッフのアカウントの安全性を高める。
  2. root の安全性を高める— root 権限のサーバと SUID/SGID バイナリ。
  3. ユーザアカウントの安全性を高める。
  4. パスワードファイルの安全性を高める。
  5. カーネルのコア、raw デバイス、ファイルシステムの安全性を高める。
  6. システムに対して行なった、不適切な変更をすばやく検出する。
  7. 偏執狂的方法。

root アカウントとスタッフアカウントの安全性を高める

root のアカウントの安全性を確保しないうちからスタッフのアカウントの安全性をうんぬんしてもしかたがありません。ほとんどのシステムでは、root アカウントに割り当てたパスワードが 1 つあります。まず最初にすべきことは、このパスワードは、 いつでも 危険に晒されていると仮定することです。ここでは、root のパスワードを消すべきだと言っているのではありません。パスワードは、マシンにコンソールからアクセスするのには、ほとんどいつでも必要なものです。ここで言いたいのは、コンソール以外からは、おそらくは、 su(1) ユーティリティを用いてすらパスワードを使えるようにするべきではないということです。例えば、PTY が、 /etc/ttys ファイルで“ insecure”と指定されているかを確認してください。そうすることで、 telnet(1)rlogin(1) 越しに root でログインできないようになります。 sshd(8) のような、別のログインサービスを使っている場合でも同様に、直接 root へログインすることを許していないかどうか確認してください。アクセスする手段、例えば ftp(1) のようなサービスが、たびたびクラックの手に落ちることを考えてみてください。 root に直接ログインできるのは、システムコンソールを通したときのみにすべきです。

システム管理者として、自分は、root になれるようにしておかねばならないのは、もちろんですから、穴をいくつか空けておきます。しかし、それらの穴を動作させるには、さらに追加のパスワード認証が必要であるようにしておきます。 root でアクセス可能とする方法の一つとして、適切なスタッフアカウントを ( /etc/group) の“ wheel”グループに加えることがあります。 wheel グループに置かれたスタッフメンバには、 su(1) を使って root になることが許されます。パスワードエントリにおいて、スタッフメンバを wheel グループを置くことで、スタッフメンバに wheel のアクセス権を与えてはいけません。スタッフメンバのアカウントは、“ staff”グループに置くべきです。そして /etc/group ファイルを通して wheel グループに加えるべきです。実際に root アクセスの必要な staff メンバのみ wheel グループに置くようにすべきです。 Kerberos のような認証方法を使用する場合、root アカウントで .k5login ファイルを使って、誰も wheel グループに置く必要なく root に ksu(1) を許すようにすることもできます。このやり方は、よりよい解決策なのかもしれません。なぜなら、 wheel のメカニズムでは、侵入者がパスワードファイルを手に入れ、staff アカウントのいずれか 1 つを破ることができると、root を破ることがまだできてしまうからです。 wheel のメカニズムを用いる方が、何もしないよりは良いのですが、必ずしも最も安全な選択肢とは限りません。

root アカウントの安全性を高める間接的な方法として、別のログインアクセスの方法を用いて、スタッフのアカウントの暗号化パスワードを * にしておくことで、スタッフのアカウントの安全性を高めるものがあります。この方法だと、侵入者は、パスワードファイルを盗むことができるかもしれませんが、スタッフアカウントを破ることはできないでしょう。また、たとえ root が暗号化パスワードをパスワードファイルに付けていたとしても、 root アカウントも破ることはできないでしょう (もちろん、コンソールへの root によるアクセスが限定されているものとします)。スタッフメンバがスタッフアカウントでログインする際には、 kerberos(8)ssh(1) のような、公開鍵 / 秘密鍵の鍵の組を使う安全性の高いログインの仕組みを使います。 Kerberos のような仕掛けを使う場合、一般に、 Kerberos サーバを実行するマシンと自分のデスクトップワークステーションとの安全性を確保しなければなりません。 SSH で公開鍵 / 秘密鍵の組を使う場合、一般に、ログイン マシン (通常は、自分のワークステーション) の安全性を確保しなければなりません。ここで、 ssh-keygen(1) で公開鍵 / 秘密鍵の組を生成する際、鍵の組をパスワードで防御することにより、鍵の組への防御層を追加することもできます。スタッフアカウントのパスワードを * で外すことができると、管理者自身が設定した安全性の高い方法でしかスタッフメンバがログインできないことも保証できます。こうして、多くの侵入者が使う重大なセキュリティの穴 (安全性の低い無関係なマシンからネットワークを覗き見る方法) を塞ぐようなセッションを提供する、安全性の高い暗号化されたコネクションを使うことを、スタッフメンバ全員に強制することができるのです。

より間接的なセキュリティの仕組みでは、制限の強いサーバから制限の弱いサーバへログインすることを前提としています。例えば、メインマシンで、様々な種類のサーバを実行させている場合、ワークステーションでは、それらのサーバを実行させてはなりません。ワークステーションを十分に安全にしておくためには、実行するサーバの数を、一つもサーバが実行されていないというくらいにまでできる限り減らすべきです。また、パスワードで保護されたスクリーンセーバを走らせておくべきです。ワークステーションへの物理的アクセスが与えられたとすると、もちろん言うまでもなく、攻撃者は、管理者が設定したいかなる種類のセキュリティをもうち破ることができるのです。これは、管理者として必ず考えておかねばならない問題ですが、システム破りの大多数は、ネットワーク経由でリモートから、ワークステーションやサーバへの物理的アクセス手段を持たない人々によって行われるという事実もまた、念頭に置いておく必要があります。

Kerberos のような方法を使うことで、スタッフアカウントのパスワードの変更もしくは停止を一箇所で行なうことと、スタッフメンバがアカウントを持つすべてのマシンに即時にその効果を及ぼすことが可能となります。スタッフメンバのアカウントが危険に晒されたときに、すべてのマシンでスタッフメンバのパスワードを即座に変更する能力を過小評価してはいけません。パスワードが分散されている状況では、N 台のマシンでパスワードを変更すると、てんやわんやの事態を招く可能性があります。 Kerberos を使用すると、パスワードの再発行に制限 (re-passwording restriction) を課することもできます。この機能を使うことにより、ある Kerberos チケットをしばらく経つとタイムアウトにすることができるだけでなく、一定期間 (例えば、1 ヶ月に 1 回) 経つと、ユーザに新しいパスワードを選ぶように要求することもできます。

root の安全性を高める— root 権限のサーバと SUID/SGID バイナリ

用心深いシステム管理者は、自分に必要なサーバプロセスだけを過不足なく実行させるものです。第三者製のサーバは、よくバグを持っていがちだということに注意して下さい。例えば、古いバージョンの imapd(8)popper(8) ( ports/mail/popper) を実行させておくのは、全世界に共通の root の切符を与えているようなものです。自分で注意深くチェックしていないサーバは、決して実行してはいけません。 root で実行させる必要のあるサーバはほとんどありません。例えば、 talkd(8), comsat(8), fingerd(8) デーモンを、特別の「砂場“sandbox”」ユーザで実行させることができます。管理者が膨大な数の問題に直面していないのなら、この「砂場」は、完璧ではありませんが、セキュリティに関するタマネギ的アプローチはここでも成り立ちます。砂場で実行されているサーバプロセスを経由して侵入を果たすことができたとしても、攻撃者は、さらに砂場から外に脱出しなければなりません。攻撃者が通過せねばならない層の数が増えれば増えるほど、それだけ攻撃者が侵入に成功する確率が減ります。 root の抜け穴は、歴史的に、基本システムサーバも含め、 root 権限で実行されるほとんどすべてのサーバプロセスで発見されています。ユーザが sshd(8) 経由でのみログインし、 telnetd(8), rshd(8), rlogind(8) 経由でログインすることが決してないマシンを稼働させているのであれば、それらのサービスを停止させて下さい。

FreeBSD では、今では talkd(8), comsat(8), fingerd(8) は、砂場で実行させることがデフォルトになっています。次に砂場で実行させるべきプログラムの候補として、 named(8) があります。デフォルトの rc.conf ファイルには、 named(8) を砂場で実行するために必要な引数がコメントアウトされた形式で含まれています。新しいシステムをインストールしているか、それとも既存のシステムをアップグレードして使っているかに依存しますが、砂場として使用する特別のユーザアカウントがインストールされていないかもしれません。用心深いシステム管理者であれば、できるだけいつでも研究を怠らず、サーバに砂場を仕込むものでしょう。

通常、砂場で実行しないサーバが他にいくつかあります: sendmail(8), popper(8), imapd(8), ftpd(8) などです。これらのいくつかへの代替手段がありますが、それらをインストールすることは、行いたいことより多くの仕事を必要とするかもしれません (便利さという要素がまたも勝利を収めるわけです)。これらのサーバは、root 権限で実行せねばならないかもしれません。また、これらのサーバ経由で生じる侵入を検出するためには、他の仕組みに頼らなくてはならないかもしれません。

システムの root 権限の潜在的な穴で他に大きなものとして、システムにインストールされた SUID-root/SGID バイナリがあります。これらのバイナリは、 rlogin(1) のように、 /bin, /sbin, /usr/bin, /usr/sbin に存在するものがほとんどです。 100% 安全なものは存在しないとはいえ、システムデフォルトの SUID/SGID バイナリは、比較的安全といえます。それでもなお、root の穴がこれらのバイナリにときおり発見されています。 1998 年に Xlib で見つかった root の穴は、 xterm(1) ( ports/x11/xterm) (普通、SUID 設定されています) を攻撃可能にしていました。安全である方がよいので、用心深いシステム管理者は、残念に思いながらも、スタッフのみが実行する必要がある SUID バイナリは、スタッフのみがアクセス可能な特別なグループに含めるように制限を加え、誰も使わない SUID バイナリは、 (“ chmod 000”) を実行して片付けてしまうでしょう。ディスプレイを持たないサーバは、一般的に xterm(1) のバイナリを必要としません。 SGID バイナリもほとんど同様の危険な存在になり得ます。侵入者が kmem に SGID されたバイナリを破ることができた場合、その侵入者は、 /dev/kmem を読み出すことができるようになります。つまり、暗号化されたパスワードファイルを読み出すことができるようになるので、パスワードを持つどのアカウントをも、 (潜在的な) 危険に晒すことになります。代わりに、“ kmem”グループを破った侵入者が PTY を通して送られたキーストロークを監視できます。キーストロークには、安全な方法でログインするユーザが使っている PTY も含まれます。“ tty”グループを破った侵入者は、ほぼ任意のユーザの TTY へ書き込みができます。ユーザが端末プログラムやキーボードをシミュレーションする機能を持ったエミュレータを使っている場合、侵入者は、潜在的に、結局そのユーザとして実行されるコマンドをユーザの端末にエコーさせるデータストリームを生成できる可能性があります。

ユーザアカウントの安全性を高める

ユーザアカウントは、普通、安全性を高めることが最も困難です。スタッフに対して、アテナイのドラコのような厳格なアクセス制限を課し、スタッフのパスワードを * で外すことができるとはいえ、管理者が持ちうる一般ユーザすべてのアカウントに対して同じことはできないかもしれません。管理者が十分に統率をとることができるなら、管理者は、勝利し、ユーザのアカウントの安全を適切に確保できるかもしれません。それができないならば、よりいっそう気を配って一般ユーザのアカウントを監視するよりほかありません。一般ユーザアカウントに対し SSH や Kerberos を利用することには、システム管理がさらに増えたりテクニカルサポートが必要になるなどの問題があります。それでも、暗号化パスワードファイルと比較するとはるかに良い解です。

パスワードファイルの安全性を高める

できるだけ多くのパスワードを * で外し、それらのアカウントのアクセスには SSH や Kerberos を使うようにすることが、唯一の確実な方法です。たとえ暗号化パスワードファイル ( /etc/spwd.db) が root でのみ読み出し可能だとしても、侵入者がそのファイルの読み出しアクセス権限を得ることは可能かもしれません。たとえ root の書き込み権限が得られないにしてもです。

セキュリティスクリプトは、常にパスワードファイルの変更をチェックし、報告するようにすべきです (後述の 「ファイルの完全性のチェック」 を参照して下さい)。

カーネルのコア、raw デバイス、ファイルシステムの安全性を高める

root の権限を破ると、攻撃者は、何でもできますが、もっと簡便なこともいくつかあります。例えば、最近のカーネルは、組み込みのパケット覗き見デバイス (packet sniffing device) ドライバを備えているものがほとんどです。 FreeBSD では、 bpf(4) デバイスと呼ばれています。侵入者は、普通、危険に晒されたマシンでパケット覗き見プログラムを実行させようと試みます。侵入者にわざわざそういう機能を提供する必要はないので、ほとんどのシステムで bpf(4) デバイスを組み込むべきではありません。

bpf(4) デバイスを外し、モジュールローダを無効にしても、 /dev/mem/dev/kmem という悩みの種がまだ残っています。この問題に関しては、侵入者は、raw デバイスに書き込むこともできます。また、 kldload(8) という、別のカーネル機能があります。やる気まんまんの侵入者は、KLD モジュールを使って自分独自の bpf(4) もしくはその他覗き見デバイスを動作中のカーネルにインストールすることができます。この問題を避けるため、システム管理者は、カーネルをより高い安全レベル (security level)、少なくとも安全レベル 1 で実行させる必要があります。 sysctl(8) を使って kern.securelevel 変数に安全レベルを設定することができます。ひとたび安全レベルに 1 を設定すると、raw デバイスに対する書き込みアクセスは拒否され、例えば schg のような特別な chflags(1) フラグが効果を発揮します。これに加えて、起動時において重要なバイナリ・ディレクトリ・スクリプトファイルなど、安全レベルが設定されるまでの間に実行されるものすべてに対しても schg フラグを確実に on にしておく必要があります。この設定をやり過ぎても構いませんが、より高い安全レベルで動作している場合、システムのアップグレードがはるかに困難になります。システムをより高い安全レベルで実行させるようにするが、お天道さまの下にあるすべてのシステムファイルとディレクトリに schg フラグを設定しないという妥協をする方法もあります。もう一つの可能性としては、単純に //usr を読み込み専用でマウントすることです。ここで特筆すべきことは、システムを守ろうとしてアテナイのドラコのように厳しくしすぎると、侵入を検出するという非常に重要なことができなくなってしまうということです。

カーネルは、5 つの違ったセキュリティレベルで実行します。スーパユーザのプロセスは、レベルを上げることができますが、どんなプロセスもそれを下げることはできません。セキュリティレベルは、次の通りです:

-1
永久に不安全なモード-不安全なモードでシステムを常に実行します。これは、デフォルトの初期値です。
0
不安全なモード-不変、追加専用フラグをオフに切り替えることができます。すべてのデバイスは、それらのパーミッションに従って読み込みまたは書き込みすることができます。
1
安全モード-システム不変とシステム追加専用フラグを切り替えることができます。マウントされたファイルシステム、 /dev/mem/dev/kmem のためのディスクは、書き込みのためにオープンすることができません。 /dev/io (利用者のプラットフォームにそれがあるなら) は、全くオープンされません。カーネルモジュール ( kld(4) 参照) は、ロードするか、またはアンロードできません。カーネルデバッガは、 debug.kdb.enter sysctl を使用して入力されません。パニックまたはトラップを、 debug.kdb.panic と他の sysctl を使用して強制することができません。
2
高度な安全モード-安全モードと同じですが、さらに、マウントされているか、マウントされていないかに関係なく ( mount(2) を除いて) ディスクは、書き込みのためにオープンすることができません。このレベルは、それらをアンマウントすることによってファイルシステムを不正に改ざんすることを排除しますが、システムがマルチユーザの間に、 newfs(8) を実行することも禁止します。

さらに、カーネルの時刻の変更は、1 秒以下に制限されます。これ以上の時間を変更する試みは、“Time adjustment clamped to +1 second” (時間の調整は、+1 秒に固定されます) というメッセージがログ登録されます。

3
ネットワーク安全モード-高度な安全モードと同じですが、さらに、 IP パケットフィルタ規則 ( ipfw(8), ipfirewall(4)pfctl(8) 参照) は、変更することができず、 dummynet(4) または pf(4) 設定は、調整することができません。

rc.conf(5) に文書化された変数で、セキュリティレベルを設定することができます。

ファイルの完全性のチェック: バイナリ、設定ファイルなど

ことこの問題に至ると、システム管理者にできることは、便利さという要素がその醜い頭を上げない程度に、コアシステムの設定 / 制御ファイルを防御することだけです。例えば、 //usr にある大部分のファイルに schg ビットを設定するために chflags(1) を使用するのは、おそらく逆効果でしょう。なぜなら、そうすることでファイルは、保護できますが、侵入を検出する窓を閉ざしてしまうことにもなるからです。セキュリティのタマネギの最後の層は、おそらく最も重要なもの、すなわち検出です。セキュリティの残りのものは、突然の侵入を検出できなければ、全然有用ではありません (あるいは、もっと悪ければ、間違った安全性に対する感覚を植え付けてしまいます)。タマネギの仕事の半分は、攻撃者を食い止めるのではなく、侵入を遅らせることにより、攻撃中の攻撃者を捕まえる機会を検出層に与えることなのです。

侵入を検出する最も良い方法は、変更されていたり、消えていたり、入れた覚えがないのに入っているファイルを探すことです。変更されたファイルを探すのに最も良い方法は、もう一つの (しばしば中央に集められた) アクセスが制限されたシステムから行なうものです。さらに安全でアクセス制限されたシステム上でセキュリティ用スクリプトを書けば、スクリプトは、潜在的な攻撃者達からはほぼ見えなくなります。これは、重要なことです。最大限に優位に立つために、一般的にビジネスで使う他のマシンへの重要なアクセスは、アクセスの制限されたマシンにやらせなくてはいけません。普通は、他のマシンからアクセス制限されたマシンへ読み込み専用で NFS エクスポートしたり、アクセス制限されたマシンから他のマシンへ SSH を行なうために、SSH 鍵のペアを作ったりすることで行います。ネットワークのトラフィックを別にして、NFS は、最も可視性のない方法です。事実上検出されない各クライアント上のファイルシステムを監視できるようになります。アクセス制限されたサーバがスイッチを通してクライアントに接続する場合、たいてい NFS がより良い選択肢です。アクセス制限されたサーバがハブを通したり、いくつかのルーティング層を通したりしてクライアントに接続する場合、 NFS は、あまりにも危険な方法かもしれず (ネットワークの面で)、SSH の方が認証の道筋は、跡となって残りますが、それでもより良い方法かもしれません。

アクセス制限されたマシンに、少なくとも監視することを前提としたクライアントシステムへの読み込みアクセスをひとたび与えると、実際に監視するためのスクリプトを書かなくてはいけません。 NFS マウントをすれば、 find(1)md5(1) などの単純なシステムユーティリティでスクリプトを書くことができます。少なくとも 1 日 1 回、クライアントのファイルを直接 md5(1) にかけ、さらにもっと頻繁に /etc および /usr/local/etc にあるようなコントロール用ファイルを試験するのが一番です。試験ファイルは、アクセス制限されたマシンが適性であると知っている、基となる MD5 情報と比べて違いが見つかった場合、システム管理者に調べて欲しいと訴えるようにするべきです。優れたセキュリティ用スクリプトは、 / および /usr などのシステムパーティション上で不適当に SUID されたバイナリや、新たに作成されたファイルや削除されたファイルもチェックするのでしょう。

NFS ではなく、SSH を使用する場合は、セキュリティ用スクリプトを書くのはずっと難しいことです。スクリプトをクライアントから見えるようにし、動かすためには、クライアントに対して scp(1) を必ず行わなくてはいけません。そして、安全のため、スクリプトが使うバイナリ ( find(1) など ) を scp(1) する必要もあります。クライアントの sshd(8) デーモンは、すでに危険に晒されているかもしれません。以上のことから、安全でないリンク上の場合は、SSH は、必要かもしれませんが、 SSH を扱うのはとても大変なことです。

優れたセキュリティ用スクリプトは、ユーザやスタッフメンバのアクセス設定ファイルもチェックするものです: .rhosts, .shosts, .ssh/authorized_keys などがそれですが、MD5 のチェックの範囲外になってしまうかもしれません。

ユーザ用のディスク容量が非常に大きい場合は、パーティション上の各ファイルを見て回るのに大変な時間がかかるかもしれません。この場合は、マウントフラグを設定して、このパーティションに SUID されたバイナリを置けないようにするのが良い考えです。 nosuid オプション ( mount(8) 参照) が調べたいものでしょう。私なら、ともかくも週に 1 度はファイルシステムをスキャンするでしょう。なぜなら、この層での目的は、侵入が意味があるかどうかに関わらず、侵入を検出することだからです。

プロセスアカウンティング ( accton(8) 参照) は、比較的オーバヘッドの低いオペレーティングシステムの機能で、マシンに侵入されてしまった後の評価の仕組みとして使用することをお勧めします。侵入を受けた後でも当該ファイルが無傷である場合に、侵入者が実際にどのようにしてシステムに侵入したかを追跡するのに特に有益です。

最後に、セキュリティスクリプトは、ログファイルを処理するようにし、ログファイル自体もできるだけ安全性の高い方法で `リモート syslog は、極めて有益になり得ます' 生成するようにすべきです。侵入者は、自分の侵入の痕跡を覆い隠そうとしますし、また、ログファイルは、システム管理者が最初の侵入の時刻と方法を追跡してゆくために極めて重要です。ログファイルを永久に残しておくための 1 つの方法は、システムコンソールをシリアルポートにつないで走らせ、コンソールを監視している安全なマシンを通して絶えず情報を集めることです。

偏執狂的方法

多少偏執狂的になっても決して悪いことにはなりません。原則的に、システム管理者は、便利さに影響を与えない範囲でいくつでもセキュリティ機能を追加することができます。また、いくらか考慮した結果、便利さに影響を与えるセキュリティ機能を追加することもできます。もっと重要なことは、セキュリティ管理者は、少々ごちゃごちゃにすべきだということです。というのも、このマニュアルページに書かれている勧告をそのまま使用した場合は、予想される攻撃者は、やはりこのマニュアルを読んでいるわけですから、防御策を漏らしてしまうことになるからです。

サービス不能攻撃 (DoS attack) についての特記事項

このセクションでは、サービス不能攻撃を扱います。サービス不能攻撃は、普通は、パケット攻撃です。ネットワークを飽和させる最先端の偽造パケット (spoofed packet) 攻撃に対してシステム管理者が打てる手は、それほど多くありませんが、一般的に、その種の攻撃によってサーバがダウンしないことを確実にすることで、被害をある限度に食い止めることはできます。
  1. サーバの fork の制限
  2. 踏み台攻撃の制限 (ICMP 応答攻撃、ping broadcast など)
  3. カーネルの経路情報のキャッシュ

普通に見られるサービス不能攻撃に、fork するサーバプロセスに対するものがあります。これは、サーバにプロセス・ファイル記述子・メモリを食い尽くさせて、マシンを殺そうとするものです。 inetd(8) サーバには、この種の攻撃を制限するオプションがいくつかあります。マシンがダウンすることを防止することは可能ですが、この種の攻撃によりサービスが崩壊することを防止することは一般的に言ってできないことに注意する必要があります。 inetd(8) のマニュアルページを注意深く読んで下さい。特に、 -c, -C, -R オプションに注意して下さい。 IP 偽造攻撃 (spoofed-IP attack) は、 inetd(8)-C オプションの裏をかけるので、一般にオプションを組み合わせて使用するべきであることに注意して下さい。スタンドアロンサーバの中には、自分自身で fork を制限するパラメータを持っているものがあります。

sendmail(8) デーモンには、 -OMaxDaemonChildren オプションがあります。負荷には遅れがあるので、 sendmail(8) の負荷に限界を設けるオプションを使うよりも、このオプションを使う方がまともに動作する可能性は、はるかに高いです。利用者は、予想される負荷を扱うために十分な sendmail(8) を開始するとき、コンピュータがダウンするほどには高くない sendmail の数を扱うことができるような値に MaxDaemonChildren パラメータを指定するべきです。 sendmail(8) を“キュー処理”モード ( -ODeliveryMode=queued) で実行することや、デーモン (“ sendmail -bd”) をキュー処理用プロセス (“ sendmail -q15m”) と別に実行することも、用心深いことと言えます。それでもなおリアルタイムでの配送を望むのであれば、 -q1m のようにすることで、キュー処理をはるかに短い時間間隔で行うことができます。いずれにしても、 MaxDaemonChildren オプションに合理的な値を確実に指定して、 sendmail(8) がなだれをうって失敗することがないようにして下さい。

syslogd(8) デーモンは、直接攻撃される可能性があるので、可能ならばいつでも -s オプションを用いることを強く推奨します。これができないなら、 -a オプションを使って下さい。

tcpwrapper の逆 identd などの接続返し (connect-back) を行うサービスについては十分注意を払うようにするべきです。これらは、直接攻撃を受ける可能性があります。こういう事情があるので、tcpwrapper の逆 ident 機能を使おうとは思わないのが一般的です。

境界ルータのところでファイアウォールを設けて、外部からのアクセスに対して内部サービスを防御するという考えは、実によいものです。この考えは、LAN の外部からの飽和攻撃を防ぐことにあり、root ネットワークベースの root 権限への攻撃から内部サービスを防御することには、あまり考慮を払っていません。ファイアウォールは、常に排他的に設定して下さい。つまり、「ポート A, B, C, D と M から Z まで 以外 のすべてにファイアウォールを設ける」というふうにです。このようにすることで、 named(8) (ゾーンのプライマリである場合), talkd(8), sendmail(8) など、インターネットにアクセスを提供するサービスとして特に指定するもの以外の、小さい番号のポートすべてをファイアウォールで防御することができます。ファイアウォールをこの他のやり方、つまり包含的もしくは受容的なファイアウォールとして設定しようとする場合、“close”することを忘れてしまうサービスがいくつか出てきたり、新しい内部サービスを追加したのにファイアウォールの更新を忘れたりする可能性がよく出てきます。ファイアウォール上の大きい番号のポートを開けておいて、小さい番号のポートを危険に晒すことなく受容的な動作を許すことができます。 FreeBSD では、 net.inet.ip.portrange への sysctl (“ sysctl net.inet.ip.portrange”), をいろいろ使用することで、動的バインドに使用されるポート番号の範囲を制御できることを記憶にとどめておいて下さい。これによりファイアウォールの設定の複雑性を緩和できます。私は、ファイアウォールに通常の first/last の範囲として、4000 から 5000 を、高位ポートの範囲として、49152 から 65535 を使用しています。そして、(いくつかのインターネットアクセス可能なポートをブロックから除外するのはもちろんですが) 4000 より下のすべてをブロックしています。

また別のありふれたサービス不能攻撃として、踏み台攻撃 (springboard attack) と呼ばれるものがあります。これは、サーバが自分自身、ローカルネットワーク、そして他のマシンを過負荷に追い込むような応答を生成させる方法でサーバを攻撃します。この種の攻撃の中で最もありふれたものは、ICMP PING BROADCAST 攻撃があります。攻撃者は、実際に攻撃したいマシンのアドレスをソースアドレスに設定した ping パケットを偽造して、対象の LAN のブロードキャストアドレスに向けてパケットを送信します。境界にあるルータがブロードキャストアドレスに対する ping パケットを握り潰すように設定されていない場合、LANは、詐称されたソースアドレスに向けて応答パケットを生成するはめになり、犠牲となるマシンが飽和するところまで行ってしまいます。攻撃者が同じトリックを異なるネットワーク上のいくつものブロードキャストアドレスに対して同時に使用した場合、とくにひどいことになります。これまでに、120 メガビット以上のブロードキャスト攻撃が観測されています。 2 番目の踏み台攻撃は、ICMP エラー報告の仕掛けを狙うものです。 ICMP エラー応答を生成するパケットを生成することにより、攻撃者は、サーバの受信ネットワークを飽和させることができ、同時に、サーバが送信ネットワークを ICMP 応答で飽和させるようにすることができます。 mbuf を消費し尽くさせることにより、この種の攻撃でサーバをクラッシュさせることも可能です。サーバの ICMP 応答生成が速過ぎて、 ICMP 応答の送信が追い付かない場合、とくにひどいことになります。 FreeBSD カーネルには、この種の攻撃の効果を抑制する ICMP_BANDLIM と呼ばれる新しいコンパイルオプションがあります。 3つめの主要なクラスに属す踏み台攻撃は、UDP echo サービスのような、ある種の内部 inetd(8) サービスに関連するものです。攻撃者は、単にソースアドレスがサーバ A の echo ポートであり、ディスティネーションアドレスがサーバ B の echo ポートであるかのように UDP パケットを偽造します。ここでサーバ A, B は、ともに自分の LAN に接続されています。この 2 つのサーバは、この一つのパケットを両者の間で互いに相手に対して打ち返しあいます。このようにしてパケットをいくつか注入するだけで、攻撃者は、両方のサーバと LAN を過負荷状態にすることができます。同様の問題が内部 chargen ポートにも存在します。有能なシステム管理者は、この手の inetd(8) 内部テストサービスのすべてを無効にしておくものです。

偽造パケット攻撃は、カーネルの経路情報キャッシュに過負荷を生じさせるために用いられることもあります。 net.inet.ip.rtexpire, net.inet.ip.rtminexpire, net.inet.ip.rtmaxcachesysctl(8) パラメータを参照して下さい。でたらめなソース IP を用いたこの偽造パケット攻撃により、カーネルは、一時的なキャッシュ経路を経路情報テーブルに生成します。これは、“ netstat -rna | fgrep W3”. で見ることができます。これらの経路は、普通は、1600 秒程度でタイムアウトになります。カーネルがキャッシュ経路テーブルが大きくなり過ぎたことを検知すると、カーネルは、動的に rtexpire を減らしますが、 rtminexpire より小さくなるようには決して減らしません。ここに問題が 2 つあります。 (1) 負荷の軽いサーバが突然攻撃された場合、カーネルが十分素早く反応できないこと。 (2) カーネルが攻撃に耐え生き延びられるほど十分 rtminexpire が低く設定されていないこと。の 2 つです。自分のサーバが T3 もしくはそれより良質の回線でインターネットに接続されている場合、 sysctl(8) を用いて rtexpirertminexpire とを手動で上書きしておくことが思慮深いことといえます。 (自分のマシンをクラッシュさせたくないのであれば :-)) どちらか一方でも 0 には、決してしないで下さい。両パラメータを 2 秒に設定すれば、攻撃から経路情報テーブルを守るには十分でしょう。

Kerberos および SSH を用いたアクセスの問題

もしあなたが、Kerberos および SSH を使用したいのだとしたら、両者に関して言っておく必要のある問題がいくつかあります。 Kerberos5 は、大変優れた認証プロトコルですが、kerberos 化された telnet(1)rlogin(1) は、バイナリストリームを扱うのに不向きになってしまうようなバグがあります。さらに、デフォルトでは、Kerberos は、 -x オプションを使わない限りセッションを暗号化してくれません。 SSH では、デフォルトですべてを暗号化してくれます。

SSH は、あらゆる場面でとても良く働いてくれます。ただし、暗号鍵を送ってしまう場合を除けばです。これは、つまり、暗号鍵を持った安全なワークステーションがあって、この暗号鍵で残りのシステムとアクセスできるようになっている場合では、安全でないマシンへ ssh(1) を行なう時に暗号鍵が見えてしまうということです。実際の鍵そのものが見えてしまうわけではありませんが、 ssh(1) は、 login している間、配送用ポートを作ります。攻撃者が安全でないマシンの root を破ると、攻撃者は、このポートを使って暗号鍵を取得し、暗号鍵でロックの外れる他のマシンへのアクセスを得ます。

staff のログインには、Kerberos を組み合せた SSH を使用することを勧めます。 SSH は、Kerberos と一緒にコンパイルできます。こうすると、見えてしまうかもしれない SSH 鍵をあまりあてにしないで良いようになります。また、それと同時に、Kerberos 経由でパスワードを保護することもできます。 SSH 鍵は、安全なマシンからの自動化されたタスク (Kerberos では、不向きなものなど ) 用のみに使用するべきです。また、SSH の設定で SSH 鍵を送らないようにするか、あるいは、 authorized_keys ファイル中で from= IP/DOMAIN オプションを使用して、特定のマシンからログインしてきたもののみに有効になる鍵を SSH が生成できるようにすることも勧めます。

歴史

security マニュアルページは、もともと Matthew Dillon によって書かれ、 1998 年 12 月に FreeBSD 3.1 ではじめて登場しました。
February 8, 2012 FreeBSD