次のページ 前のページ 目次へ

7. 他のリソースの呼び出しの際には注意する

7.1 呼び出しの際に正しい値だけを使う

他のプログラムの呼び出しは,全ての引数が正しくかつ期待されている値であ る場合に限って許すこと. これは見た感じよりも難しいことである.なぜなら,おかしな方法で低レベル 関数を呼び出しているかもしれないライブラリ関数やコマンドがたくさん存在 するからである. 例えば,popen(3) や system(3) などのシステムコールはコマンドシェルを呼 び出す方法で実装されているので,シェルのメタ文字の影響を受けてしまう. 同様に,execlp(3) と execvp(3) はシェルを呼び出すことがある. 多くのガイドラインでは,popen(3), system(3), execlp(3), execvp(3) の使 用は絶対に避け,C でプロセスを立ち上げる時には直接 execve(3) を使うこ とを勧めている[Galvin 1998b]. 同じように,Perl やシェルのバッククォート記号(`)もコマンドシェルを呼び 出す.

この問題で一番悪質な例は,シェルのメタ文字である. Linux の標準のコマンドシェルは多くの文字を特別扱いする. このような文字がシェルに送られた場合,その文字をエスケープしていなけれ ば特殊な処理が行われる.この動作を利用してプログラムを破ることが可能で ある. WWW Security FAQ [Stein 1999, Q37] によると,このようなメタ文字は以下 の通りである:

& ; ` ' \ " | * ? ~ < > ^ ( ) [ ] { } $ \n \r

これらの文字のどれかを忘れていると悲惨なことになる可能性がある.例えば, 多くのプログラムはバックスラッシュをメタ文字として省略する[rfp 1999]. 「全ての入力を検証する」の章で説明したように,望ましいアプローチは, 少なくともこれらの文字が入力に現われたら即座にエスケープすることである.

これに関連する問題として,NIL 文字(文字 `0')が困った影響をもたらす可能 性がある. C/C++ のほとんどの関数は,NIL 文字は文字列の終わりを表すものとしている が,他の言語(Perl や Ada95 等)では NIL 文字を含む文字列を扱うことがで きる. 多くの関数やシステムコールは C の慣習に従っているので,チェックしたも のが実際に使われるものと異なってしまうことになる[rfp 1999].

他のプログラムを呼び出すときやファイルを参照するときには,必ず絶対パス で(/usr/bin/sort)指定すること. プログラムを呼び出す場合にこのような指定を行うと,PATH 変数が正しく設 定されていなくても「間違った」コマンドを呼ぶことがなくなる. 他のファイルを参照する場合にも,開始ディレクトリを「間違う」問題を減ら すことができる.

7.2 システムコールの戻り値は全てチェックする

エラー状態を返せるシステムコールを呼び出す場合には必ず,エラー状態を チェックしなければならない. その理由のひとつは,ほとんど全てのシステムコールはシステムのリソースを 制限する必要があるが,ユーザはいろいろな方法でリソースに影響を与えられ ることである. setuid/setgid されたプログラムには,setrlimit(3) や nice(2) といったシ ステムコールを使って制限を設定するとよい. サーバプログラムや CGI スクリプトを外部から使うユーザは,大量の リクエストを同時に送るだけでシステムのリソースを食い潰すことができるか もしれない. エラーを無難に処理できないのであれば,先に説明したフェールオープンな対 応を行うこと.


次のページ 前のページ 目次へ