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

We started seeing heightened loads on the freeCodeCamp.org Discourse on June 21. Our average CPU load started to grow to the point that the entire forum became unresponsive.

Our Initial investigation

  1. We updated Discourse from the Stable version to the latest Tests-Passed (Beta) version, which is recommended to get all the latest performance fixes. There seemed to not be much of a difference.

  2. We got rid of some of the old plugins to help diagnose the issue, and it does not seem to be the case for slow down.

  3. To rule out any misconfigurations, we tested this with the default theme and checked the /logs and did find some exceptions:

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

This seems to be because the instance may already stressed out with a lot of long running jobs.

The discourse container (upstream) is running on Digital Ocean, and seems to be running hot on all 6 vCPUs. It is currently running on version: 2.5.0.beta7

Further investigation

  1. This morning our moderators let us know that there was a significant increase in the number of spam accounts, which was leading us to believe that this could be a targeted attack.

  2. To try and mitigate the issue, we have put the forum into read-only mode. Despite this, the resource utilization rate remains quite high at 60+%.

  3. From what we can tell: ever since this started, we have been seeing a lower requests-per-second and higher current request rate on our proxy:

  1. The volume of traffic to freecodecamp.org/forum has not significantly changed according to Google Analytics.
  2. None of the other applications on the same proxy seem to be affected. Our /news and /learn platform are operating normally.
  3. We tried adding some additional rate limiting on the proxy, and it did not make much difference, so we removed it (to allow normal users to continue to reach our site).
  4. We have also moved our old forum.freecodecamp.com redirects away from the .org forum since we noticed that old subdomain (which we haven’t used in 2.5 years) had a big spike in traffic starting a few days ago.

At the moment with ~400 real-time users, the stats look like so:

Observations About The Spammer’s Behavior

The spammers seem to be running some sort of script that creates new accounts on a Discourse instance, then waits several days. Then those accounts suddenly become active. They start posting new threads with links to a website. (Perhaps to build backlinks?)

Some of these accounts were created all the way back in March.

Here’s what one of their spam posts look like, though there are a lot of variants, linking to a lot of websites:

Any advice would be welcome here.

14 إعجابًا

This deserves much more attention

Thank you so much for sharing!

One of my favorite Discourse instances, freeCodeCamp, has slowed to a halt the last two days.

5 إعجابات

I don’t think that the heavy load main problem caused by spammer.
Here is why:

Normal discourse usage (without API) can only work with modern browser because it heavily depend on javascript. Google Analytics use javascript too to collect various user informations (and doesn’t need modern javascript support to run the analytics code). If Google Analytics can’t detect user activity, then discourse should not be able to serve its content and features.

Here is bot capture when I use old headless browser library (phantomjs) to access discourse site :

And here is with more modern library (puppeteer)

  1. It’s just strange if someone able to post (without API) replies on discourse while google analytics can’t detect them.
  2. Usually, spammers use public proxy to do dirty things and I think your cloudflare is smart enough to stop “bad visitors” before really reach your app.

Did you see high queue jobs on sidekiq process?

إعجابَين (2)

This ignores the fact that more than half of people in tech communities are running some sort of Ad Block extension, which always block Google Analytics by default.

18 إعجابًا

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

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

5 إعجابات

Is akismet enabled? Can you turn on moderation for trust level 1?

إعجابَين (2)

Yes, we did see the jobs kicking up and down as a part of my initial investigation. We then proceeded to revoke all of the user keys.

It does not seem have had done any change on the stability though.

Although we are working very closely with the Discourse team to resolve this.

5 إعجابات

I don’t see why it’s strange if there can be requests without js based analytics showing anything.
The spammer can use the same endpoints as the javascript does, without javascript. No javascript based analytics would trigger

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 إعجابًا