PHP4.2.0(2003/05) から、register_globals の初期値が Off に変更されました。これにより、これまで稼動していたスクリプトや、書籍に記載されているサンプルコードが動かないといった現象に、戸惑った方もいらっしゃるのではないでしょうか。セキュリティー強化の為このような変更がなされた訳ですが、入門者や初心者にとっては、PHPの都合に振り回されているように感じるばかりです。いくらかでもこの初期値の変更を理解していただきたいと思い、register_globals = On の危険性と、安全なスクリプトを書く為のポイントをまとめてみました。
register_globals = On の場合、環境変数や GET・POST などのPHPの外部からくる値は全て、$変数名 という書式で使用することが出来ます。では、同じ変数名が存在した場合はどうなるのでしょう。これは、variables_order によって、優先順位が決まります。初期値は、”EGPCS”(Environment、GET、POST、Cookie、Server の頭文字)で、左から順番に変数に展開されますので、GET と POST に同じ名前の変数があった場合には、POST の値で上書きされることになりますす。
さて、実際にどのようなことが起こりえるかというと、テンポラリーファイルのパスを示す環境変数 “TEMP” があり、hoge.php というスクリプトは、この “TEMP” が示すディレクトリーの一時ファイル全てを削除するスクリプトだとします。ここでこのスクリプトに対して http://xxxxx.com/hoge.php?TEMP=%2F のようにアクセスすると、環境変数”TEMP” の値を GETメゾットの”TEMP” が上書きして、恐ろしいことに、ルートディレクトリのファイルを削除してしまいます。このようなスクリプトを誰でもアクセスできるところに置くことが一番の問題であり、実際には権限などの条件が揃わない限り削除されることはありませんが、値が上書きされることによって、思わぬところで値を改ざんされる危険性を含んでいるということです。
こうした上書きによる改ざんを防ぐには、register_globals = On の場合でも、PHP4.1.0 から採用されたスーパーグローバル変数($_GET、$_POST、$_COOKIE)を使うことが、最良の防御策となります。
register_globals = On の場合、初期化されていないグローバル変数を参照しているコードが実行される危険性があります。
例えば、パスワードが一致していればログオン時のコードを実行し、不一致であればエラーメッセージを表示する、以下のようなコードがあったとします。一見パスワードが一致しない限り、ログオン時のコードが実行されることはないように思いますが、このスクリプトに http://xxxxx.com/hoge.php?Logon=1 とアクセスすると、ログオン時のコードが実行されてしまいます。
<?php
if($password == ‘1234′) {
$Logon = true;
}
else {
echo “パスワードが違います。”;
}
if($Logon) {
// 以下、ログオン時の処理
echo “ログオンしました。”;
}
?>
スクリプトの中だけで使用するグローバル変数が、外部から初期化されることを想定していないために、このような問題が起こります。register_globals = On の場合、グローバル変数は、ユーザーに対してもグローバルであることを認識しておきましょう。
グローバル変数は、参照する前にあらかじめ初期化しておくことが、最良の対策です。例に挙げた logon.php ならば、スクリプトの始めに、$Logon = false; を記述しておけば、パスワードが一致しない限り、ログオン時のコードが実行されることはありません。
セキュリティーホールになる可能性が高い register_globals = On でも、次の事に留意していれば、安全なコードを書くことが出来ます。これらは、新たなコードを書く場合、既存のコードを修正する場合、register_globals = On/Off にかかわらず、プログラマが常に意識しておくべきポイントでもあります。