Skip to content
Ahmed Al Ahmed
Go back

CVE-2024-52301 - Laravel Framework Environment Manipulation

Hello — I know, I know, this is an old vulnerability, but I still want to share it with you. In this article, you will learn why this vulnerability exists, how to exploit it, how to fix it, and the reasons behind it. So let’s get started.

CVE-2024-52301

Laravel Framework Environment Manipulation is a high-severity vulnerability that allows an attacker to manipulate the environment that the application is running in.

As usual, we have at least two environments such as dev and prod. With this vulnerability, we can force the app to run in any environment we want.

It does not allow us to change the environment in the .env file or in the application settings — it only affects the APP_ENV variable.

Reasons

Why does this vulnerability happen in the first place?

Technically, it is a bug in the detectEnvironment function in the Application class. It delegates and passes all global variables to override the environment when the PHP option register_argc_argv is On.

This option allows PHP to register the $argc and $argv variables in the global scope of the application.

By trusting the $argc and $argv variables and passing them to the Application class, an attacker can craft a payload like --env=prod to force the app to run in the prod environment. More dangerously, by brute-forcing other modes such as local, dev, or testing, we are most likely exposing full debug traces — something developers typically enable in non-production environments.

Vulnerable Versions

Lab

Let’s see this vulnerability in action.

<h1>Welcome to CVE-2024-52301</h1>

@if(app()->environment('prod'))
    <h2>Production - Secured Area</h2>
@else
    <h2>Sandbox - Allow Access to Admin & Data</h2>
@endif
Route::get('/', function () {
    return view('test-env');
});

image

image

image

Digging Deeper

Looking at src/Illuminate/Foundation/Application.php, we can find the detectEnvironment function:

public function detectEnvironment(Closure $callback)
{
    $args = $_SERVER['argv'] ?? null;
    return $this['env'] = (new EnvironmentDetector)->detect($callback, $args);
}

The line $args = $_SERVER['argv'] ?? null; is vulnerable when the PHP option register_argc_argv is On, because it accepts all user-controlled arguments and passes them to the Application class.

The detectConsoleEnvironment function is called because the second parameter of the detect function is $args. The environment returned from detectConsoleEnvironment is then used to overwrite $this['env'].

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);
}

In the patched versions, a validation check that ensures the application is running as a console application is added before trusting $_SERVER['argv']:

public function detectEnvironment(Closure $callback)
{
    $args = $this->runningInConsole() && isset($_SERVER['argv'])
        ? $_SERVER['argv']
        : null;
    return $this['env'] = (new EnvironmentDetector)->detect($callback, $args);
}

I hope you enjoyed this article. If you have any questions, corrections, or suggestions, please don’t hesitate to reach out.


Share this post on:


Next Post
How I passed HTB Certified Penetration Testing Specialist