安全を考えてPHPの実行時設定を調整する:仕事で使える魔法のLAMP(37)
PHPを初期設定のまま使うと、いろいろ問題が起こる可能性があります。今回は、問題の発生を未然に防ぐ設定法をいくつか紹介します。(編集部)
初期設定のままでは良くないところもある
ここ数回はPHP実行時の設定について解説しています。実行時設定を変更する方法として、PHPの設定ファイル(以下php.iniファイル)に設定を記述する方法と、Apache HTTP Server(以下Apache)の設定ファイルにPHPの設定を記述する方法の2つがあり、前回はその使い分けについて解説しました。
サーバ全体で標準の設定値としたいものはphp.iniファイルに、バーチャルホストやURLごとに変更したいものはApacheの設定ファイルに記述する、という使い分けの指針も示しました。
今回は、php.iniで設定できる項目、つまりサーバ全体にかかわる設定項目の中でも、初期設定のままにしておくことがあまり適切でないものや、設定値を明示した方が、管理者にとって分かりやすくなる項目について説明します。まずは、安定性にかかわる部分について解説します。
使用できるメモリの量を制限
前回、前々回に紹介した設定項目「memory_limit」から説明しましょう。この設定項目はPHPのスクリプトが利用できるメモリ容量の最大値を決めるものです。初期設定では128Mbytesになっていますが、この設定の意味を考えると、小さくしておいた方がよいです。
利用可能なメモリの量を制限するのは、スクリプトの作成ミスなどによって大量のメモリを消費してしまうことを防ぐためです。あるプロセスが大量にメモリを消費してしまうと、Apacheに接続しているほかのユーザーもメモリ不足の影響を受けてしまうことがあります。従って、標準の設定ではある程度小さくしておき、プログラムのミスなどの欠陥を検出しやすくしておくのがよいのです。
あらかじめ大量にメモリを消費することが分かっている処理があるときは、Apacheの設定ファイルを利用したり、PHPの関数を利用することで、その部分だけ最大メモリ量を大きくすることもできます。もちろんこれは、部分的に設定を変更することの影響をしっかり把握してから慎重に設定しなければなりません。
具体的に、どれくらいのメモリを利用可能と設定するか分かりにくいとおっしゃる方もいるでしょう。少なめにしたいときは16M〜32Mbytes、多めにするときは64M〜128Mbytesといったところが目安になると思います。もちろん、利用するフレームワークやアプリケーションによっては、最低値の指定がある場合も考えられます。
なお、設定した値以上のメモリを使用するとFatal Error(致命的なエラー)となって、その時点でプログラムが停止します。これを嫌って、本番環境では「無制限」としてしまうこともあります。無制限と設定するには、設定値を「-1」とします。もちろん、無制限に設定するときは開発環境などで十分にテストをしておく必要があります。
設定した最大メモリ量を完全に消費すると、図1のような画面が現れます。
図1のエラーは、次のような単純なPHPのスクリプトで再現できます。ループで配列に値を設定することを繰り返し、巨大な配列を作ってしまうのです。
<?php for ($i=0; $i<10000000; $i++) { $a[$i] = $i; } ?>
スクリプト実行時間を制限する
設定項目「memory_limit」は、使用できるメモリ量を制限するものでした。これに対して、スクリプト実行時間を制限するのが、設定項目「max_execution_time」です。これは、memory_limitと同様、ミスなどによって処理が終了せずに延々と続いてしまうことを防ぐために使います。
スクリプトの実行が続いていると、プロセッサ時間を消費し続けます。これが延々と続くと、Apacheに接続しているほかのユーザーのために使わなければならないプロセッサ時間もなくなってしまい、悪影響を与えることになります。
memory_limitと同様に、あらかじめ処理に時間がかかることが分かっているスクリプトを実行するときは、設定値を大きくすることもできます。ただし、スクリプトを実行している間は、ユーザーのWebブラウザから見ると待ち状態が続いていることになるので、ユーザーが待ちきれずにWebブラウザの「中止」ボタンを押してしまうことも考えられます。さらに、Apacheの設定にはタイムアウトになるまでの時間を設定する項目があります。この設定値を超えてしまうと、PHPの設定に関係なくスクリプトの処理が終了となってしまいます。
つまり、処理に時間がかかるからといって、単純にmax_execution_timeの設定値を大きくすることは得策ではありません。こういうときは、時間のかかる処理をバックグラウンドで実行するようにして、WebページをすぐにWebブラウザに返すようにするのが良いでしょう。その後、Webページ上のJavaScriptからサーバに対して処理が完了しているかどうかを問い合わせるようにします。
max_execution_timeの設定にはもう1つ注意してほしい点があります。この設定で制限できる実行時間とは、PHPスクリプトの処理時間のみを指しています。例えば、データベースにアクセスしたときの応答が返ってくるまでの待ち時間などは含みません。あくまでPHPスクリプトの処理時間を限定するためのものです。データベースの反応が遅くなるときは、どの処理に時間がかかっているのかを検出する必要がありますが、これはMySQLの設定に進んだときに解説します。
max_execution_timeの初期設定値は30秒です。特別な事情がない限り、この設定値が妥当だと筆者は考えます。そして、制限をなくすには「0」と設定します。
PHPを使っているという事実を隠す
PHPは、初期設定のままではそのバージョン番号をHTTPのヘッダ情報に入れるようになっています。攻撃者から見ると、PHPのバージョンが攻撃の手掛かりになることもあります。従って、バージョン番号は公開しない方がよいでしょう。
さらに、第34回でも触れたように、PHPを使っていること自体を隠したい場合もあります。これを隠すには設定項目「expose_php」の値を「Off」にします。
また、第24回では、Apacheの設定ディレクティブ「ServerTokens」を使って、ApacheのバージョンをHTTPのヘッダ情報に入れないように設定しています。これも攻撃の手掛かりを与えないという同じ理由によるものでした。では、HTTPのヘッダ情報には、サーバの状態を示す情報がどれだけあるのかを見てみましょう。いったんServerTokensの設定を変更して、すべての情報をHTTPヘッダに表示するようにします。
ヘッダ情報を見るにはいくつか方法がありますが、今回はcurlコマンドを使います。curlは引数で指定したURLにアクセスして、データをダウンロードするコマンドです。「-I」を引数に指定するとヘッダ情報だけを表示させることができます。では、前回まで使っていたphpinfo()の実行結果を表示するURLにアクセスしてみましょう。
$ curl -I http://www3026ub.sakura.ne.jp/phpinfo.php HTTP/1.1 200 OK Date: Thu, 05 Jan 2012 03:10:43 GMT Server: Apache/2.2.21 (Unix) PHP/5.3.8 X-Powered-By: PHP/5.3.8 Content-Type: text/html
ヘッダの中に「X-Powered-By: PHP/5.3.8」という部分があります。X-で始まるヘッダは独自ヘッダです。「Server」ヘッダを見ると、Apacheのバージョンに加えてPHPのバージョンも分かります。ServerTokensの設定を完全表示にすると、ApacheのバージョンやOSに加えて、一部のApacheモジュールの情報もHTTPヘッダに流れるのです。
ではここで、PHPの設定ディレクティブであるexpose_phpをOffにして再度ヘッダを取得してみましょう。
$ curl -I http://www3026ub.sakura.ne.jp/phpinfo.php HTTP/1.1 200 OK Date: Thu, 05 Jan 2012 03:16:57 GMT Server: Apache/2.2.21 (Unix) Content-Type: text/html
「X-Powered-By」ヘッダが消え、「Server」ヘッダからもPHPの情報がなくなりました。これでヘッダの情報からは、サーバでPHPを使っているということが分からなくなりました。さらにServerTokensを最小表示に戻すと、次のようになります。
$ curl -I http://www3026ub.sakura.ne.jp/phpinfo.php HTTP/1.1 200 OK Date: Thu, 05 Jan 2012 03:20:22 GMT Server: Apache Content-Type: text/html
ApacheのバージョンやOSもHTTPヘッダからは読み取れなくなりました。攻撃者に与える情報を最小限にするという観点からすると、この状態が望ましいでしょう。
expose_phpの設定値をOffにすると、もう1つ動作に変化があります。phpinfo()を実行したときの結果を表示する画面からPHPのロゴ画像が消えるのです。expose_phpがOn(初期設定)であるときは、phpinfo()の実行結果は図2のようになります。
expose_phpの設定値をOffにして、phpinfo()を実行すると、結果を表示する画面からPHPのロゴが消えます(図3)。
これは、設定によって画像へのリンクが消えるというだけの話ではありません。この画像はPHPの実行環境に埋め込んであるもので、どんなPHPスクリプトであっても、URLの末尾に「?=PHPE9568F34-D428-11d2-A769-00AA001ACF42」という文字列を追加すると、このロゴを表示させることができるのです。phpinfo()を実行しないスクリプトであってもです。例えば先に紹介した、メモリを使い切ってしまうスクリプトの末尾にこの文字列を追加してもPHPのロゴを表示させることができます(図4)。
PHPの動作環境がこんな動きを見せることをご存じの方はどれだけいらっしゃるでしょうか? ロゴが表示できるだけで何か悪影響があるわけではないものの、こういった予期しない動作を止めるためにもexpose_phpはOffにしておきましょう。
ここまで解説した内容をphp.iniにまとめると、設定項目は次の通りになります。memory_limitなどの値についてはアプリケーションに応じて変更してください。
memory_limit = 32M max_execution_time = 30 expose_php = Off
次回は、リクエストデータをどう取り扱うかを決める設定項目について解説します。
- CMakeでMySQLをビルドしてみる
- MySQLのビルドに欠かせないCMakeを準備する
- いよいよMySQL編、ソースからビルドすべきか?
- PHPでセッションを利用するための設定
- クライアントがアクセスできる範囲を制限する
- エラーメッセージをどう扱うか?
- ファイルのアップロードを制限する
- リクエストデータを受け取る変数の扱い
- マジッククオート機能には頼らない
- 安全を考えてPHPの実行時設定を調整する
- Apacheの設定ファイルでPHPの設定を変える
- PHPの設定ファイルを作って配置してみる
- PHPスクリプトを実行できるようにする準備
- PHPエクステンション組み込みの仕上げ
- 単純なデータを管理するDBMを使えるようにする
- エクステンションの組み込み状況を確認する
- PHPでデータベースを使う準備をする
- XMLを処理できるようにする
- エクステンションを有効にしてビルドに挑戦!
- PHPテスト失敗の原因を追究する
- 早速PHPをビルド! そしてテスト!
- PHP編に突入! まずはソースをダウンロード
- 設定ファイルを作成してApacheを動作させる
- 設定ファイルや公開ドキュメントの配置を考える
- 1つのサーバに複数の仮想サーバ?
- Apacheの設定ファイルを記述する前に
- サードパーティのApacheモジュールをビルドする
- 認証DBにアクセスするライブラリを組み込む
- Apache同梱ソフトウェアに引数を渡してビルド
- OpenSSLをビルドしてApacheで利用する
- proxyやsslのモジュールを使ってみる
- ライブラリが足りなくてビルドできないときは?
- Apache HTTP Serverのビルドを始めよう
- configureでソフトウェア固有の設定を変更してみる
- configureの設定を変更してみる
- 配布パッケージの中身と、configureの役目を知る
- ダウンロードファイルが真正なものであるかを確認
- Makefileをいろいろ書き換えながらビルドしてみよう
- makeを使ってソフトウェアをビルドしてみよう
- ダイナミックリンクとスタティックリンク
- 「ビルド」という作業は何を指しているのか
- 公開鍵認証でsshを安全に使う
- sshを便利にする公開鍵暗号
- アクセス制限の設定とCentOSのアップデート
- サーバに接続して、一般ユーザーのアカウントを作る
- LAMP環境、自分で作りませんか?
Copyright © ITmedia, Inc. All Rights Reserved.