9.8. PHP

SecureReality は、非常に興味をそそる「A Study In Scarlet - Exploiting Common Vulnerabilities in PHP」[Clowes 2001]」というドキュメントを出して いて、PHP 4.1.0 以前のバージョンにターゲットを当て、安全なプログラムを 書く上で問題となる点のいくつかを論じています。 このドキュメントでは「努力したとしても、PHP で安全なアプリケーションを 書くのは非常に難しい(PHP のデフォルトの設定では)」と結論づけています。

どんな言語にもセキュリティ上の問題はありますが、PHP には安全上おそらく 他の大半の言語と比べて際だった問題点が 1 つあります。それは名前空間に データをロードする方法です。 デフォルトで PHP (バージョン 4.1.0 もしくはそれよりも古いバージョン)は、 Web 上の PHP へと送られる環境変数とその値をすべて、自動的に同じ名前空間 (グローバル変数)にロードします。通常の変数もそこにロードします。したがって、 攻撃者は自由に変数やその値を設定可能で、PHP プログラムがあえて再設定しない 限り、その値はそのままになっています。 さらに PHP は最初に変数を作る要求があった時に、デフォルトの値を設定します。 したがって、PHP プログラムは変数を初期化しないのが普通です。 変数を設定するのを忘れると、PHP は報告をあげますが、デフォルトではそうなって いません。ただ忘れてはいけない点は、これが単にエラーの報告であって、攻撃者 が普通でない方法を見つけて、エラーを起こすことを止められないことです。 つまり PHP はデフォルトでは、プログラムが攻撃者に対して特別に注意を払って 攻撃者を負かさない限り、プログラムにある変数すべての値のコントロールを完全に 許してしまっています。 プログラムが動きだすと、これらの変数を再設定できますが、どの変数の再設定に 失敗しても(はっきりとしていなくても) PHP プログラムの脆弱さがあらわになる でしょう。

たとえば、下記の PHP プログラム(Clowes 氏による例)は、パスワードを知っている 人にだけ何か重要な情報を与えようとしていますが、攻撃者は Web ブラウザで 「auth」に値を設定し、認証チェックの効力を失わせられます。
 <?php
  if ($pass == "hello")
   $auth = 1;
  ...
  if ($auth == 1)
   echo "some important information";
 ?>

私の他にも、このとりわけ危険な問題を批判する人が大勢います。PHP は広範に 使われているので、問題は深刻です。 結局、簡単に使える言語は、簡単に安全なプログラムを書けるようになっています。 PHP では、設計時に見通しを誤ってしまったこの機能を無効にできます。 「register_globals」を「off」にすればよいのです。しかし、PHP の 4.1.0 より 新しいバージョンでは、デフォルトで「on」になります。4.1.0 以前は register_globals を off にして使用するのは困難です。 PHP の開発者は、PHP 4.1.0 のアナウンスの中で下記のように述べています。 「PHP の次の準メジャー・バージョンアップでは、デフォルトで register_globals は off になってインストールされます」

「register_globals」が「on」になっている PHP は、重要なプログラムにとって 危険な選択となります。いとも簡単に安全でないプログラムが書けるからです。 しかし、「register_globals」が「off」になりさえすれば、PHP は開発するのに なかなか使える言語になります。

デフォルトを安全にするには、「register_globals」を「off」にすること、 ユーザが外部の情報源から得る入力に対して設定を行い、制限をかけやすく できる機能を追加することが挙げられます。 Web サーバ(Apache のような)は、独自に PHP を安全に設定してインストールでき ます。 ユーザが受け取りたい入力変数が簡単にリストアップできるようなルーチンを PHP ライブラリに入れられます。 関数には、変数が持たなければならないパタンおよび変数が強制されなければ ならない型をチェックするものがあります。 私の考えでは、現状、安全な Web 開発に PHP を採用するのはどうかと思います (register_globals が on なので)。しかし、ちょっとした修正をすれば、手ごろな 手段になります。

PHP を使おうと決めたなら、ここでアドバイスをいくつか書いておきます(これら のアドバイスの多くは、Clowes 氏が提起している問題への対処方法をベースにして います)。

【訳註:原著では、オブジェクト指向スクリプト言語 Ruby にふれていません。 訳註として簡単に Ruby のことにふれたいと思います。 Ruby にはセキュリティモデルが存在しています。 大きくわけて 2 つの危険なケースを想定しています。 1 つは、信頼できないデータを扱う場合、もう 1 つは、信頼できないプログラムを 扱う場合です。 このケースに対応して、レベル 0 から 4 までのセキュリティ・レベルを $SAFE というグローバル変数を用いてスレッド単位に設定できます。 ただし注意していただきたいのは、C で書かれた組み込みライブラリ、拡張ライブラリ いずれとも、すべての汚染をチェックしている保証がない点です。 汚染をチェックするのは、作成者にまかされています。 セキュリティモデルの詳細については、 「オブジェクト指向スクリプト言語 Ruby リファレンスマニュアル」の「セキュリティモデル」 を参照してください】