تضمين تعليقات Discourse على موقع آخر عبر Javascript

لقد تتبعنا مؤخرًا مصدر هذه المشكلة في إضافة التضمين (embed plugin). عند تكوين التضمين، يوجد إعداد يُسمى “الاستضافات المسموح بها” (Allowed Hosts)، والذي يُعدّل سياسة أمان المحتوى (CSP) الخاصة بإطار الـ iframe، بحيث يظهر الإطار فقط على تلك الاستضافة. على سبيل المثال، إذا قمت بتكوين التضمين مع استضافة مسموح بها هي example.com ثم حاولت تضمين كود JavaScript على attacker.com، فسيتم رفض تحميل الـ iframe مع ظهور الخطأ التالي:

Refused to frame 'https://forum.example.com/' because an ancestor violates the following Content Security Policy directive: "frame-ancestors 'self' https://example.com".

ومع ذلك، في هذه الحالة، يكون كود JavaScript قد تنفذ بالفعل وأنشأ موضوعًا في المنتدى باستخدام أي عنوان URL تم توفيره في كود التضمين.

ما يحدث في حالتي هو أننا نستخدم Netlify لمعاينة الإصدارات، وبالتالي يتم تقديم نسخة من المدونة فعليًا من عناوين URL الخاصة بـ netlify.app، والتي تقوم بتحميل ملف embed.js هذا وإنشاء خيوط المنتدى للمشاركات التي قمت باستيرادها بشكل خاطئ سابقًا.

هذا ليس بالضرورة مشكلة أمنية، لأنه لا يزال بإمكانه إنشاء مواضيع فقط لعناوين URL الموجودة على الموقع المُكوَّن والتي تطابق قائمة السماح بالمسارات. لكنه يمثل مشكلة في استراتيجية الهجرة هذه، حيث لم أتمكن من تعيين embed_url في خيوط المنتدى عند استيراد المشاركات القديمة إلى Discourse.

الحل هو إضافة قاعدة CSP لمنع تشغيل embed.js على نطاقات غير مُدرجة ضمن إعداد “الاستضافات المسموح بها”.

كإثبات للمفهوم، قمت بنسخ كود التضمين إلى نطاق غير ذي صلة تمامًا وقمت بتعيين discourseEmbedUrl إلى أحد المشاركات القديمة التي استوردتها. عند تحميل الصفحة، تم حظر الـ iframe، لكن كود JavaScript قد تنفذ بالفعل وأنشأ خيط المنتدى.

إذا كنت تعتقد أن هذه مشكلة أمنية أكثر من كونها خللًا برمجيًا، فسأكون سعيدًا بحذف هذا المنشور والإبلاغ عنه عبر HackerOne بدلاً من ذلك.

إعجابَين (2)