
CVE-2026-9811 is a Stored Cross-Site Scripting (Stored XSS) vulnerability affecting Mautic 7 (versions 7.0.0 through 7.1.1).
CVE-2026-9811 هي ثغرة البرمجة النصية عبر المواقع المخزنة (Stored XSS) تؤثر على Mautic 7 (الإصدارات من 7.0.0 إلى 7.1.1). توجد الثغرة في مكوّن محدد المشروع (Project Selector)، إذ تُدرَج أسماء المشاريع التي يعيدها طلب AJAX في الصفحة دون ترميز مناسب للمخرجات أو تعقيم. يمكن لمستخدم مصادَق عليه يملك صلاحية إنشاء المشاريع تخزين حمولة JavaScript خبيثة في اسم مشروع. وعندما يفتح مسؤول آخر لاحقًا محرر كيان يحتوي على محدد المشروع، يُنفَّذ السكربت الضار في متصفحه.
الخاصية القيمة المنتج Mautic الإصدارات المتأثرة 7.0.0 – 7.1.1 الإصدار المُصحَّح 7.1.2 المكوّن Project Selector نوع الثغرة البرمجة النصية عبر المواقع المخزنة (XSS)
يخزّن التطبيق أسماء المشاريع المقدمة من المستخدمين المصادَق عليهم، ثم يستعيدها لاحقًا عبر نقطة نهاية AJAX. عند عرض محدد المشروع، يُدخل التطبيق هذه القيم مباشرةً في DOM كعناصر خيارات HTML دون ترميز المحتوى أو تعقيمه.
مفهوميًا:
User creates project
│
▼
Project name stored in database
│
▼
AJAX returns project name
│
▼
Inserted into DOM without sanitization
│
▼
Browser executes embedded JavaScript
ونظرًا لأن التطبيق يثق في البيانات المخزنة، يُنفَّذ JavaScript الضار كلما فتح مستخدم متميّز آخر الصفحة المعرضة للثغرة.
Attacker
│
▼
Creates a project with a malicious JavaScript payload as its name
│
▼
Payload is stored in the database
│
▼
Administrator opens an entity editor
│
▼
AJAX request retrieves project names
│
▼
Application inserts project name into the DOM without encoding
│
▼
Browser executes the malicious script
│
▼
Attacker gains actions within the administrator's session
يستطيع المهاجم الذي يملك صلاحية إنشاء المشاريع إنشاء مشروع يحتوي اسمه على حمولة JavaScript خبيثة.
لاحقًا، يحرّر مسؤول كيانًا آخر يتضمّن محدد المشروع. يحمّل المحدد أسماء المشاريع عبر AJAX ويُدخلها مباشرةً في الصفحة. ولأن اسم المشروع غير مُعقَّم، ينفّذ المتصفح السكربت المضمّن بصلاحيات المسؤول.
تخيّل أن Mautic يحتوي على نموذج مثل هذا:
POST /projects/create HTTP/1.1
Content-Type: application/x-www-form-urlencoded
projectName=Marketing Campaign
description=Email Campaign
يُحفظ المشروع على النحو التالي:
Marketing Campaign
الخطوة 2: إنشاء المهاجم لمشروع
بدلًا من اسم عادي، يُدخل المهاجم HTML يحتوي على حدث JavaScript غير ضار:
POST /projects/create HTTP/1.1
Content-Type: application/x-www-form-urlencoded
projectName=<img src="https://raw.githubusercontent.com/aj2108/cve-2026-9811/HEAD/x" onerror="console.log('XSS Demo')">
description=Test
تخزّن قاعدة البيانات الآن تلك السلسلة النصية كما هي تمامًا.
الخطوة 3: إرجاع AJAX للقيمة المخزنة
لاحقًا، يفتح مسؤول صفحة تحمّل المشاريع.
استجابة AJAX:
{
"id": 7,
"projectName": ""
}
الخطوة 4: كود JavaScript الهش
افترض أن التطبيق يقوم بذلك:
const project = response.projectName;
document.getElementById("projects").innerHTML +=
`<option>${project}</option>`;
يرى المتصفح ما يلي:
<option>
<img src="https://raw.githubusercontent.com/aj2108/cve-2026-9811/HEAD/x" onerror="console.log('XSS Demo')">
</option>
ولأن التطبيق أدخل السلسلة كـ HTML وليس كنص، يحلّلها المتصفح كعنصر فعلي. يفشل تحميل الصورة (src="x")، مما يؤدي إلى تنفيذ معالج onerror.
قد يسمح الاستغلال الناجح للمهاجم بما يلي:
| المقياس | النتيجة |
|---|---|
| CVSS v3.1 (CNA) | 5.4 (متوسطة) |
لم تنشر NVD بعدُ تقييمها الخاص لـ CVSS لهذا CVE.
ملاحظة: لم ينشر البائع الكود المصدري الدقيق للثغرة. يوضح المثال التالي نمط الثغرة فقط.
// Data returned from AJAX
const project = response.projectName;
// Unsafe: inserted directly into the DOM
document.getElementById("projectSelector").innerHTML +=
`<option>${project}</option>`;
ينشأ اسم المشروع من مدخلات المستخدم، لكنه يُدرَج في الصفحة دون ترميز HTML. إذا احتوت القيمة المخزنة على HTML أو JavaScript، يفسّرها المتصفح كمحتوى قابل للتنفيذ بدلًا من نص عادي.
const option = document.createElement("option");
// Safe: assign as text, not HTML
option.textContent = response.projectName;
document.getElementById("projectSelector").appendChild(option);
أو، إذا كان إخراج HTML أمرًا لا مفر منه، فتأكد من ترميز المخرجات بشكل صحيح قبل الإدراج.
يضمن استخدام textContent (أو أي واجهة برمجة تطبيقات (API) آمنة مكافئة) معاملة أي أحرف خاصة كنص عادي بدلًا من HTML أو JavaScript قابل للتنفيذ. حتى إذا خُزِّن اسم مشروع خبيث في قاعدة البيانات، فسيُعرض كما هو حرفيًا بدلًا من تنفيذه.