
Эксплойт доказательства концепции для CVE-2024-52301, демонстрирующий манипуляцию окружением в Laravel через внедренные параметры URL, с подробным анализом кода и шагами воспроизведения.
Эта уязвимость основана на уязвимости CVE-2024-50340
Опция register_argc_argv должна быть включена в файле конфигурации PHP (php.ini). Этот параметр загружает аргументы командной строки и параметры запроса в $_SERVER['argv'].
https://www.php.net/manual/en/ini.core.php#ini.register-argc-argv
//Illuminate\Foundation\Application
public function detectEnvironment (Closure $callback)
{
$args = $_SERVER['argv'] ?? null;
return $this['env'] = (new EnvironmentDetector)->detect($callback, $args);
}
Назначение: Этот метод определяет окружение, обращаясь к $_SERVER['argv'], который содержит аргументы командной строки, и затем передает управление классу EnvironmentDetector.
Источник уязвимости: Полагаясь на $_SERVER['argv'], любые внедренные параметры URL (например, ?--env=dev) могут манипулировать $_SERVER['argv'] так, что он будет содержать ["--env=dev"]. Этот массив передается непосредственно в метод detect, что потенциально позволяет злоумышленнику контролировать окружение.
//Illuminate\Foundation\EnvironmentDetector
public function detect(Closure $callback, $consoleArgs = null)
{
if ($consoleArgs) {
return $this->detectConsoleEnvironment($callback, $consoleArgs);
}
return $this->detectWebEnvironment($callback);
}
Назначение: Метод detect определяет, предоставлен ли $consoleArgs (массив argv). Если да, он вызывает detectConsoleEnvironment для обработки обнаружения окружения на основе консоли; в противном случае вызывает detectWebEnvironment для HTTP-запросов.
Путь к уязвимости: Если $_SERVER['argv'] включает внедренные значения, такие как --env=dev, это приводит к вызову detectConsoleEnvironment, который обрабатывает аргументы и может переключить приложение в другое окружение.
//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);
}
Назначение: Этот метод проверяет, присутствует ли аргумент --env среди консольных аргументов.
Механизм: Он вызывает getEnvironmentArgument, чтобы увидеть, указывает ли какой-либо из аргументов argv окружение. Если --env предоставлен, этот метод возвращает указанное значение окружения, обходя вызов detectWebEnvironment.
//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));
}
}
}
Назначение: Этот метод анализирует argv для поиска аргумента --env. Механизм:
Если --env найдено как отдельный флаг, возвращается следующий аргумент как значение окружения.
Если используется синтаксис --env= (например, --env=dev), извлекается и возвращается окружение (в данном случае dev).
Конфигурация окружения:
Файл .env содержит APP_ENV=development, поэтому по умолчанию приложение установлено в окружение разработки.
@production
<p>Production environment</p>
@endproduction
@env ('local')
<p>Local environment</p>
@endenv
Доступ по умолчанию (http://localhost):
Поскольку APP_ENV установлен в development и аргумент --env не внедрен, ни директива @production, ни @env('local') не совпадают.
Результат: Вывод пуст.
Внедренный аргумент для Production (http://localhost?--env=production):
С ?--env=production в URL, $_SERVER['argv'] манипулируется так, чтобы содержать ["--env=production"].
Это запускает механизм определения окружения Laravel, устанавливая окружение в production.
Результат: Директива @production выводит <p>Production environment</p>.
Внедренный аргумент для Local (http://localhost?--env=local):
С ?--env=local, $_SERVER['argv'] включает ["--env=local"], изменяя окружение на local.
Результат: Директива @env('local') выводит <p>Local environment</p>
Эта уязвимость не позволяет изменять окружение внутри функции config. Вместо этого она затрагивает только настройку окружения внутри класса Application.
Таким образом, хотя директивы Blade и другие части кода полагаются на класс Application для определения окружения, код, использующий функцию config, не подвержен этой уязвимости.