مخاوف أمنية/خصوصية: بريد إلكتروني مكشوف في عنوان URL لإعادة توجيه مزود DiscourseConnect

صف الخطأ

عند استخدام Discourse كمزود DiscourseConnect (مزود SSO)، يتم الكشف عن عنوان البريد الإلكتروني للمستخدم في عنوان URL لإعادة التوجيه 302 إلى الطرف المعتمد. يحدث هذا لأن الدالة populate_user_data في lib/second_factor/actions/discourse_connect_provider.rb تقوم دائمًا بتعيين البريد الإلكتروني:

  def populate_user_data(sso)
    sso.name = current_user.name
    sso.username = current_user.username
    sso.email = current_user.email  # <-- يتم تضمينه دائمًا
    sso.external_id = current_user.id.to_s
    # ...
  end

يتم بعد ذلك ترميز هذا البريد الإلكتروني بـ Base64 وتضمينه في عنوان URL لإعادة التوجيه:
https://target-site.com/callback?sso=<base64_payload>&sig=<hmac_signature>

فك تشفير حمولة base64 يكشف عنوان البريد الإلكتروني كنص عادي.

التأثير

  1. سجل المتصفح: يتم تسجيل البريد الإلكتروني في سجل المتصفح
  2. سجلات Nginx: يتم تسجيل عنوان URL بالكامل في سجلات وصول nginx
  3. سجلات الموقع الهدف: يتلقى الطرف المعتمد البريد الإلكتروني دون موافقة صريحة من المستخدم
  4. توقعات المستخدم: يتوقع المستخدمون عادةً المصادقة لإثبات “أنا مستخدم شرعي” - ولا يتوقعون مشاركة بريدهم الإلكتروني

السلوك المتوقع

يجب أن يكون المستخدمون قادرين على التحكم فيما إذا كان بريدهم الإلكتروني مشتركًا مع الطرف المعتمد. يجب أن يكون هناك خيار تكوين مشابه لـ discourse_connect_overrides_groups و discourse_connect_overrides_avatar وما إلى ذلك.

لا يوجد حاليًا إعداد موقع لتعطيل هذا السلوك. كتابة إضافة لتجاوز هذا السلوك ممكن ولكن ليس مثاليًا.

خطوات إعادة الإنتاج

  1. تمكين enable_discourse_connect_provider
  2. تكوين discourse_connect_provider_secrets (على سبيل المثال، *.example.com|secret123)
  3. قيام مستخدم بالمصادقة عبر مزود DiscourseConnect
  4. التحقق من عنوان URL لإعادة التوجيه 302 - يظهر البريد الإلكتروني في معلمات عنوان URL

يبدو عنوان URL لإعادة التوجيه كما يلي:
https://relying-party.com/sso?sso=nonce=xxx&sig=xxx

فك تشفير المعلمة sso يكشف:
nonce=xxx&return_sso_url=xxx&email=user@example.com&external_id=123

البيئة

  • إصدار Discourse: (الأحدث)
  • مستضاف ذاتيًا

اقتراحات إصلاح محتملة

  1. إضافة إعداد موقع مثل discourse_connect_provider_includes_email (الافتراضي: true للتوافق مع الإصدارات السابقة) للتحكم فيما إذا كان البريد الإلكتروني مدرجًا في الاستجابة
  2. أو تنفيذ رد اتصال قائم على POST بدلاً من إعادة توجيه GET 302 لتجنب تسجيل عنوان URL
إعجاب واحد (1)

أليس هذا مشفرًا أيضًا باستخدام المفتاح السري المشترك؟

إعجاب واحد (1)

مرحباً فالكو،

تضمن توقيع HMAC أن الحمولة لم يتم العبث بها فقط - فهو لا يقوم بتشفير البيانات. ترميز Base64 هو ترميز، وليس تشفيراً، لذا يمكن لأي شخص فك ترميزه لقراءة المحتويات.

المشكلة الأساسية هي: نحن لا نريد الكشف عن معلومات المستخدم غير الضرورية (مثل البريد الإلكتروني) لـ “مواقع الطرف الثالث التي تستخدم Discourse لتسجيل الدخول عبر SSO”. يفوض المستخدمون فقط لإثبات “أنا مستخدم شرعي” - ولا يتوقعون مشاركة بريدهم الإلكتروني.

هل سيكون إعداد موقع للتحكم فيما إذا كان سيتم إرجاع البريد الإلكتروني مقبولاً؟

أنا فضولي، ما هو هذا الطرف الثالث اللاحق الذي قام بتنفيذ بروتوكول الدخول الموحد (SSO) المخصص لدينا؟

أعتقد أن هذا هو pr-welcome طالما أنه ليس الإعداد الافتراضي، حتى لا نُحدث خللاً في المواقع الحالية.

شكرًا على الملاحظات!

لأعطيك بعض السياق حول حالة الاستخدام: منتدانا هو “منتدى جامعي”، وقد أنشأ طالب موقعًا إلكترونيًا مجانيًا ليستخدمه الطلاب الآخرون. يريدون استخدام منتدانا الجامعي القائم على Discourse للمصادقة على ما إذا كان المستخدم طالبًا بالفعل في مدرستنا - أي إثبات “أنا طالب شرعي هنا”.

في هذا السيناريو، يحتاج الموقع الخارجي فقط إلى معرفة “هذا مستخدم صالح من منتدانا الجامعي” - ليس بالضرورة أن يحتاجوا إلى بريد المستخدم الإلكتروني، وهي معلومات حساسة لا ينبغي مشاركتها دون داعٍ.

سأعمل على طلب سحب (PR) يضيف إعداد موقع للتحكم في هذا السلوك، مع قيمة افتراضية تحافظ على التوافق مع الإصدارات السابقة للتثبيتات الحالية.

إعجابَين (2)