
CVE-2024-52301에 대한 개념 증명 익스플로잇: 주입된 URL 매개변수를 통해 Laravel에서 환경 조작을 시연하며, 상세한 코드 분석 및 재현 단계 포함
이 취약점은 CVE-2024-50340 취약점을 기반으로 합니다.
PHP 설정 파일(php.ini)에서 register_argc_argv 옵션이 활성화되어 있어야 합니다. 이 설정은 명령줄 인수와 쿼리 매개변수를 $_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를 호출하여 콘솔 기반 환경 감지를 처리하고, 그렇지 않으면 HTTP 요청에 대해 detectWebEnvironment를 호출합니다.
취약점 경로: $_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가 설정되어 있어 기본적으로 애플리케이션은 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):
URL에 ?--env=production이 포함되면 $_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 함수를 사용하는 코드는 이 취약점의 영향을 받지 않습니다.