
أداة Python لإثبات المفهوم للثغرة CVE-2026-93453، وهي ثغرة تسميم رابط إعادة تعيين كلمة المرور في SOGo عبر ترويسة Origin التي يتحكم بها المهاجم، مما يتيح اعتراض رمز إعادة التعيين والاستيلاء على الحساب.
استغلال لثغرة يقوم فيها SOGo بتجميع رابط إعادة تعيين كلمة المرور الذي يرسله بالبريد الإلكتروني للمستخدمين مباشرةً من ترويسة Origin المقدَّمة من العميل. يقوم مهاجم مجهول يعرف اسم تسجيل دخول الضحية بإرسال طلب استرداد مع Origin تحت سيطرته؛ فيشير الرابط داخل رسالة "Password reset" المُرسَلة بالبريد إلى مضيف المهاجم بينما يظل رمز JWT المضمَّن رمز استرداد صالحًا تمامًا. وبعد نقرة واحدة من الضحية يصبح الرمز في سجل وصول المهاجم، ويقوم POST /SOGo/changePassword باستبداله بكلمة مرور جديدة — استيلاء كامل على الحساب يشمل البريد والتقويمات وجهات الاتصال، دون أي مصادقة في أي خطوة. كما يتخطى فرع البريد الإلكتروني فحص SOGoPasswordRecoveryEnabled (إذ يُستشار هذا العلم فقط في فرع SecretQuestion)، لذا يعمل مسار البريد الإلكتروني حتى عندما يظن المشغّل أن الاسترداد مُعطَّل.
السجل: https://www.cve.org/CVERecord?id=CVE-2026-93453
| المتأثر | SOGo < 5.12.11 (≤ 5.12.10) |
| المُصلَح | 5.12.11 (قائمة السماح SOGoPasswordRecoveryBaseURLs) |
| المتطلبات المسبقة | ضحية بنمط استرداد SecondaryEmail؛ المهاجم يعرف userName؛ الضحية تنقر الرابط المُرسَل بالبريد |
| التأثير | الاستيلاء على الحساب |
// UI/MainUI/SOGoRootPage.m:1374 (tag SOGo-5.12.10) — passwordRecoveryEmailAction
url = [NSString stringWithFormat:@"%@%@?token=%@",
[[request headers] objectForKey:@"origin"], // <-- raw client header
[request uri],
jwtToken]; // <-- valid HS256 JWT, 10 min TTL
رابط إعادة التعيين المزوَّد بالرمز هو Origin + request URI + JWT، لذا فمن يضبط الترويسة يحدد المضيف الذي ينتقل إليه سرّ الضحية. هذا تسميم لإعادة تعيين كلمة المرور (CWE-640 / CWE-601)، وليس إعادة توجيه مفتوح: إذ يقبل /SOGo/changePassword رمز JWT بغض النظر عن المضيف الذي نقله إليه.
// 5.12.11 — the fix: origins are validated against a mandatory allowlist
baseUrls = [[SOGoSystemDefaults sharedSystemDefaults] passwordRecoveryBaseURLs];
serverUrl = [[request headers] objectForKey:@"origin"];
if (!(baseUrls && [baseUrls count] > 0)) // unset config -> 403
if (![baseUrls containsObject:serverUrl]) // foreign origin -> 403
في الإصدار 5.12.11 يحصل Origin الأجنبي على 403 ("Password recovery email in error")؛ وفي الإصدارات ≤ 5.12.10 يُعيد الطلب نفسه 200 ويُرسَل البريد — وهذا الفرق هو ما يعتمد عليه check.
# non-destructive probe: canary user + foreign Origin, classify the reply
python3 CVE-2026-93453.py check https://sogo.example
# poison: dispatch the reset mail for the victim with your host in the link
python3 CVE-2026-93453.py poison https://sogo.example --user victim --origin https://attacker.example
المكتبة القياسية فقط (Python 3.8+). يدعم --proxy و--insecure و--timeout و--no-color و--prefix لنقاط تركيب SOGo غير القياسية.
لا يحتاج الـ PoC إلى أي بنية تحتية للمهاجم: فـ poison يجعل الخادم يرسل الرابط بالبريد فقط، والمضيف المسموم هو ما تضعه في --origin. على نسخة مصابة يصبح الرابط المُرسَل بالبريد https://attacker.example/SOGo/passwordRecoveryEmail?token=<valid HS256 JWT> — فينتقل الرمز إلى مضيفك في اللحظة التي تنقر فيها الضحية.
يستخدم check اسم مستخدم وهميًا غير موجود حتى لا يُسلَّم أي بريد إلى صندوق بريد حقيقي؛ 200 = فرع البريد الإلكتروني قبل الـ Origin الأجنبي (بصمة الثغرة)، 403 = قائمة السماح في 5.12.11 أو SOGoPasswordRecoveryBaseURLs غير مضبوط (غير قابل للاستغلال). لإجراء اختبار ذاتي قاطع، استخدم poison على حساب تملكه واقرأ مضيف الرابط في صندوق بريدك الخاص.
passwordRecoveryEmailAction)للاختبار والبحث المصرَّح بهما فقط. استخدمه فقط ضد الأنظمة التي تملكها أو لديك إذن صريح باختبارها.