
CVE-2026-34038: Coolify에서 인증된 원격 명령 주입
이 저장소는 CVE-2026-34038에 대한 문서와 분석을 포함합니다. 이는 Coolify의 심각한 명령어 삽입 취약점입니다.
Coolify에서 인증된 원격 명령어 삽입 취약점(CWE-78)으로 인해 애플리케이션 "쓰기" 권한을 가진 사용자가 **원격 코드 실행(RCE)**을 달성하고, 배포 로그를 통해 민감한 환경 변수(예: 데이터베이스 자격 증명, API 키)를 탈취할 수 있습니다. 빌드 환경이 Docker 소켓을 격리하더라도 가능합니다.
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:Hwrite (설정 업데이트) 및 read:sensitive (로그를 통해 탈취된 데이터 읽기)deploy 권한이 없는 토큰이 빌드를 트리거할 수 있는 메커니즘이 존재합니다.dockerfile_location 삽입파일: app/Jobs/ApplicationDeploymentJob.php
입력 값에 적절한 셸 이스케이프 또는 입력 검증이 부재하여 ;, &&, 파이프와 같은 메타 문자를 사용한 직접 명령어 삽입이 가능합니다.
// Lines 2976-2978: Traditional build with args
$build_command = $this->wrap_build_command_with_env_export(
"docker build {$this->buildTarget} --network {$this->destination->network} -f {$this->workdir}{$this->dockerfile_location} {$this->build_args} --progress plain -t $this->build_image_name {$this->workdir}"
);
// Lines 526: Also used in simple dockerfile deployment
executeInDocker($this->deployment_uuid, "echo '$dockerfile_base64' | base64 -d | tee {$this->workdir}{$this->dockerfile_location} > /dev/null"),
pre_deployment_command 실행파일: app/Jobs/ApplicationDeploymentJob.php (Lines 3882-3909)
기본적인 이스케이프 처리는 이루어지지만, 함수가 본질적으로 네이티브 셸 명령어를 실행하므로 데이터를 빌드 로그에 직접 덤프할 수 있습니다.
private function run_pre_deployment_command()
{
if (empty($this->application->pre_deployment_command)) {
return;
}
// ...
$cmd = "sh -c '".str_replace("'", "'\\''", $this->application->pre_deployment_command)."'";
$exec = "docker exec {$containerName} {$cmd}";
$this->execute_remote_command(
[
'command' => $exec,
'hidden' => true,
],
);
}
dockerfile_location 입력 검증 (ApplicationDeploymentJob.php에서):엄격한 정규 표현식을 사용하여 입력을 검증하고 셸 인수를 이스케이프합니다:
if ($this->application->dockerfile_location) {
if (!preg_match('/^[a-zA-Z0-9._\-\/]+$/', $this->application->dockerfile_location)) {
throw new \RuntimeException("Invalid dockerfile_location: contains forbidden characters");
}
if (str_contains($this->application->dockerfile_location, '..')) {
throw new \RuntimeException("Invalid dockerfile_location: path traversal detected");
}
$this->dockerfile_location = escapeshellarg($this->application->dockerfile_location);
}
bootstrap/helpers/api.php):'dockerfile_location' => [
'string',
'nullable',
'regex:/^[a-zA-Z0-9._\-\/]+$/',
'max:255'
],
docker_compose_location과 같은 동등한 필드를 감사합니다.