【PHP8.x】putenv関数の使い方

作成日: 更新日:

putenv関数は、環境変数の値を設定、または既存の環境変数を変更する関数です。環境変数とは、スクリプトが実行されているオペレーティングシステムの環境に存在する、名前と値のペアからなる情報です。この関数には、"変数名=値"という形式の文字列を引数として渡します。例えば、putenv("APP_MODE=development") のように記述することで、APP_MODE という名前の環境変数に development という値を設定できます。この関数で設定された環境変数は、現在のPHPスクリプトの実行期間中のみ有効であり、スクリプトが終了するとその値は破棄されます。Webサーバー環境では、この設定はリクエストの処理が完了するまで維持されます。設定した値は、同じスクリプト内で getenv() 関数やスーパーグローバル変数 $_ENV を使って取得することが可能です。また、このスクリプトから呼び出された子プロセス(外部コマンドなど)は、設定された環境変数を引き継ぎます。関数の実行に成功した場合は true を、失敗した場合は false を返します。

基本的な使い方

構文(syntax)

putenv(string $assignment): bool

引数(parameters)

string $assignment

  • string $assignment: 環境変数の設定内容を指定する文字列。NAME=VALUE の形式で指定します。

戻り値(return)

bool

環境変数に文字列を設定できた場合は true を、失敗した場合は false を返します。

サンプルコード

PHP putenv() のセキュリティリスクをデモする

<?php

/**
 * putenv関数のセキュリティ上のリスクを示すデモンストレーション。
 *
 * putenv() 関数は環境変数を設定しますが、外部からの入力で PATH などの
 * 環境変数を操作されると、意図しないコマンドが実行されるセキュリティ上の
 * 脆弱性 (PATHインジェクションなど) につながる可能性があります。
 * このコードは、その概念を教育目的で示します。
 * (このデモンストレーションはUNIX系システムを想定しています。)
 */
function demonstratePutenvExploitRisk(): void
{
    echo "=== putenv() セキュリティリスクのデモンストレーション ===\n\n";

    // オリジナルのPATH環境変数を保存
    $originalPath = getenv('PATH');
    echo "現在のPATH環境変数: " . ($originalPath !== false ? $originalPath : '[未設定]') . "\n\n";

    // 一時的な「悪意のある」実行パスを作成
    $maliciousPath = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'malicious_bin';
    if (!is_dir($maliciousPath) && !mkdir($maliciousPath, 0755, true)) {
        echo "エラー: 悪意のあるパスを作成できませんでした。\n";
        return;
    }

    // 偽の 'ls' スクリプトを作成
    // UNIX系システムでは、このスクリプトが本来のlsよりも優先して実行される
    $fakeLsScript = $maliciousPath . DIRECTORY_SEPARATOR . 'ls';
    $scriptContent = "#!/bin/sh\necho '!!! WARNING: Fake ls executed from malicious path !!!'\n";
    if (file_put_contents($fakeLsScript, $scriptContent) === false) {
        echo "エラー: 偽の 'ls' スクリプトを作成できませんでした。\n";
        rmdir($maliciousPath);
        return;
    }
    chmod($fakeLsScript, 0755);

    echo "一時的な悪意のあるパスを作成しました: " . $maliciousPath . "\n";
    echo "偽の 'ls' スクリプトを作成しました: " . $fakeLsScript . "\n\n";

    // PATH環境変数を変更し、悪意のあるパスを最優先にする
    echo "PATH環境変数を変更中... (putenv('PATH=$maliciousPath" . ($originalPath !== false ? ":$originalPath" : '') . "'))\n";
    if (putenv("PATH=$maliciousPath" . ($originalPath !== false ? ":$originalPath" : ''))) {
        echo "PATH環境変数の設定に成功しました。\n";
        echo "新しいPATH環境変数: " . getenv('PATH') . "\n\n";
    } else {
        echo "PATH環境変数の設定に失敗しました。\n";
        // クリーンアップ
        unlink($fakeLsScript);
        rmdir($maliciousPath);
        return;
    }

    // `ls`コマンドを実行してみる
    // 通常であればシステム標準のlsが実行されるが、ここでは偽のlsが実行されるはず
    echo "外部コマンド 'ls' を実行します (shell_exec('ls')):\n";
    $output = shell_exec('ls');
    echo "--- コマンド出力開始 ---\n";
    echo $output;
    echo "--- コマンド出力終了 ---\n\n";

    // 元のPATH環境変数に戻す
    echo "PATH環境変数を元に戻します... (putenv('PATH=" . ($originalPath !== false ? $originalPath : '') . "'))\n";
    if (putenv("PATH=" . ($originalPath !== false ? $originalPath : ''))) {
        echo "PATH環境変数を元に戻しました。\n";
        echo "現在のPATH環境変数: " . getenv('PATH') . "\n\n";
    } else {
        echo "PATH環境変数を元に戻すのに失敗しました。\n";
    }

    // クリーンアップ
    echo "一時ファイルをクリーンアップ中...\n";
    unlink($fakeLsScript);
    rmdir($maliciousPath);
    echo "クリーンアップが完了しました。\n\n";

    echo "警告: putenv() の引数がユーザー入力に基づいて生成される場合、\n";
    echo "環境変数を操作され、意図しないコマンド実行などの重大なセキュリティリスクが生じます。\n";
    echo "外部からの入力を使って putenv() を呼び出す場合は、厳重な検証とサニタイズが不可欠です。\n";
}

// デモンストレーションを実行
demonstratePutenvExploitRisk();

PHPのputenv関数は、指定された文字列$assignment(例えば「PATH=/usr/local/bin」のような「変数名=値」の形式)を用いて環境変数を設定する機能を提供します。この関数は、設定が成功すればtrueを、失敗すればfalseを戻り値として返します。

提供されたサンプルコードは、putenv関数が持つセキュリティ上のリスク、特に「PATHインジェクション」と呼ばれる脆弱性の概念を教育目的で示しています。通常、システム上でコマンド(例: ls)が実行される際、PATH環境変数に設定されたディレクトリの順序で実行ファイルが検索されます。このデモンストレーションでは、一時的に「悪意のある」ディレクトリを作成し、その中に本来のコマンドと同じ名前(ls)の偽のスクリプトを配置します。

その後、putenv関数を使ってPATH環境変数を意図的に変更し、この悪意のあるディレクトリがシステム標準のパスよりも優先して検索されるように設定します。その結果、shell_exec('ls')のようなコマンドを実行すると、システム本来のlsコマンドではなく、作成した偽のスクリプトが誤って実行されてしまう様子が示されます。これは、もし外部からの入力によってPATHなどの環境変数が操作されると、攻撃者が意図しないプログラムを実行させることが可能になる重大なセキュリティリスクであることを意味します。putenv関数を外部からの入力値と組み合わせて使用する際は、厳重な検証とサニタイズが不可欠です。

putenv()関数は環境変数を設定しますが、サンプルコードが示すように、ユーザー入力など外部からの値を直接引数に使うと、特にPATH環境変数の操作により、意図しないコマンドが実行されるPATHインジェクションという重大なセキュリティリスクにつながります。このコードは脆弱性のデモンストレーションであり、実運用では絶対にこのような利用は避けてください。やむを得ず環境変数を設定する場合は、引数に対する厳格な検証とサニタイズを徹底し、変更がもたらす影響範囲を十分に理解することが不可欠です。

PHPでputenv()getenv()を使う

<?php

/**
 * Demonstrates the use of putenv() to set, modify, and unset environment variables
 * and getenv() to retrieve their values.
 *
 * putenv() affects the environment variables for the current PHP process
 * and any child processes it spawns. It does not affect the parent process
 * or other unrelated processes.
 */
function demonstrateEnvironmentVariables(): void
{
    echo "--- Demonstrating putenv() and getenv() ---\n\n";

    // Define a unique name for our test environment variable
    $variableName = 'PHP_DEMO_ENV_VAR';

    // --- 1. Set a new environment variable ---
    $initialValue = 'HelloFromPHP';
    // The argument format for putenv() is "VAR_NAME=VALUE"
    $assignment = "$variableName=$initialValue";

    echo "1. Attempting to set environment variable: '$assignment'\n";
    if (putenv($assignment)) {
        echo "   Successfully set '$variableName'.\n";
    } else {
        echo "   Failed to set '$variableName'.\n";
    }

    // Retrieve and display the value using getenv()
    $retrievedValue = getenv($variableName);
    echo "   Value of '$variableName' using getenv(): " .
         ($retrievedValue !== false ? "'$retrievedValue'" : "Not set (false)") . "\n\n";


    // --- 2. Update the environment variable ---
    $updatedValue = 'UpdatedValueByPHP';
    $newAssignment = "$variableName=$updatedValue";

    echo "2. Attempting to update environment variable: '$newAssignment'\n";
    if (putenv($newAssignment)) {
        echo "   Successfully updated '$variableName'.\n";
    } else {
        echo "   Failed to update '$variableName'.\n";
    }

    // Retrieve and display the updated value
    $retrievedValue = getenv($variableName);
    echo "   New value of '$variableName' using getenv(): " .
         ($retrievedValue !== false ? "'$retrievedValue'" : "Not set (false)") . "\n\n";


    // --- 3. Unset (remove) the environment variable ---
    // According to PHP documentation, passing an empty string as the assignment
    // parameter (e.g., "VAR_NAME=") will unset the environment variable.
    $unsetAssignment = "$variableName=";

    echo "3. Attempting to unset environment variable: '$unsetAssignment'\n";
    if (putenv($unsetAssignment)) {
        echo "   Successfully unset '$variableName'.\n";
    } else {
        echo "   Failed to unset '$variableName'.\n";
    }

    // Attempt to retrieve the value after unsetting.
    // getenv() returns false if the variable is not set in the environment.
    $retrievedValue = getenv($variableName);
    echo "   Value of '$variableName' after unsetting using getenv(): " .
         ($retrievedValue !== false ? "'$retrievedValue'" : "Not set (false)") . "\n";
    echo "   (Note: 'Not set (false)' indicates the variable has been successfully removed from the environment.)\n\n";

    echo "--- End of demonstration ---\n";
}

// Execute the demonstration function
demonstrateEnvironmentVariables();

このPHPサンプルコードは、環境変数を操作するための putenv 関数と getenv 関数の使い方を解説しています。

putenv 関数は、PHPスクリプトが実行されている環境に新しい環境変数を追加したり、既存の値を変更したりするために使用します。引数には "変数名=値" という形式の文字列を渡します。処理が成功すると true を、失敗すると false を返します。

一方、getenv 関数は、指定した名前の環境変数の値を取得します。引数に環境変数名を文字列で渡すと、その値が文字列として返されます。もし指定した環境変数が存在しない場合は false が返されます。

サンプルコードでは、まず putenv を使って PHP_DEMO_ENV_VAR という名前の環境変数を設定し、getenv でその値が正しく取得できることを確認しています。次に、同じ変数名に対して再度 putenv を実行し、値が更新されることを示しています。最後に、"変数名=" という形式で putenv を呼び出すことで、環境変数が削除(設定解除)されることを実演しています。削除後、getenvfalse を返すようになります。このように、二つの関数を組み合わせることで、スクリプトの実行中に環境変数を動的に設定、取得、削除することが可能です。

putenv()関数は、「変数名=値」の形式で文字列を引数に指定し、環境変数を設定・更新します。値を空のまま「変数名=」とすると、その環境変数を解除できます。しかし、この設定は現在のPHPプロセスとその子プロセスにのみ影響し、システム全体や他のプロセスには影響しない点に注意が必要です。putenv()の実行結果やgetenv()で値を取得した際は、戻り値(成功ならtrue、失敗ならfalse、またはgetenv()の場合は値が存在しないときにfalse)を必ず確認し、正しく処理が行われたかを検証するようにしましょう。これにより、意図しない動作を防ぎ、安全なコード運用につながります。

【PHP8.x】putenv関数の使い方 | いっしー@Webエンジニア