
واجهة سطر أوامر Python تكتشف وتستغل CVE-2026-90907، وهو تجاوز للتفويض في Joomla! com_users يتيح إنشاء حسابات دون مصادقة؛ مع وضع فحص غير تدميري بالإضافة إلى PoC.
لأغراض الاختبار الأمني المصرّح به فقط. تشغيل وضع الاستغلال ضد أنظمة لا تملكها أو لا تملك إذنًا كتابيًا صريحًا لاختبارها غير قانوني. الوضع الافتراضي (
CHECK) غير مدمّر ولا ينشئ أي شيء.
أداة سطر أوامر تكتشف و(اختياريًا، باستخدام -U) تستغل
CVE-2026-90907، وهو
تجاوز تفويض متوسط الخطورة (CVSS 6.9) في نواة Joomla! CMS
يسمح لمهاجم بعيد غير مصادَق بإطلاق إنشاء حساب مستخدم غير مصرّح به
عبر وحدة التحكم com_users → profile.save —
حتى عندما يكون التسجيل العام معطّلًا في الإعدادات العامة.
| الحقل | القيمة |
|---|---|
| معرّف CVE | CVE-2026-90907 |
| الخطورة | متوسطة — CVSS 6.9 |
| النوع | تجاوز تفويض / تحكم غير سليم في الوصول (CWE-862) |
| المكوّن | مكوّن com_users، مهمة profile.save |
| ناقل الهجوم | عن بُعد، غير مصادَق، POST من خطوتين في الجلسة نفسها |
| تم إصلاحه في | Joomla! 5.4.9 و 6.1.4 (إصدار أمني، 2026-09-29) |
وفقًا للنشرة الأمنية لـ Joomla! (2026-09-29) ومصادر الاستشارات العامة:
Joomla! 3.x متأثر أيضًا لكنه انتهى عمره الافتراضي: لن يتلقى تصحيحًا رسميًا — خطّط للترحيل. فحص لافتة الإصدار في الأداة للمعلومات فقط؛ الحكم نهائي سلوكي (انظر أدناه).
الحساب الذي يتحكم به المهاجم هو حساب واجهة أمامية منخفض الصلاحيات بدون وصول إداري أو إلى الواجهة الخلفية. ومع ذلك، يتيح هذا للمهاجم:
ProfileModel::save() يقوم فقط بـ unset() لـ $data['username'] عندما
يُعتبر اسم المستخدم متوافقًا. يُشتق isUsernameCompliant من حالة المستخدم
com_users.edit.profile.data، التي يملؤها المتحكم بـ
الطلب الكامل عند فشل التحقق من النموذج. كما يفشل المتحكم في
التحقق من حالة تسجيل الدخول للطلب الوارد. لذلك، ضمن جلسة زائر
واحدة:
privacyconsent → يفشل التحقق → يُحفظ اسم المستخدم غير النظيف في
حالة مستخدم الجلسة (لا يُنشأ أي شيء بعد).jform[privacyconsent][privacy]=1 → يتم تجاوز حارس unset() →
INSERT INTO #__users → إعادة توجيه 303 مع user_id > 0.user.login (اسم الحقل هو
password، وليس passwd) بكلمة المرور الصحيحة مقابل كلمة مرور خاطئة و
قراءة رسالة الفلاش: صحيحة → "you cannot access the private section"
(المصادقة ناجحة، قوائم التحكم في الوصول تحجب) / خاطئة → "do not match". الفرق
هو الدليل.git clone https://github.com/aorozco-sys/CVE-2026-90907.git
cd CVE-2026-90907
pip install -r requirements.txt # only dependency: requests
# CHECK mode (default) — non-destructive: never sends consent, never creates an account
python3 joomla_cve_2026_90907.py https://ejemplo.com
# Verbose CHECK (full request/response log on stderr)
python3 joomla_cve_2026_90907.py https://ejemplo.com --no-color -v
# EXPLOIT mode (-U) — creates a real account in #__users (authorized targets only!)
python3 joomla_cve_2026_90907.py https://ejemplo.com \
-U audit.user -E [email protected] -N "CVE Audit"
# Through a proxy (e.g. Burp Suite) with a custom timeout
python3 joomla_cve_2026_90907.py https://ejemplo.com -U audit.user \
--proxy http://127.0.0.1:8080 --timeout 30
# Exploit without the differential login verification
python3 joomla_cve_2026_90907.py https://ejemplo.com -U audit.user \
--no-verify-login
| المعامل | الوصف |
|---|---|
TARGET | عنوان URL الأساسي (مُطبَّع؛ بدون شرطة مائلة في النهاية) |
-U/--username | يُفعّل وضع EXPLOIT. بدون -U ← فحص CHECK غير مُدمِّر |
-P/--password | الافتراضي: يُولَّد باستخدام secrets، 16 حرفًا أبجديًا رقميًا + رموز، يُطبَع دائمًا |
-E/--email | الافتراضي: <username>@example.invalid |
-N/--name | الافتراضي: CVE Audit |
-o/--output | دليل الأدلة (الافتراضي evidence_cve90907_<ts> ضمن cwd) |
--proxy URL | وكيل (proxy) للطلبات (Burp: http://127.0.0.1:8080) |
--timeout | الافتراضي 20 ثانية |
--ua | User-Agent (الافتراضي cve-2026-90907-audit/1.0) |
--no-verify-login | يتخطى تفاضل تسجيل الدخول (وضع exploit) |
--verify-ssl | التحقق من TLS (الافتراضي: عدم التحقق) |
--no-color | بدون ألوان ANSI |
-v/--verbose | سجل كامل للطلبات/الاستجابات على stderr |
| الرمز | المعنى |
|---|---|
0 | سليم / غير معرّض للثغرة / غير معروف |
1 | معرّض للثغرة (LIKELY في وضع الفحص، CONFIRMED في وضع exploit) |
2 | خطأ تشغيلي (شبكة، اعتمادية، إلخ) |
profile في Location، دون إعادة توجيه إلى تسجيل الدخول) + رسالة
خطأ تحقق (flash) (مثل رسالة اشتراط سياسة الخصوصية). التأكيد القاطع =
وضع exploit.summary.json.Location يحتوي على user_id > 0 بعد W2.يكتب كل تشغيل دليلًا مؤرَّخًا -o يحتوي على 00_token.txt،
01_version.txt، 02_w1_seed.txt، 03_w2_exploit.txt،
04_login_correct.txt، 05_login_wrong.txt وsummary.json. يسجّل كل ملف
الطلب الكامل (REQUEST) (الطريقة/URL/الترويسات الرئيسية/النص)، والاستجابة
(RESPONSE) (الحالة، Location، Server، رسالة flash المستخرجة، أول 500 بايت من النص)
والطوابع الزمنية ISO — جاهزة للإرفاق بتقرير اختبار اختراق.
privacyconsent أبدًا ويستخدم اسم مستخدم غير مطابق
(probe()): يفشل الحفظ بسبب قواعد النموذج ولا يُحفظ أي شيء.user_id > 0 (وهو ما لا ينبغي أن يحدث)،
يتوقف وضع exploit قبل W2.user_usergroup_map).MIT — راجع LICENSE.