別のプログラムを呼び出す場合は、そのプログラムが常にパラメタとして有効かつ 事前に予想されている値だけを許可しているかを確認する必要があります。 これは言うよりもずっと困難なことです。と言うのも、様々なライブラリ関数や コマンドが、低レベルの関数を意外なやり方で呼び出しているかもしれないからです。 たとえば popen(3)や system(3)のようなシステムコールのいくつかは、コマンド シェルを呼び出すように実装されています。つまりシェルのメタキャラクタがこれら のシステムコールに影響をおよぼすことを意味します。 同様に execlp(3)や execvp(3)もシェルを呼び出すしくみになっています。 ガイドラインの多くは popen(3)、system(3)、execlp(3)と execvp(3)をまったく 使用しないように提案していて、プロセスを生成する場合には execve(3)を C 言語 から直接呼び出すように提案しています [Galvin 1998b]。 同様な方法で Perl や シェルのバッククォート(`)もコマンドシェルを呼び出します。
この問題の厄介な例のひとつにシェルのメタキャラクタがあります。 標準的な Linux のコマンドシェルは、解釈を特別に行うキャラクタがたくさんあり ます。 シェルにこれらのキャラクタが渡ると、エスケープされていなければシェルは特別に 解釈します。この方法を使ってプログラムがしばしば壊されます。 WWW Security FAQ [Stein 1999, Q37] によると、メタキャラクタは以下のものです。
& ; ` ' \ " | * ? ~ < > ^ ( ) [ ] { } $ \n \r
これらのキャラクタの内 1 つでも忘れると、悲惨なことになるかもしれません。 たとえば、プログラムの多くはバックスラッシュをメタキャラクタとして扱うことを 怠っています[rfp 1999]。 入力の検証を説明したセクションで論じましたが、対策として、これらのキャラクタ が入力されたらすぐにエスケープすることをお勧めします。
これと関連する問題として NIL キャラクタ(キャラクタの 0)が意外な影響を及ぼす ことがあげられます。 C や C++ の関数の大部分は、NIL キャラクタが文字列の終端の印と想定して いますが、他の言語(Perl や Ada95 など)の文字列を扱う関数は NIL を文字列の 一部として扱います。ライブラリやカーネルの呼び出しは C と同じ扱いを踏襲 していますので、チェックする内容と実際使用されることが一致していません [rfp 1999]。
他のプログラムを呼び出したり、ファイルを参照したりする時は、いつもフルパス (たとえば /usr/bin/sort のように)で指定するようにしてください。 こうすることで、「間違った」コマンドを呼び出す際に生じるエラーを無くすことが できるだけでなく、PATH 環境変数が間違って設定されていてもエラーを回避でき ます。 他のファイルの参照についても、「間違った」開始パスを指定した結果生じる問題 を減らせます。
システムコールでエラー状況を返せるものは、すべてそのエラー状態をチェックする 必要があります。 まず理由としてあげられるのは、システムコールのほとんどすべてが、制限をかけら れているシステム・リソースを対象としており、そのリソースに対してユーザは さまざまな方法で影響を与えることができてしまう点があります。 setuid/setgid されたプログラムには、setrlimit(3)や nice(2)のようなシステム コールを呼び出すことで、そのプログラムで使用するリソースに制限をかけること ができます。 サーバープログラムを利用する外部のユーザや CGI スクリプトは同時に多量のリクエ ストをサーバーに要求することで、リソースを食い潰すことができます。 エラーを適切に扱えていないならば、すでに述べた「フェイル・オープン」を参照 してください。