追記 (12/24)
PHP 5.4 以上でも register_globals と生きていくために $_SESSION のことも忘れてはいけない - Thanks Driven Life
セッションを扱う場合は ↓ だけでは対策が不十分なので ↑ もご参照下さい
PHP: グローバル変数の登録機能の使用法 - Manual
register_globalsをonとした場合、この機能により、HTMLフォームから投 稿される変数と同時に、あらゆる種類の変数がスクリプトに注入される ことになります。これは、PHPにおいては変数の初期化が不 要であるということにも関係し、安全でないコードを書くことが極めて容 易になるということを意味します。
経緯
そんなものあってはならない(憤怒)
方法
簡単に言うと register_globals
が提供している機能と同じことをすれば良いと思われます。
<?php function registerGlobals(array $variables) { foreach ($variables as $name => $value) { $GLOBALS[$name] = $value; } } function registerGlobalsWithMagicQuotesGpc(array $theVariables) { registerGlobals(array_map('addshales', $theVariables)); } function emulateRegisterGlobals() { $files = array(); foreach ($_FILES as $field => $info) { foreach ($info as $key => $value) { if ($key === 'tmp_name') { $name = $field; } else { $name = "${field}_${key}"; } $files[$name] = $value; } } registerGlobals($files); foreach (str_split(ini_get('variables_order')) as $variableName) { switch (strtolower($variableName)) { case 'e': registerGlobals($_ENV); break; case 'g': registerGlobalsWithMagicQuotesGpc($_GET); break; case 'p': registerGlobalsWithMagicQuotesGpc($_POST); break; case 'c': registerGlobalsWithMagicQuotesGpc($_COOKIE); break; case 's': registerGlobals($_SERVER); break; } } }
emulateRegisterGlobals()
を entry point (auto_prepend_file
で呼ばれる部分とか) にでも入れると良いでしょう。
解説
1. ひたすら $GLOBALS に叩きこむ
register_globals
は variables_order ディレクティブの値順に $GLOBALS
に値をセットしていきます。
今回は書いてませんが、おそらく variables_order
に同じ文字が2回以上出てきた場合はマージしない、という処理が必要だと思います。
php-src/php_variables.c at php-5.3.29 · php/php-src
2. $_FILES だけは特別扱い
詳しくはこちらをご覧下さい。
PHP における register_globals と $_FILES の関係について - Thanks Driven Life
3. magic_quotes_gpc も忘れてはいけない
もしも貴方が register_globals
と同時に magic_quotes_gpc を使っていた場合は、それも考慮する必要があるだろう。
まとめ
$_FILES
と、その他 EGPCS はどっちが優先なのか- ソース見る限りよくわからなかった。実際に動かすと EGPCS で上書きされていた気がする
とかおそらくいろいろ不足点あると思うので、これで完全にエミュレートできるとは限りませんが 完全にエミュレートしようと思わない優しい世界にしたい。
参考
- PHP: グローバル変数の登録機能の使用法 - Manual の User Contributed Notes
- エミュレートする勢も書き込んでる