
CVE-2026-34038: حقن أوامر عن بُعد يتطلب مصادقة في Coolify
يحتوي هذا المستودع على توثيق وتحليل لثغرة CVE-2026-34038، وهي ثغرة حرجة لحقن الأوامر في Coolify.
تتيح ثغرة حقن أوامر عن بُعد بعد المصادقة (CWE-78) في Coolify للمستخدمين الحاصلين على صلاحيات "write" على التطبيق تحقيق تنفيذ التعليمات البرمجية عن بُعد (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
يفتقر الإدخال إلى تهريب (escaping) صحيح لأوامر الصدفة أو إلى التحقق من صحة الإدخال، مما يسمح بحقن أوامر مباشر باستخدام المحارف الوصفية مثل ; و&& والأنابيب.
// 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 (الأسطر 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.