
IDOR + XSS مخزّن عبر كسر التفويض على مستوى الكائن في JoomGallery
JoomGallery ≤ 4.3.0 — مستخدم بدور المحرر يختطف أي صورة في المعرض ويخزّن حمولة XSS، مما يتيح الاستيلاء على جلسة المسؤول
تتحقق الدالة UserimageController::save() في JoomGallery من checkACL('edit', ...) بدلاً من checkACL('edit.own', ...). يمكن لمستخدم بدور المحرر إرسال طلب POST إلى task=userimage.save&id=N لأي صورة بغض النظر عن مالكها (IDOR — CWE-639). ولأن دور المحرر يملك صلاحية core.edit بشكل عام، فإن فحص التفويض ينجح لكل معرّف صورة على الموقع، بما في ذلك الصور المملوكة للمسؤولين.
إلى جانب غياب استدعاء $this->escape() في قالب الصورة بواجهة المستخدم الأمامية، يمكن للمحرر تخزين حمولة XSS في عنوان أي صورة — بما في ذلك الصور المملوكة للمسؤول — مما يتسبب في تنفيذ JavaScript في متصفح كل زائر. وهذا يتيح اختطاف جلسة المسؤول بالكامل والاستيلاء على الموقع بأكمله.
| COMPONENT | VULNERABLE | TESTED ON | FIXED |
|---|---|---|---|
| JoomGallery (com_joomgallery) | 4.0.0 – 4.3.0 | Joomla 5.4.7 + JoomGallery 4.3.0-stable (PHP 8.2 / Apache) | 4.4.0 |
النوع: كسر التفويض على مستوى الكائن / IDOR (CWE-639) بالتزامن مع XSS المخزّن (CWE-79) المصادقة المطلوبة: حساب محرر بصلاحيات منخفضة
الملف: components/com_joomgallery/src/Controller/UserimageController.php
ينفّذ إجراء save() فحص ACL باستخدام صلاحية edit بدلاً من edit.own. تُمنح صلاحية edit لجميع مستخدمي دور المحرر بشكل عام، لذا ينجح الفحص لأي معرّف صورة بغض النظر عمّن أنشأها.
USERIMAGECONTROLLER.PHP — الكود المعرّض للثغرة (السطر 145)
// Vulnerable
if (!$this->checkACL('edit', 'image', $recordId, $parent_id, true)) { ... }
ونظرًا لأن مجموعة المحررين تمتلك core.edit بشكل عام، فإن الشرط يُقيَّم على أنه false لكل معرّف صورة، مما يمنح صلاحية كتابة غير مقيدة. وعند نجاح الحفظ، يقوم النموذج (Model) أيضًا بتحديث created_by إلى معرّف المستخدم المهاجم، مما ينقل ملكية الصورة إلى المهاجم بصمت.
الملف: components/com_joomgallery/tmpl/image/default.php
يقوم قالب الصورة الأمامي بطباعة $this->item->title دون ترميز HTML في سياق خاصية alt. لا يزيل فلتر STRING في JInput الخاص بجملة علامات الاقتباس المزدوجة، لذا فإن حمولة تحتوي على " تخرج من الخاصية وتحقن معالجات أحداث (Event Handlers) عشوائية.
DEFAULT.PHP — الكود المعرّض للثغرة (السطران 64 و78)
// Vulnerable
item->title; ?>" ...>
يتم تخزين الحمولة abc" onmouseover="alert(document.domain);" x=" في jos_joomgallery.title وحقنها كما هي في خاصية HTML عند كل عرض للصفحة. لا يحدث أي تنقية (Sanitization) في طبقة التخزين أو العرض.
task=userimage.save&id=3 مع حمولة XSS في jform[title]. ينجح فحص ACL (core.edit وليس edit.own). يعيد الخادم HTTP 303 — وليس 403.created_by إلى معرّف المستخدم المهاجم.jos_joomgallery.title.alt="abc" onmouseover="alert(document.domain);". تنطلق XSS. يتم التقاط جلسة المسؤول → استيلاء كامل على الموقع.ينشئ المسؤول admin_image عبر واجهة إدارة JoomGallery الخلفية (Joomla 5.4.7). الصورة منشورة ومعتمدة ومملوكة بواسطة Administrator

يحتوي استجابة JSON من GET /index.php/component/users/login على "csrf.token":"a68c2b3a...". يتم التقاط الرمز لطلب تسجيل الدخول POST اللاحق.

joomla_user_state=logged_inإرسال POST /index.php/component/users/login مع رمز CSRF وبيانات اعتماد المحرر. الاستجابة: HTTP 303 وSet-Cookie: joomla_user_state=logged_in. يتم التقاط ملف تعريف ارتباط الجلسة.

إرسال GET /index.php?option=com_joomgallery مع ملف تعريف ارتباط الجلسة. تحتوي الاستجابة على "csrf.token":"2d96934b..." جديد لاستخدامه في طلب الحفظ.

يرسل المحرر طلب POST إلى option=com_joomgallery&task=userimage.save&id=3 مع تعيين jform[title] إلى:
abc" onmouseover="alert(document.domain);" x="
يعيد الخادم HTTP 303 (وليس 403)، مما يؤكد وجود IDOR. يُظهر ترويسة Location حمولة XSS في رابط إعادة التوجيه، مما يؤكد قبول العنوان وحفظه.

تعرض واجهة إدارة JoomGallery الخلفية أن الصورة ID=3 أصبح مالكها الآن: Editor User. تم تحديث حقل created_by بصمت في قاعدة البيانات أثناء الحفظ غير المصرح به.

يؤكد استعلام SQL على jos_joomgallery أن حمولة XSS مخزّنة — يتم تخزين " كعلامة اقتباس مزدوجة خام، وليس كـ ". لم يحدث أي تنقية في طبقة التخزين.

أي مستخدم يزور /index.php/component/joomgallery/gallery يقوم بتشغيل الحمولة. يؤكد صندوق حوار alert() في المتصفح تنفيذ JavaScript في نطاق الضحية (document.domain).

created_by للمهاجم بصمت، مما يغيّر مسار التدقيق بشكل دائم.alt سرقة ملف تعريف ارتباط الجلسة الخاص بالمسؤول، مما يمنح المهاجم وصولاً كاملاً للواجهة الخلفية وتحكمًا في تثبيت Joomla بالكامل.S:C)، متجاوزةً حدود الثقة بين جلسة المهاجم منخفضة الصلاحيات وجلسة الضحية عالية الصلاحيات.