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

名称

sprog安全なプログラミング実践

解説

安全の問題は長年にわたっておおくのシステムにひそかに入り込んでいます。この文書はこれらの問題を防ぐプログラミングを実践するためのガイドです。

概要

安全なアプリケーションを書くことは、たいへん注意深く悲観的な見通しを取ります。アプリケーションは、プロセスがその関数を遂行するために必要とする最低限アクセス以上で絶対に実行されないように、“ 最少の特権”の原則で実行されるべきです。以前テストされたコードは可能であるときはいつも、再利用されるべきです。一般的に、プログラムの制御以上ことは決して信用すべきではありません。これはユーザ入力、システムリソース、プロセス間通信、とイベントのタイミングのすべての形式を含んでいます。

バッファオーバフロー

最も一般的なタイプのセキュリティ問題の 1 つはバッファオーバフローです。要するに、プログラムが受け取るデータに慎重でないなら、このデータがメモリを越えて書き込まれ、関数呼び出しの返りアドレスを上書きして、プログラムがやむを得ず敵意のあるコードを実行することが可能となるかもしれません。

標準 C ライブラリのかなり多くの関数は、使用されるとき、バッファオーバフローを防ぐことが難しいか不可能にさえします。これらは、 fscanf(3), gets(3), getwd(3), realpath(3), scanf(3), sprintf(3), strcat(3), strcpy(3), vscanf(3)vsprintf(3) を含んでいます。

また、文字列を処理する他の多くの関数は慎重に使用されないなら、潜在的バッファオーバフローの可能性があるかもしれません。例えば、 strncat(3) は、わざわざヌル文字の終了を供給しません。もちろん、常に適切な長さを指定しなければなりません。 strlcat(3)strlcpy(3) の使用法は、文字列が指定された長さで確実にヌル文字で終了することです。

また、文字列書式を受け取る関数は慎重に使用しなければなりません。文字列がバッファオーバフローのための別の可能性となる、追加書式の記述子を含むことが可能です。‘ %s’を使用しないで、信頼されていないデータで文字列を決して渡さないでください。次のように、常に適切で安全な慣用句を使用してください:

function("%s", string);

ライブラリとコンパイラレベルでこれらの問題のための補強を提供するメカニズムがありますが、単に良いコードを書く代わりのものはありません。

セットユーザ ID (set-user-ID) 問題

多くの場合、プログラムは増強されたパーミッションの状態で動作する必要があるかもしれません。この理由は、保護されたソケットへのバインド、特定のファイルとディレクトリの読み込み書き込み、と様々なリソースへのアクセスを含んでいます。しばしば、setuid プログラムを使用して解決されます。しかしながら、プログラムができるだけ早くこれらの特権を放棄することは重要です。例えば、プログラムが保護されたソケットにバインドされるなら、そのソケットへのバインドが終了するとすぐに、その特権を放棄するべきです。これはシステムコールの setuid(2) ファミリで達成されます。

制限された環境

プロセスを制限する伝統的方法は chroot(2) システムコールを使用することです。このシステムコールはプロセスとその任意の子プロセスで参照される他のすべてのパスのルートディレクトリを変更します。もちろん、プロセスは初めにこのパスにアクセスできなければなりません。 chdir(2) がプロセスを新しい環境に置くために呼び出されるまで、新しい環境は実際に効力を生じません。残念ながら、ルートアクセスが取得されるなら、プロセスはこの環境から抜け出すことができます。

しばしば、 chroot(2) が提供できるより、より完全で囲い込まれた環境を作成するために jail(2) を使用することができます。 jail (刑務所) は、スーパユーザ特権があるプロセスを含んで、すべてのプロセスをその環境の内側に制限します。

POSIX.1e 拡張で説明される、きめの細かい特権は、現在の進行中の作業であり、 TrustedBSD プロジェクトの活動の焦点です。 http://www.TrustedBSD.org/ で詳しい情報を見つけることができます。

信頼

プログラムはそれらが実行される環境に関して仮定するべきではありません。これは、プログラムで制御できない他のものに共通して、ユーザ入力、シグナル、環境変数、システムリソース、プロセス間通信、と共有メモリを含んでいます。それらは、無効のデータのすべての形式を検出することができると仮定するべきではありません。代わりに、それらは、確信しているフィルタリングを使用して、安全であることが知られている入力の特定の部分集合のみを許すべきです。これは管理者がファイアウォールに適用するべきであるのと同じ論理であり、すなわち、デフォルトで拒否して、受け付けられるものを指定します。

競合条件

競合条件はイベントに関係するタイミングによって引き起こされる変則的な振る舞いです。プログラムは特定のイベントが別のものの前に起こると仮定するべきではありません。競合条件の最も一般的な原因は、シグナル、アクセスチェック、とファイルの読み込みです。シグナルは本来非同期であるので、それらを処理している間は特別な注意を払わなければなりません。その時々でファイルを移動して、変更することができるとき、連続した不可分でない操作でアクセスをチェックする試みは、非常に悪い考えです。 access(2)open(2) のシーケンスを使用する代わりに、 seteuid(2) を使用し、次に、直接 open(2) を呼び出してください。あらかじめ、適切に umask(2) を設定してください。

作者

Eric Melville <eric@FreeBSD.org>は、 Murray Stokely <murray@FreeBSD.org>によって書かれた FreeBSD Developer's Handbook の章に基づいて元々この文書を書きました。
June 3, 2001 FreeBSD