
CVE-2026-39275 - ثغرة XSS مخزنة تؤدي إلى الاستيلاء على الحساب في Cockpit CMS
| CVE ID | CVE-2026-39275 |
| الثغرة | تخزين Cross-Site Scripting (XSS) → الاستيلاء على الحساب |
| CWE | CWE-79 |
| المتأثر | Cockpit CMS <= 2.13.5 |
| تم التصحيح | d70dc50 |
| CVSS 3.1 | 8.4 (AV:N/AC:L/PR:L/UI:R/S:C/C:H/I:H/A:N) |
| المبلغ | Rohith - مستشار أمني @ SecurifyAI |
ثغرة تخزين XSS في عرض قائمة المحتوى الجماعي تسمح لأي مستخدم لديه صلاحيات كتابة المحتوى (مفتاح API أو جلسة محرر موثقة) بحقن JavaScript تعسفي يتم تنفيذه في متصفح أي مسؤول أو محرر يشاهد قائمة العناصر للمجموعة المتأثرة.
رموز جلسة Cockpit يمكن الوصول إليها بالكامل من JavaScript - حيث يتم تعيين ملف تعريف الارتباط للجلسة بدون علامة HttpOnly، وجWT CSRF مكشوف في المتغير العام App.csrf والخاصية data-csrf في عنصر <html>. هذا يسمح للبرنامج النصي المحقون بقراءة كلا الرمزين وإرسالهما خارجياً، مما يلغي حماية CSRF ويتيح اختطاف الجلسة الكامل والاستيلاء على الحساب.
يتم تمرير مخرجات Field render() إلى توجيه Vue v-html دون ترميز المخرجات.
| الملف | السطور | الدور |
|---|---|---|
modules/App/assets/vue-components/fields/field-tags.js | 25 - 34 | عارض العلامات - بدون ترميز |
modules/App/assets/vue-components/fields/field-select.js | 26 | عارض التحديد - بدون ترميز |
modules/Content/views/collection/items.php | 149 | حوض v-html |
curl -X POST "http://localhost:8080/api/content/item/posts" \
-H "Content-Type: application/json" \
-H "api-key: USR-<attacker-api-key>" \
-d '{
"data": {
"title": "Innocent Looking Post",
"tags": [
"",
""
],
"body": "Just a regular post.",
"_state": 1
}
}'
يقوم مسؤول أو محرر بالتنقل إلى /content/collection/items/posts. يقوم عارض العلامات بإرجاع السلسلة المخزنة، ويقوم v-html بتحليلها إلى عنصر `` حقيقي، يفشل src المزيف، ويتم تشغيل معالج onerror.
كلا الرمزين قابلة للقراءة الآن - ملف تعريف الارتباط للجلسة عبر document.cookie وJWT CSRF عبر App.csrf / document.documentElement.getAttribute('data-csrf'). تقوم حمولة مسلحة بإرسال كليهما:

يقوم المهاجم بإعادة تشغيل ملف تعريف الارتباط المسروق ورمز CSRF، مما يمنحه وصولاً كاملاً بصلاحيات المسؤول - ويمكنه بعد ذلك إنشاء حسابات مسؤول، تغيير بيانات الاعتماد، أو تعديل المحتوى.
محرر ذو امتيازات منخفضة (أو أي حامل مفتاح API لكتابة المحتوى) يرتقي إلى مسؤول كامل. الحمولة مخزنة ويتم تشغيلها لكل مسؤول/محرر يشاهد القائمة، مما يجعلها اختراقاً مستمراً متعدد الضحايا.
الإصلاح الأساسي - تنظيف مخرجات التقديم قبل وصولها إلى v-html باستخدام المساعد الموجود App.utils.stripTags().
field-tags.js:
value = App.utils.stripTags(value); // تنظيف قبل v-html
field-select.js:
return App.utils.stripTags(value); // تنظيف قبل v-html
دفاع متعدد الطبقات - تعزيز ملف تعريف الارتباط للجلسة:
ini_set('session.cookie_httponly', 1);
ini_set('session.cookie_secure', 1); // عبر HTTPS
ini_set('session.cookie_samesite', 'Strict');
HttpOnly وحده غير كافٍ - لا يزال XSS يمكنه التصرف في سياق المتصفح الموثوق للضحية - لذا فإن ترميز المخرجات هو الإصلاح الأساسي.
| التاريخ | الحدث |
|---|---|
| 2026-03-29 | تم الإبلاغ عن الثغرة إلى المشرفين على Cockpit CMS |
| 2026-03-29 | تم إصدار التصحيح من قبل المشرفين |
| 2026-04-04 | تم طلب CVE |
| 2026-06-23 | تم تعيين CVE-2026-39275 |
<pub date> | الإفصاح العام |
تم نشر هذه المادة لأغراض تعليمية ودفاعية بعد الإفصاح المنسق. استخدم فقط ضد الأنظمة التي تملكها أو مصرح لك باختبارها بشكل صريح.