読者です 読者をやめる 読者になる 読者になる

Thanks Driven Life

日々是感謝

PHP 5.4 以上でも register_globals と生きていくために

追記 (12/24)

PHP 5.4 以上でも register_globals と生きていくために $_SESSION のことも忘れてはいけない - Thanks Driven Life

セッションを扱う場合は ↓ だけでは対策が不十分なので ↑ もご参照下さい


PHP: グローバル変数の登録機能の使用法 - Manual

register_globalsをonとした場合、この機能により、HTMLフォームから投 稿される変数と同時に、あらゆる種類の変数がスクリプトに注入される ことになります。これは、PHPにおいては変数の初期化が不 要であるということにも関係し、安全でないコードを書くことが極めて容 易になるということを意味します。

f:id:gongoZ:20141126222546p:plain

経緯

そんなものあってはならない(憤怒)

方法

簡単に言うと 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_globalsvariables_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 で上書きされていた気がする

とかおそらくいろいろ不足点あると思うので、これで完全にエミュレートできるとは限りませんが 完全にエミュレートしようと思わない優しい世界にしたい。

参考