1984 年に Richard Stallman 氏は Free Software Foundation (FSF)にて、GNU プロジェクトという、フリーな UNIX オペレーティングシステムを作り上げる プロジェクトを立ち上げました。フリーという言葉で、Stallman 氏は利用する こと、内容(ソース)を読むこと、修正を加えること、再配布することが自由に できるソフトウエアを表現しました。 FSF は数多くの便利なツール群を作成することができましたが、独自のオペレー ティングシステムのカーネルを思うように開発できずにいました [FSF 1998]。 1991 年に Linus Torvalds 氏が「Linux」というオペレーティングシステムの カーネルを開発しはじめました [Torvalds 1999]。 このカーネルは FSF や他のツールと相まって、自由に改変できる、たいへん実用的 なオペレーティングシステムとなりました。 このドキュメントではカーネルを指す言葉として「Linux カーネル」を、システム 全体を示す言葉として「Linux」を使用します(同様な意味で GNU/Linux という表現 を使う場合が多々あります)。
様々な団体がそれぞれに、便利なツール群をこのカーネルと組み合わせています。 この組合せを「ディストリビューション」と呼び、団体を「ディストリビュータ」 と呼んでいます。 よく知られたディストリビュータには Red Hat、Mandrake、SuSE、Caldera、Corel、 Debian があります。 このドキュメントは特定のディストリビューションにターゲットを当てていません が、カーネルのバージョンが 2.2 以上で C ライブラリが glibc 2.1 以上である ことを前提にしています。現在の主要なディストリビューションはすべて、この 前提を満たしています。
「フリーソフトウエア」への関心が増すにつれ、その定義と説明を行う必要性が でてきました。 世間で広く使用されている言葉は「オープン・ソース・ソフトウエア」であり、 [OSI 1999] で詳細に定義されています。 Eric Raymond [1997, 1998] の中で、フリーソフトウエアの開発過程について、 独創性に富んだ論文をいくつか発表しています。
Linux はいわゆる UNIX と呼ばれるものからソースコードを流用していません。 しかしそのインターフェースは非常に UNIX ライクです。 そのため UNIX で学んだ教訓はそのまま Linux にも当てはまります。もちろん セキュリティについても同様です。 このドキュメントで述べられている情報の大部分は、実際のところ他の UNIX ライクなシステムでも役に立ちます。しかし Linux 固有の情報も意図的に加え られています。それは Linux の持つ優れた能力を引き出すためです。 このドキュメントではあえて Linux システムに焦点を当てて、対象となるシステム を狭めています。すべての UNIX ライクなシステムを対象にしてしまうと、ポーティ ングや他のシステムの機能についての詳細な検討が必要になってしまい、結果として このドキュメントの量が増えてしまうためです。
Linux は非常に UNIX ライクで、UNIX の持つセキュリティ関連のしくみを持って います。 そのしくみとは、プロセスに対するユーザやグループの ID(uid と gid)、読み/ 書き/実行それぞれのパーミッションを持ったファイルシステム、System V 由来 のプロセス間通信(IPC)、ソケットベースの IPC(ネットワークを利用した通信も 含む)等です。 UNIX システム一般の基本的なセキュリティについての情報は、 Thompson [1974] と Bach [1986] を見てください。 セクション 3 では Linux のセキュリティ機構のキーポイントを概説します。
セキュリティの原則については、少なからず知っておく必要があります。 ぜひ [Pfleeger 1997] のような、コンピュータに関わるセキュリティ全般について 書かれた書籍を読んでください。
Saltzer [1974] と Saltzer and Schroeder [1975] において、安全を保護する ためのシステム設計を行うに当たって、その原則について下記のようにまとめて います。これは現在でもなお有効です。
安全性は多岐に渡るプログラム(このドキュメントで定義されている)に求めら れています。 代表的なものをあげてみます。
訳註:サンドボックス(sandbox)とは、制限付きで保護されたメモリー 領域。この領域で動くアプリケーションは、システムにダメージを与えない ように設計、動作します。
このドキュメントでは、上記の異なった種類のプログラムの問題点を一切合財まと めてしまいます。 このやり方の欠点は、指摘された問題の中にはすべての種類のプログラムに当て はまるとは限らないものも含まれているということです。 特に setuid/setgid されたプログラムは、予想できないような入力を受け取るため、 ガイドラインのいくつかは setuid/setgid されたプログラムにしか当てはまりま せん。 しかし実際はそんなに割り切れるものではありません。というのも、ある種のプロ グラムはいくつかの範疇にまたがっているからです(たとえば、 CGI スクリプトは setuid/setgid されているかもしれないし、setuid/setgid と同様な効果が出るよう に設定されているかもしれません)。 プログラムの種類すべてをまとめて考えることの長所は、プログラムの分類を間違え たりすることなくすべての問題を検討できる点にあります。 これから見ていくことになりますが、原則の多くは安全性が必要となるプログラム すべてに当てはまります。
このドキュメントは、C で書かれたプログラムに多少かたよる傾向にありますが、 C++ や、Perl、Python、Ada95、Java などについても多少は触れています。 これは C が 安全なプログラムを Linux で実装するのに最もポピュラーな言語 だからです(CGI スクリプトは例外です。Perl がよく使われています)。他の言語 であっても、その実装は C で行っている場合がほとんどです。 だからといって、C が安全なプログラムを書くための「最良の」言語である わけではありません。ここで述べられている原則の多くは、使用されているプログラ ミング言語によらず適用できます。
まず安全性が求められるプログラムを書くに当たってやっかいな点は、その着眼点 が普通のプログラムと違うところです。簡単にいうと、疑い深く、こだわりを強く 持つ必要があるということです。 というのも、エラー(欠陥とかバグとも呼ばれています)が生じた時に、システム に与える影響が普通のプログラムとはまったく違うからです。
安全性が求められない普通のプログラムは、エラーをたくさん抱えています。 もちろんこれらのエラーは好ましくないものですが、たいていはほとんど起こら ないものだったり、起こったとしても非常にまれなケースだったりします。仮に 起こったとしても、ユーザは偶然に出くわしてしまったはずで、そのバグを何とか 避けながら利用し続けようとすると思います。
安全性が求められるプログラムでは、この状況が一変します。 とあるユーザは、意図的にバグを捜し出して、本当にまれにしか起こらない状況を つくり出します。そして攻撃することによって不当な権限を得ようとします。 つまり、安全なプログラムを書くのに当たっては、疑い深く、こだわりを強く持つ ことが美徳になるのです。
安全性が求められるプログラムを書くため(もしくは既存のプログラムのセキュ リティ上の問題点を見つけるため)に、様々なドキュメントが書かれています。 これらのドキュメントは、これからこのドキュメントで明らかにしていくガイド ラインの根拠になっています。
AUSCERT はプログラムに当たってのチェックリストを公開しています。 [AUSCERT 1996], このチェックリストは suid されたプログラムやネットワーク関連のプログラムを いかに安全にするかについて論じた Garfinkel、Spafford 各氏の 22 章の部分を ベースにしています。 [Garfinkel 1996]. Matt 氏は、 Bishop [1996, 1997] でこのトピックに関連して、非常に役に立つドキュメントを発表しています。 Galvin [1998a] は、安全なプログラムの開発のためのシンプル な開発プロセスとチェックリストについて記述しています。 Galvin [1998b]. Sitaker [1999] は、「Linux セキュリティ監査」チームが調査する問題に関してのリストを提示 しています。 Shostack [1999] では、セキュリティを重要視するコードをレビューする場合のチェックリストを 上記とは別に提示しています。 The Secure Unix Programming FAQ も役に立つ内容です [Al-Herbish 1999]. Ranum [1998]. からも有益な情報がいくつか得られます。 Anonymous [unknown] は、通常でも起こりうる危険な競合状態を起こり得ないものとして、access(3)の 使用を推奨しています。 Wood [1985] の中の「Security for Programmers」の章は役に立ちますが、少々 古い内容になってしまいました。 Bellovin [1994] と FreeBSD [1999] にも役に立つガイドラインがあります。
Web とのインターフェースとなる CGI(Common Gateway Interface)については、 プログラミングをする際に必要になるセキュリティのガイドラインを示した ドキュメントが多数あります。 Gundavaram [unknown], Kim [1996], Phillips [1995], Stein [1999], Webber [1999].
別の観点(つまり「システムをクラックするには」等)からこの問題を扱った ドキュメントもたくさんあります。 たとえば McClure [1999] がそれにあたります。インターネットの利点を生かして、 他にも数え切れないほどの資料があふれています。
このドキュメントは、有益に違いないと私が判断したガイドラインをまとめました。 そのため、考えられるすべてを網羅したものではありません。 私自身が編集したもの(おまけにリストそれぞれが独自の構成を持っています) ですし、 Linux 固有のガイドライン(たとえばケイパビリティについてや fsuid の値等)についても同様です。 上記すべてのドキュメントを是非参照してください。
訳註:ケイパビリティとは、オペレーティングシステムやハードウェア (CPU)が持つ、セキュリティやアクセス・コントロールを実現するしくみ。 fsuid とは、ファイルシステムをチェックする場合に使用するユーザー識別機能。
「他人のドキュメントを引用するだけでなく、自分でドキュメントを書いたのはなぜ ですか?」 という疑問をお持ちになったかもしれません。理由はいくつかあります。
システムにあるマニュアル(man)のページは名称(番号)の形式で参照します。 番号は、マニュアルのセクション番号を表しています。 C と C++ は「\0」(ASCII の 0)を特別扱いするので、このドキュメントでは「NIL」 と表記します。 「どこも指していない」ポインタ値は、「NULL」と表記します。C コンパイラは 通常、整数の 0 を NULL として扱いますが、NULL をすべてのビットが 0 という 実装にするようにと C の規格が規定しているわけではありません。