تتعرض منصة Discourse الخاصة بـ freeCodeCamp.org للانهيار بسبب نصوص برمجية للمحتالين

بدأنا نلاحظ أحمالًا متزايدة على منصة Discourse الخاصة بـ freeCodeCamp.org في 21 يونيو. وبدأ متوسط حمل المعالج المركزي (CPU) في الارتفاع إلى الحد الذي جعل المنتدى بأكمله غير مستجيب.

التحقيق الأولي

  1. قمنا بتحديث Discourse من الإصدار المستقر إلى أحدث إصدار “تمت اختباره بنجاح” (Beta)، وهو موصى به للحصول على جميع إصلاحات الأداء الأحدث. لكن يبدو أن الفرق لم يكن كبيرًا.

  2. قمنا بإزالة بعض الإضافات القديمة للمساعدة في تشخيص المشكلة، ويبدو أن الأمر لا يتعلق بها في إبطاء الأداء.

  3. لاستبعاد أي إعدادات خاطئة، اختبرنا هذا مع السمة الافتراضية وفحصنا /logs، ووجدنا بعض الاستثناءات:

    Job exception: could not obtain connection from the pool within 5.000 seconds (awaited 5.006 seconds); all pooled connections were in use

يبدو أن السبب هو أن النسخة قد تكون بالفعل تحت ضغط كبير بسبب عدد كبير من المهام طويلة الأمد.

يتم تشغيل حاوية Discourse (من المصدر) على Digital Ocean، ويبدو أنها تعمل تحت ضغط على جميع وحدات المعالجة المركزية الافتراضية الستة (6 vCPUs). وهي تعمل حاليًا على الإصدار: 2.5.0.beta7

مزيد من التحقيق

  1. في صباح اليوم، أبلغنا المراقبون عن زيادة كبيرة في عدد حسابات البريد المزعج (Spam)، مما دفعنا إلى الاعتقاد بأن هذا قد يكون هجومًا موجهاً.

  2. لمحاولة التخفيف من المشكلة، وضعنا المنتدى في وضع القراءة فقط. وعلى الرغم من ذلك، لا تزال نسبة استهلاك الموارد مرتفعة جدًا عند أكثر من 60%.

  3. بناءً على ما يمكننا استنتاجه: منذ بدء هذه المشكلة، لاحظنا انخفاضًا في عدد الطلبات في الثانية وارتفاعًا في معدل الطلبات الحالية على الوكيل (proxy) الخاص بنا:

  1. لم يتغير حجم حركة المرور إلى The freeCodeCamp Forum - Join the developer community and learn to code for free. بشكل كبير وفقًا لـ Google Analytics.
  2. لا يبدو أن أيًا من التطبيقات الأخرى على نفس الوكيل قد تأثرت. فموقعنا /news ومنصة /learn تعملان بشكل طبيعي.
  3. جربنا إضافة بعض قيود المعدل الإضافية على الوكيل، لكن ذلك لم يحدث فرقًا كبيرًا، لذا قمنا بإزالتها ( للسماح للمستخدمين العاديين بالاستمرار في الوصول إلى موقعنا).
  4. كما قمنا بنقل تحويلات المنتدى القديم freecodecamp.com بعيدًا عن منتدى .org، حيث لاحظنا أن هذا النطاق الفرعي القديم (الذي لم نستخدمه منذ 2.5 سنة) شهد ارتفاعًا كبيرًا في حركة المرور بدءًا من بضعة أيام.

في الوقت الحالي، ومع حوالي 400 مستخدم في الوقت الفعلي، تبدو الإحصائيات كالتالي:

ملاحظات حول سلوك مرسل البريد المزعج

يبدو أن مرسلي البريد المزعج يديرون نوعًا من السكربتات التي تنشئ حسابات جديدة على نسخة من Discourse، ثم تنتظر عدة أيام. ثم تصبح هذه الحسابات فجأة نشطة. يبدأون في نشر مواضيع جديدة تحتوي على روابط لموقع ويب. (ربما لبناء روابط خلفية Backlinks؟)

تم إنشاء بعض هذه الحسابات منذ شهر مارس.

إليك كيف يبدو أحد منشوراتهم المزعجة، رغم وجود العديد من المتغيرات التي تربط بالعديد من المواقع الإلكترونية:

أي نصيحة ستكون موضع ترحيب هنا.

14 إعجابًا

هذا يستحق الكثير من الاهتمام

شكرًا جزيلاً لك على المشاركة!

أحد أمثلة Discourse المفضلة لدي، وهي freeCodeCamp، توقفت عن العمل تقريبًا خلال اليومين الماضيين.

5 إعجابات

لا أعتقد أن الحمل الثقيل هو المشكلة الرئيسية التي يسببها المرسلون العشوائيون.
إليك السبب:

لا يمكن استخدام المناقشة العادية (بدون API) إلا مع المتصفحات الحديثة لأنها تعتمد بشكل كبير على JavaScript. تستخدم Google Analytics JavaScript أيضًا لجمع معلومات مختلفة عن المستخدمين (ولا تحتاج إلى دعم JavaScript حديث لتشغيل كود التحليلات). إذا لم تتمكن Google Analytics من اكتشاف نشاط المستخدم، فلا يجب أن يتمكن Discourse من تقديم محتواه وميزاته.

إليك لقطة لروبوت عندما استخدمت مكتبة متصفح غير مرئي قديمة (phantomjs) للوصول إلى موقع Discourse:

وهنا مع مكتبة أحدث (puppeteer):

  1. من الغريب حقًا أن يتمكن شخص ما من نشر ردود (بدون API) على Discourse بينما لا تستطيع Google Analytics اكتشافهم.
  2. عادةً ما يستخدم المرسلون العشوائيون وكلاء عموميين (proxies) للقيام بأعمال غير أخلاقية، وأعتقد أن Cloudflare الخاص بك ذكي بما يكفي لوقف “الزوار السيئين” قبل أن يصلوا فعليًا إلى تطبيقك.

هل لاحظت وجود مهام عالية الطابور في عملية Sidekiq؟

إعجابَين (2)

يتجاهل هذا حقيقة أن أكثر من نصف الأشخاص في مجتمعات التكنولوجيا يستخدمون نوعًا ما من ملحقات حظر الإعلانات، والتي تقوم دائمًا بحظر Google Analytics افتراضيًا.

18 إعجابًا

بما في ذلك نظام macOS الجديد.

كان مجرد إشاعة سيئة. انظر في الأسفل.

5 إعجابات

هل تم تفعيل Akismet؟ هل يمكنك تفعيل المراجعة لمستوى الثقة 1؟

إعجابَين (2)

نعم، لاحظنا ظهور الوظائف واختفاؤها كجزء من تحقيقنا الأولي. ثم قمنا بإلغاء جميع مفاتيح المستخدمين.

غير أن ذلك لم يبدُ أنه أحدث أي تغيير في الاستقرار.

رغم أننا نعمل بشكل وثيق مع فريق Discourse لحل هذه المشكلة.

5 إعجابات

لا أرى ما الغريب في وجود طلبات لا تظهر فيها أي إحصائيات تعتمد على JavaScript.
يمكن للمُرسِل للرسائل المزعجة استخدام نفس نقاط النهاية التي يستخدمها JavaScript، ولكن دون استخدام JavaScript. وبالتالي لن تُفعَّل أي إحصائيات تعتمد على JavaScript.

3 إعجابات

من المرجح جدًا أن يكون ذلك تفاعلًا مع إضافة أو تكوين وكيل خاطئ. لا نلاحظ أي نجاح من «المرسلين غير المرغوب فيهم» على استضافتنا.

وبما أنه موقع برمجي، فقد يكون أيضًا «مبرمجون» يحاولون فعل شيء غريب على المنتدى؟

لكن لا — المرسلون غير المرغوب فيهم ليسوا مشكلة عامة عبر آلاف المواقع التي نوفر استضافتها.

3 إعجابات

نعم، أميل إلى الاعتقاد بأن المشكلة إما في الإعدادات (إعدادات إضافة خاطئة أو إعدادات وسيط خاطئة) أو أن شخصًا ما يتلاعب بالمنتدى.

الأمر الثاني هو السبب الأكثر احتمالاً بناءً على جميع الأنماط.

ما لاحظته هو أن حسابات البريد المزعج تم إنشاؤها على مدار فترة زمنية طويلة، وهي تحاول إضافة روابط (للحصول على روابط خلفية؟) في بياناتها الشخصية وغيرها من الأمور الغريبة.

كما قد يكون هناك عملية كشط (Scraping) متضمنة، لأننا وضعنا الموقع في وضع القراءة فقط، وقمنا بإعداد ذاكرة تخزين مؤقت على الوسيط بالإضافة إلى تحديد معدل الطلبات. ومع ذلك، يبدو أن استخدام الموارد مرتفع بغض النظر عن الحاوية الصاعدة.

ومع ذلك، لا أستبعد أن تكون إعداداتنا سيئة أيضًا، فنحن نستخدم مسارات فرعية و Cloudflare فوق وسيط العكس الخاص بنا، وهو تقليديًا ليس الإعداد الأكثر كفاءة الذي يوصي به Discourse.

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

image

نسبة سرقة الموارد بنسبة 42.5% تعتبر مرتفعة جدًا، حتى لو كنت أنت السبب في المشاكل على ذلك الهيبيرفايزر. يبدو لي أن هذا جار صاخب. لو كنتُ مكانك، لراجعت DigitalOcean وطلبت منهم نقل الـ Droplet إلى هيبيرفايزر آخر.

10 إعجابات

أنا متأكد من أنك تقوم على الأرجح بذلك، ولكن للتأكد فقط، أقترح مراقبة اتصالات TCP/UDP المفتوحة ومُلخصة حسب عنوان IP على مستوى نظام التشغيل. إذا كان هناك حمل مرتفع على المعالج، فيجب أن يُظهر لك عددًا هائلًا من الاتصالات المفتوحة إلى خادم الويب.

هل هناك أي نمط غريب في production.log؟

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

مرحبًا كوينسي @ossia

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

المفهوم الرئيسي في جميع مهام الأمن السيبراني هو مفهوم “الوعي الظرفي”، لذا في هذه الحالة يُسمى “الوعي الظرفي السيبراني” (CSA).

ولمعرفة “ما يحدث” بشكل قاطع، تحتاج إلى تطوير أفضل معرفة ظرفية ممكنة دون تكهنات أو تخمين. فقط الحقائق.

كيف تفعل ذلك؟

حسنًا، باختصار شديد:

حسنًا، باختصار شديد:

نقوم بذلك من خلال دمج المعلومات من جميع أجهزة الاستشعار لدينا، وبالنسبة للتطبيقات القائمة على الويب، تأتي هذه المعلومات عادةً من ملفات السجل (log files) وبيانات الجلسة. لا أعتقد (بناءً على ما أعرفه فورًا) أن نظام discourse يحفظ معلومات الجلسة في قاعدة بيانات PG (آخر مرة تفحصت فيها لم يكن هناك جدول للجلسات مثل بعض تطبيقات الويب LAMP)، لكن هذا ليس عائقًا على الإطلاق.

لديك معظم ما تحتاجه في ملفات سجل nginx لكل من وكيل العكس (reverse proxy) الموجود خارج الحاوية (أتذكر أنني قرأت في هذا الموضوع أنك تستخدم nginx كوكيل)، ومعلومات السجل نفسها موجودة أيضًا داخل الحاوية. في كلتا الحالتين، يقع ملف السجل هنا، في الإعداد القياسي OOTB:

إليك مثالًا في أحد إعداداتنا (خارج الحاوية) لوكيل العكس:

# cd /var/log/nginx
# ls -l 
total 779964
-rw-r----- 1 www-data adm         0 Jun 17 06:25 access.log
-rw-r----- 1 www-data adm 660766201 Jun 25 18:26 access.log.1
-rw-r----- 1 www-data adm 107367317 Jun 17 03:18 access.log.2.gz
-rw-r----- 1 www-data adm  21890638 May 21 03:08 access.log.3.gz
-rw-r----- 1 www-data adm   7414232 May  5 07:26 access.log.4.gz
-rw-r----- 1 www-data adm     63289 Apr 18 09:12 access.log.5.gz
-rw-r----- 1 www-data adm         0 Jun 17 06:25 error.log
-rw-r----- 1 www-data adm    904864 Jun 25 18:19 error.log.1
-rw-r----- 1 www-data adm     96255 Jun 17 03:17 error.log.2.gz
-rw-r----- 1 www-data adm     79065 May 21 02:58 error.log.3.gz
-rw-r----- 1 www-data adm     70799 May  5 06:54 error.log.4.gz
-rw-r----- 1 www-data adm      1977 Apr 18 05:49 error.log.5.gz

وإليك نفس معلومات السجل الأساسية داخل حاوية discourse:

# cd /var/discourse/
# ./launcher enter socket
# cd /var/log/nginx
# ls -l
total 215440
-rw-r--r-- 1 www-data www-data  87002396 Jun 25 18:28 access.log
-rw-r--r-- 1 www-data www-data 101014650 Jun 25 08:02 access.log.1
-rw-r--r-- 1 www-data www-data   8217731 Jun 24 08:02 access.log.2.gz
-rw-r--r-- 1 www-data www-data   6972317 Jun 23 07:53 access.log.3.gz
-rw-r--r-- 1 www-data www-data   3136381 Jun 22 07:50 access.log.4.gz
-rw-r--r-- 1 www-data www-data   2661418 Jun 21 07:45 access.log.5.gz
-rw-r--r-- 1 www-data www-data   5098097 Jun 20 07:38 access.log.6.gz
-rw-r--r-- 1 www-data www-data   6461672 Jun 19 07:40 access.log.7.gz
-rw-r--r-- 1 www-data www-data         0 Jun 25 08:02 error.log
-rw-r--r-- 1 www-data www-data         0 Jun 24 08:02 error.log.1
-rw-r--r-- 1 www-data www-data        20 Jun 23 07:53 error.log.2.gz
-rw-r--r-- 1 www-data www-data       254 Jun 23 02:36 error.log.3.gz
-rw-r--r-- 1 www-data www-data        20 Jun 21 07:45 error.log.4.gz
-rw-r--r-- 1 www-data www-data        20 Jun 20 07:38 error.log.5.gz
-rw-r--r-- 1 www-data www-data        20 Jun 19 07:40 error.log.6.gz
-rw-r--r-- 1 www-data www-data       274 Jun 18 15:40 error.log.7.gz

ملاحظة: هذه المعلومات “داخل الحاوية” متاحة أيضًا من خارج الحاوية على الحجم المشترك (shared volume).

وبالتالي (ولإبقاء هذه الإجابة قصيرة)، @ossia، فكل ما تحتاجه تقريبًا لاكتساب معرفة ظرفية لما يحدث موجود في ملفات السجل هذه القوية. لا حاجة للتكهنات. البيانات موجودة جميعها.

هناك حتى بيانات رائعة أخرى متاحة في سجل rails، على سبيل المثال. في أحد إعداداتنا هنا، إليك سجل الإنتاج rails:

tail -f /var/discourse/shared/socket/log/rails/production.log

يحتوي سجل rails على الكثير من معلومات تسجيل الدخول الرائعة للمستخدمين أيضًا، على سبيل المثال:

Started GET "/embed/comments?topic_id=378686" for 73.63.114.60 at 2020-06-25 18:36:15 +0000
Started GET "/embed/comments?topic_id=378686" for 195.184.106.202 at 2020-06-25 18:36:16 +0000
Started GET "/embed/comments?topic_id=378686" for 17.150.212.174 at 2020-06-25 18:36:16 +0000
Started GET "/embed/comments?topic_id=378686" for 76.235.99.73 at 2020-06-25 18:36:18 +0000
Started GET "/embed/comments?topic_id=378686" for 124.253.211.42 at 2020-06-25 18:36:19 +0000
Started GET "/embed/comments?topic_id=378686" for 103.96.30.11 at 2020-06-25 18:36:21 +0000
Started GET "/embed/comments?topic_id=378686" for 72.191.206.59 at 2020-06-25 18:36:22 +0000
Started GET "/embed/comments?topic_id=378686" for 68.252.68.76 at 2020-06-25 18:36:23 +0000
Started GET "/embed/comments?topic_id=378686" for 69.17.252.83 at 2020-06-25 18:36:23 +0000
Started GET "/embed/comments?topic_id=378686" for 98.109.33.230 at 2020-06-25 18:36:24 +0000

ملاحظة: هنا (أعلى، كمثال) نرى عناوين IP للعملاء الذين يسحبون كود التضمين (embedded code) الخاص بـ discourse من خادم آخر.

المهمة المطروحة....

نعود إلى المهمة المطروحة، “الحيلة” هي تجاوز التكهنات والتخمين، والقيام بالمرحلتين الممتعتين: (1) التصفية/تنظيف البيانات، (2) دمج البيانات، و (3) تحليل بيانات أجهزة الاستشعار لديك (ملفات السجل) لإنشاء (4) الوعي الظرفي (SA) لما يحدث في موقعك.

بالنسبة لتطبيقات LAMP الأقدم، لدي في الواقع كود مخصص كتبته منذ سنوات يقوم بكتابة كل هذه المعلومات إلى جدول قاعدة بيانات ويقوم بالتحليل في الوقت الفعلي ويحسب “النقرات” حسب عنوان IP (كمثال واحد) حيث يمكنني رؤية ما يحدث ومن ومن أين يضرب الموقع بسرعة، لأن هذا النوع من تنظيف البيانات وتصفيتها ودمجها يتطلب بعض الكود. (مفيد أثناء هجمات DDOS ونشاط الروبوتات الخبيثة، على سبيل المثال).

هذا ليس مشكلة بالنسبة لك @ossia لأنك freeCodeCamp.org، لذا لديك كل من المعرفة للعثور على أدوات رائعة لتحليل ملفات السجل (هناك العديد منها في العالم السيبراني) و/أو إنشاء كود مخصص خاص بك لإجراء التحليل بسرعة وسهولة بناءً على السيناريو الذي ترغب في فهمه (موضوعك ومشكلتك).

لقد كتبت كودي المخصص لتطبيق LAMP قديم قبل سنوات في بضع ساعات، وأنا لست عبقري برمجة بأي حال من الأحوال، حتى لو يُشار إليّ أحيانًا بـ “أسطورة” من قبل العديد في مجال الأمن السيبراني، LOL :slight_smile:

للخلاصة....

حسنًا، للخلاصة…

لديك جميع البيانات التي تحتاجها لإنشاء معرفة ظرفية عميقة حول “ما يحدث” في موقعك. ويمكنك إنشاء هذا الوعي الظرفي (SA) من خلال تنظيف وتصفية ودمج وإجراء بعض التحليلات الأساسية لبيانات ملفات السجل لديك. هناك أدوات متاحة يمكن أن تساعد، لكنني دائمًا ما أجد أنه من الأسهل كتابة بعض الكود المخصص بناءً على هدف التحليل (تحليل معتمد)، وقد يختلف الأمر من شخص لآخر. لكن يمكنك القيام بذلك بسهولة لأنك freeCodeCamp.org ولديك الكثير من المهارات التقنية.

أوصيك بالابتعاد عن محاولة اكتساب الوعي الظرفي (SA) من Google Analytics وتطبيقات الطرف الثالث الأخرى القائمة على JavaScript. لا يوجد شيء أفضل من ملفات سجل الويب الخاصة بك (وأيضًا بيانات جلسة قاعدة البيانات إذا كانت متاحة لديك)، ولا داعي للقلق بشأن “ما قد يتم حظره أو لا” وما إلى ذلك. تحتوي ملفات سجل خادم الويب لديك على البيانات اللازمة لاكتساب الوعي الظرفي السيبراني (CSA) الذي تحتاجه (ويمكن أيضًا تخصيصها عند الحاجة).

في بعض أكواد الوعي الظرفي السيبراني (CSA) الخاصة بي، أقوم فعليًا باعتراض معلومات الجلسة ومعلومات السجل من طلبات HTTP التي لا يسجلها nginx أو apache2 أو خوادم الويب الأخرى (لمعلومات إضافية)؛ لكنني لم أكتب هذا النوع من الكود لـ discourse (بعد) لأنني لست “سهلًا مثل الفطيرة” كمطور إضافات discourse (مثل خبراء فريق meta discourse هنا) كما هو الحال مع تطبيقات LAMP، حيث بدأت فقط مع discourse قبل بضعة أشهر ولم أكتب بعد أي كود مخصص للوعي الظرفي السيبراني (CSA) لـ discourse (وحاولت كتابة كود أقل هذا العام، بصراحة).

الوعي الظرفي السيبراني (CSA) مبني على دمج بيانات أجهزة الاستشعار، ومن الوعي الظرفي السيبراني (CSA) تنبع المعرفة لفهم الإجراءات التي تحتاج إلى اتخاذها لتصحيح أي مشكلة أمنية سيبرانية.

كل التوفيق في سعيك، وآمل أن يساعدك هذا على الحصول على راحة أكثر :slight_smile:

تحياتي!


المرجع الأصلي (التاريخي) للوعي الظرفي السيبراني (CSA):

المرجع الأصلي (التاريخي) للوعي الظرفي السيبراني (CSA):

https://www.researchgate.net/publication/220420389_Intrusion_Detection_Systems_and_Multisensor_Data_Fusion

(مرجع فقط للأشخاص المهتمين بأصول وتقنية الوعي الظرفي السيبراني الأساسية)

13 إعجابًا

شكرًا لكم على عملكم الشاق، يا فريق!

وشكرًا لكم جـدًا جدًا جدًا
على تبسيط
شريط الأدوات المزدوج :nauseated_face:

4 إعجابات

سأقوم فقط بإغلاق الحلقة هنا.

تستضيف منصة Discourse الآن https://forum.freecodecamp.org/. الموقع سريع للغاية، ولم تعد سكريبتات المُرسلين المزعجين تسبب حتى أدنى اضطراب. لا يزال لدينا بعض الغموض حول المشكلة التي كانت موجودة على Digital Ocean؛ فقد يكون هناك جار “صاخب”، أو أن الجهاز كان ضعيف الطاقة، أو ربما كانت هناك أعطال غير مفسرة في الجهاز، ونحن غير متأكدين. لكن المشكلة الأصلية قد حُلت بنسبة 100% الآن، والمجتمع سعيد جداً.

16 إعجابًا