تركت ووردبريس، وفتحت phpMyAdmin، واكتشفت أن موقعي القديم قد تعرّض للاختراق

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

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

ثم لاحظت شيئاً مثيراً للاهتمام.

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


رائع.

لا يمكنني الجزم بدقة بكيفية اختراق تثبيت WordPress القديم من دون إجراء فحص جنائي كامل للخادم. قد يكون السبب حقن SQL. وقد يكون مكوّنًا إضافيًا عرضة للاختراق أو قديمًا. وربما كانت ثغرة في القالب، أو بيانات اعتماد مسؤول مسروقة، أو بيانات اعتماد FTP أو الاستضافة مخترقة، أو بابًا خلفيًا قديمًا بلغة PHP، أو عملية رفع ضارة، أو بيانات اعتماد قاعدة بيانات مكشوفة، أو مكوّنًا منسيًا آخر ظل موجودًا على الخادم لسنوات.

النقطة المهمة هي أن العثور على سجلات تالفة في قاعدة بيانات لا يثبت تلقائيًا وجود حقن SQL. أي شخص يرى صفوفًا غريبة في قاعدة البيانات ويصرخ فورًا، "SQL INJECTION!" من دون فحص الخادم، إنما يخمّن. هناك طرق كثيرة لاختراق تثبيت WordPress. وللأسف، يقدّم WordPress للمهاجمين قائمة خيارات واسعة جدًا عندما يكون التثبيت قد تراكمت فيه بما يكفي من المكوّنات الإضافية والقوالب والمستخدمين والنسخ الاحتياطية والملفات المنسية على مر السنين.

اختفى WordPress، لكن درس الأمان بقي

موقعي الحالي لا يستخدم WordPress على الإطلاق. إنه يعمل على نظام إدارة محتوى مخصص بنيته خصيصًا لتلبية احتياجاتي. وهو يدير الصفحات والمنشورات والفئات والوسائط وتحسين محركات البحث والترجمات وأدوات المحتوى المدعومة من OpenAI والتعليقات ودفعات Stripe والوظائف الإدارية والمكوّنات الإضافية المخصصة وتدقيق الأمان والميزات الأخرى التي أستخدمها فعليًا.

أدى إزالة WordPress إلى التخلص من قدر هائل من مساحة الهجوم غير الضرورية. فلا توجد منظومة ضخمة من المكوّنات الإضافية تعمل خلف الموقع. ولا توجد قوالب عشوائية تستدعي مكتبات من عشرة مطورين مختلفين. ولا توجد مكوّنات إضافية منسية توقفت عن تلقي تحديثات الأمان قبل خمس سنوات. وإذا أردت ميزة، فأنا أعرف بالضبط أين نُفذت تلك الميزة وما الشيفرة المسؤولة عنها.

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

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

البدء بقاعدة البيانات

كانت إحدى أولى المناطق التي راجعتها هي أمن قاعدة البيانات. يستخدم نظام إدارة المحتوى الجديد عبارات PDO المُعدّة مسبقًا للقيم التي يتحكم فيها المستخدم، بدلًا من إنشاء استعلامات SQL من خلال ربط حقول نماذج عشوائية مباشرةً داخل سلاسل الاستعلام. ويقلل ذلك بدرجة كبيرة من سطح الهجوم التقليدي لحقن SQL.

كما أن تنفيذ العبارات المتعددة في MySQL معطّل لاتصالات قاعدة بيانات التطبيق العادية. وينبغي ألا يمتلك حساب قاعدة البيانات سوى الأذونات التي يحتاج إليها نظام إدارة المحتوى فعليًا. فلا حاجة إلى منح تطبيق PHP المواجه للعامة امتيازات إدارية غير محدودة على قاعدة البيانات لمجرد أن منح كل شيء أسهل.

لم تكن الراحة والأمن رفيقين جيدين على نحو خاص قط.

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

أنشأتُ مركزًا أمنيًا لأنني أريد أن أعرف من يطرق الباب

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

يحتوي نظام إدارة المحتوى الآن على مركز أمني مخصص يسجل الأنشطة المتعلقة بالأمان. وبحسب الحدث، يمكنه تسجيل عنوان IP المصدر، والتاريخ والوقت، وطريقة الطلب، والمسار المطلوب، ووكيل المستخدم، والمسؤول الذي تمت مصادقته، وفئة الحدث، ومستوى الخطورة، ومدى تكرار ملاحظة النشاط نفسه.

يمكن للنظام الأمني تتبع عمليات تسجيل دخول المسؤولين الناجحة والفاشلة، وفشل التفويض، وعمليات الاستكشاف المريبة لعناوين URL، وانتهاكات حدود المعدل، وطلبات POST الإدارية، وتعديلات المحتوى، وفشل خطافات Stripe الشبكية، وأنشطة الاتصال والتعليقات، ومحاولات الوصول إلى نظام تسجيل دخول WordPress الوهمي.

في الوقت نفسه، يتجنب المسجل عمدًا التحول إلى صندوق كنوز للمهاجم. لا تُخزَّن كلمات المرور. ولا تُفرَّغ ملفات تعريف الارتباط في السجل. وتُستبعد ترويسات التفويض، ومفاتيح API، وأسرار Stripe، ورموز CSRF، وبيانات الاعتماد المماثلة أو تُحجَب. فلا جدوى من إنشاء نظام أمني متطور ثم تخزين كل سر قد يريده المهاجم بسهولة في جدول واحد بقاعدة البيانات.

المسؤول

حظر عناوين IP مدمج في نظام إدارة المحتوى

إذا رأيت ماسحًا ضوئيًا مُصرًّا بشكل خاص أو شخصًا يحاول مرارًا إرسال طلبات مشبوهة، فيمكنني حظر عنوان IPv4 أو IPv6 الفردي مباشرةً من مركز الأمان. ويمكن أيضًا حظر نطاقات CIDR عند الضرورة.

يمكن لنظام إدارة المحتوى فرض عمليات الحظر هذه على مستوى التطبيق، لكنه يستطيع أيضًا إنشاء قواعد Apache للحظر على مستوى الخادم. وهذا التمييز مهم. فعندما أحظر شخصًا داخل PHP، يظل على تطبيق الويب استقبال جزء من الطلب ومعالجته. أما حظر العنوان على مستوى Apache أو جدار الحماية أو حافة الشبكة فهو أفضل، لأن الطلب يمكن رفضه قبل أن يضطر التطبيق إلى إهدار الموارد في التعامل معه.

إذا كنت سأُخرج شخصًا من المبنى، فسأفضل إيقافه عند الباب الأمامي بدلًا من السماح له بركوب المصعد إلى الطابق العلوي أولًا.

أنا لا أسمح للزوار باختيار عنوان IP الخاص بهم

تتعلق مشكلة أمنية أخرى شائعة على نحو مفاجئ برؤوس مثل X-Forwarded-For وX-Real-IP. فالتطبيقات سيئة التصميم تثق أحيانًا بهذه الرؤوس تلقائيًا، وتسجل أي عنوان IP يرسله العميل.

وهذه مشكلة لأن أي شخص يستخدم Burp Suite أو curl أو نصًا برمجيًا مخصصًا أو عميل HTTP آخر يمكنه إرسال رأس توجيه مزيف. فقد يرسل المهاجم X-Forwarded-For: 8.8.8.8 وفجأة يعتقد نظام الأمان لديك أن Google تهاجمك.

لا يثق نظام إدارة المحتوى لدي برؤوس عنوان IP للعميل المُمرَّر إلا عندما ينشأ الاتصال الفعلي من عنوان وكيل قمتُ بتكوينه صراحةً باعتباره موثوقًا. وبخلاف ذلك، يعتمد نظام إدارة المحتوى على عنوان الاتصال البعيد الفعلي. ولست مهتمًا بالاحتفاظ بسجل أمني يُسمح فيه للشخص الذي يخضع للتحقيق باختيار عنوان IP الذي يظهر بجانب نشاطه.

يبدو أن الجميع على الإنترنت يريد ملف ‎.env‎ الخاص بي

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

فهي تتحرى عن أشياء مثل /.env، و/.env.production، و/.env.local، و/.env.backup، و/.env.old، و/.git/config، و/.aws/credentials، و/database.sql، و/backup.sql، وملفات إعدادات ونسخ احتياطية متنوعة.

يبدو أن متغيرات البيئة الخاصة بي تحظى بشعبية هائلة. ربما ينبغي أن أبدأ بفرض رسوم دخول.

يرفض إعداد Apache الآن الملفات المخفية، وملفات الإعداد، وملفات النسخ الاحتياطية، ونسخ قواعد البيانات، وأدلة أنظمة التحكم بالمصادر، والملفات المؤقتة، وملفات السجل، والموارد الحساسة الأخرى قبل أن يصل الطلب إلى نظام توجيه CMS المعتاد.

يُستثنى الدليل .well-known عمدًا من القيد العام المفروض على الملفات المخفية، لأن خدمات مشروعة مثل ACME وLet's Encrypt قد تحتاج إلى الوصول إليه. أما كل شيء آخر فيُعامل بقدر أقل بكثير من حسن الضيافة.

كما أفضّل إرجاع استجابة 404 عامة للعديد من طلبات الاستطلاع بدلًا من تأكيد وجود مورد محمي. فلا يوجد سبب لإخبار أداة فحص آلية: «تهانينا، لقد عثرت على ملف ‎.env‎ الخاص بي، لكن للأسف لن أسمح لك بقراءته». إن عبارة بسيطة مثل «لا شيء هنا» تقدم معلومات أقل.

لإضافة طبقة حماية أخرى، يمكن تخزين أسرار الإنتاج بالكامل خارج جذر المستندات المتاح للعامة. وبهذه الطريقة، حتى إذا تم تغيير إحدى قواعد Apache عن طريق الخطأ أو فشلت إعادة الكتابة، فلن يكون هناك ملف بيئة داخل مجلد الموقع ليقدمه خادم الويب.

تبقى المجلدات الداخلية داخلية

يحتوي نظام إدارة المحتوى على مجلدات داخلية مخصصة للإعدادات، والملفات المضمّنة، وشيفرة قاعدة البيانات، والتخزين، والإضافات، والوثائق. وتوجد هذه المجلدات لأن التطبيق يحتاج إليها. وهي ليست صفحات عامة، ولا يوجد سبب مشروع يدعو أي شخص على الإنترنت إلى تصفحها.

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

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

رؤوس الأمان طبقة أخرى

يعيد خادم الويب أيضًا مجموعة من رؤوس HTTP الموجهة نحو الأمان. وتشمل هذه الرؤوس وسائل حماية تتعلق باستكشاف نوع المحتوى، والتضمين داخل إطارات، ومعلومات المُحيل، وأذونات المتصفح، وفرض استخدام HTTPS، وسلوك سياسات النطاقات المتقاطعة، والمحتوى المضمّن القابل للتنفيذ.

يتضمن الإعداد عناصر تحكم مثل X-Content-Type-Options وReferrer-Policy وX-Frame-Options وX-Permitted-Cross-Domain-Policies وPermissions-Policy وStrict-Transport-Security وContent-Security-Policy.

لا تُعد ترويسات الأمان بدائل عن تعليمات برمجية آمنة للتطبيق. إنها ببساطة طبقة دفاعية أخرى. عادةً ما يأتي الأمان الجيد من تكديس عناصر تحكم معقولة متعددة، بدلاً من تثبيت ميزة سحرية واحدة وإعلان النصر.

تم تشديد الجلسات الإدارية

خضع نظام مصادقة المسؤول أيضاً لمراجعة أمنية جادة. تتطلب كلمات مرور المسؤولين الجديدة متطلبات دنيا أقوى، وتستخدم تجزئات كلمات المرور خوارزميات حديثة مثل Argon2id عندما تدعمها بيئة PHP. ويمكن ترقية التجزئات الأقدم المتوافقة بعد نجاح المصادقة.

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

تستخدم ملفات تعريف ارتباط الجلسة إعدادات Secure وHttpOnly وSameSite المناسبة. ويُفعَّل سلوك الجلسة الصارم، كما يمكن التحقق من خصائص إضافية للجلسة لجعل إعادة استخدام الجلسات المسروقة أكثر صعوبة.

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

ليس من المفترض أن يتحول برنامج التثبيت إلى سطح هجوم

خلال تدقيق الأمان، وجدت أيضًا شيئًا في نظام إدارة المحتوى الخاص بي لم يعجبني كثيرًا. كان برنامج التثبيت يحتوي سابقًا على آلية طوارئ مخصصة للمساعدة في استعادة عمليات التثبيت غير المكتملة.

قد يكون ذلك مناسبًا أثناء تطوير البرامج. لكنه يصبح أقل جاذبية بكثير بمجرد تشغيل الموقع في بيئة الإنتاج.

تمت إزالة تجاوز التثبيت الإجباري. وبمجرد أن يحتوي نظام إدارة المحتوى على محتوى إنتاج حقيقي، يُقفل برنامج التثبيت. إذا كنت بحاجة فعلًا إلى استعادة عملية تثبيت غير مكتملة، فعليّ تمكين وظيفة الاستعادة صراحةً من خلال إعدادات الخادم.

أفضل أن أُسبب لنفسي بعض الإزعاج لمدة ثلاثين ثانية على أن أترك مسارًا لبرنامج التثبيت قائمًا على خادم عام طوال السنوات العشر القادمة.

محرر إضافات PHP معطّل عادةً

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

أي شيء قادر على تعديل الشيفرة البرمجية القابلة للتنفيذ من جانب الخادم يستحق حماية إضافية. لذلك يكون محرر الإضافات في بيئة الإنتاج معطّلًا في ظروف التشغيل العادية. وإذا احتجتُ عمدًا إلى تعديل شيفرة إضافة، يمكنني تمكينه على مستوى الخادم، وإجراء العمل بصفتي مسؤولًا فائق الصلاحيات، ثم تعطيله مرة أخرى فورًا بعد ذلك.

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

تُعامَل الصور المرفوعة كأنها غرباء

تلقت عمليات رفع الملفات ضوابط أمنية إضافية أيضًا. لا يصدّق نظام إدارة المحتوى المتصفحَ بشكل أعمى لمجرد أن المتصفح يقول إن الملف صورة. بل يجري فحص المحتويات الفعلية والتحقق منها.

تُفكّ شفرة صور المنشورات المرفوعة ثم يُعاد ترميزها في ملفات WebP جديدة. وتُوحَّد أبعادها وفق الأبعاد التي يستخدمها نظام إدارة المحتوى، كما تساعد هذه العملية على إزالة البيانات الزائدة غير الضرورية المضمّنة في الملف الأصلي. ويتحقق التطبيق أيضًا من امتدادات الملفات، ومعلومات MIME الفعلية، وأبعاد الصور، وحجم الملف، والمشكلات المحتملة المرتبطة بإزالة الضغط.

تُرفَض امتدادات الملفات القابلة للتنفيذ، وتُهيَّأ مجلدات الرفع لمنع الملفات المرفوعة من أن تقرر فجأة أنها تفضّل التحول إلى تطبيقات PHP.

إذا رفع أحدهم ملفًا اسمه totally-not-a-webshell.php، فأنا أفضل ألا يستجيب الخادم قائلًا: «يبدو لي أنها صورة عائلية».

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

جعلتني قاعدة بيانات WordPress المخترقة أفكر أيضًا في أمر لا يتطلب من الناحية التقنية أي استغلال على الإطلاق. فقد تُساء إساءة استخدام ميزة عامة مشروعة أحيانًا بدرجة تكفي لإحداث النتيجة العملية نفسها التي يسببها الهجوم.

يحتوي موقع الويب الخاص بي على وظائف مدفوعة للتواصل والتعليق. ولكي يرسل نظام إدارة المحتوى شخصًا إلى Stripe Checkout، قد يحتاج إلى إنشاء سجل مؤقت معلّق قبل إتمام الدفع. ومن دون ضوابط، يمكن لروبوت أن يبدأ العملية مرارًا آلاف المرات، من دون أن يدفع شيئًا، ويملأ قاعدة البيانات ببطء بسجلات معلّقة عديمة الفائدة.

تخضع نقاط النهاية هذه الآن لتحديد معدل الطلبات. كما تُنظَّف سجلات التواصل والتعليقات المتروكة وغير المدفوعة تلقائيًا بعد فترة محددة. ويستخدم نظام تحديد معدل الطلبات عدادات مدمجة بدلًا من إنشاء إدخال ضخم في سجل الأمان لكل طلب عادي.

لا يتطلب كل هجوم استغلالًا متطورًا. فأحيانًا يمكن لشخص ما ببساطة الضغط على زر مشروع تمامًا عشرة آلاف مرة وتحويل قاعدة بياناتك إلى مكبّ للنفايات.

تستخدم الإجراءات الإدارية حماية CSRF

كما أن التغييرات الإدارية محمية من تزوير الطلبات عبر المواقع. فلا ينبغي لمجرد تسجيل الدخول إلى نظام إدارة المحتوى أن يسمح لموقع ويب آخر بخداع المتصفح لإرسال إجراء إداري من وراء ظهر المستخدم.

تتطلب الطلبات الإدارية الحساسة عمليات تحقق مناسبة ووسائل حماية من CSRF، بينما يمكن تسجيل الإجراءات الإدارية المهمة في سجل تدقيق الأمان. ويمنحني ذلك سجلًا يوضح ما الذي تم تغييره، ومتى حدث ذلك، وأي حساب نفّذ الإجراء، ومن أين نشأ الطلب.

قد يبدو التسجيل مبالغًا فيه عندما يكون هناك مسؤول أساسي واحد فقط. لكنه يصبح أقل مبالغة بكثير عندما يتغير شيء ما وتحدق في الشاشة مفكرًا: «أنا متأكد تمامًا أنني لم أفعل ذلك».

ثم بنيت أكثر ميزات الأمان إمتاعًا: ووردبريس زائف

ربما يكون هذا الجزء المفضل لدي من نظام الأمان بأكمله.

لم يعد موقعي يعمل بوردبريس. لا يوجد أي سبب مشروع على الإطلاق لزائر عادي أن يطلب /wp-admin أو /wp-login.php. فالقراء العاديون لا يستيقظون في الصباح ويكتبون /wp-admin بالخطأ بعد اسم نطاقي.

أما الروبوتات، فهي تحب عناوين URL تلك حبًا شديدًا.

لذلك، بدلًا من إعادة صفحة خطأ مملة فحسب، بنيت لها مفاجأة صغيرة.

إذا زار أحدهم /wp-admin أو /wp-login.php، يعرض نظام إدارة المحتوى شاشة تسجيل دخول مزيفة لووردبريس. تبدو شبيهة بووردبريس بما يكفي لإرضاء عمليات الفحص الآلية والزوار الفضوليين، لكن لا يوجد خلفها أي تثبيت فعلي لووردبريس.

يمكنهم إدخال اسم مستخدم. ويمكنهم إدخال كلمة مرور. ويمكنهم النقر على «تسجيل الدخول». ويمكنهم التحديق فيها. ويمكنهم المحاولة مرة أخرى. ويمكنهم التشكيك في قراراتهم الحياتية. وتستمر الصفحة في كونها عديمة الفائدة تمامًا بالنسبة إليهم، بينما يسجل مركز الأمان بهدوء الأجزاء المهمة من المحاولة.

يسجّل المصيد أشياء مثل عنوان IP، والطابع الزمني، ونقطة النهاية المطلوبة، ووكيل المستخدم، وعدد مرات الوصول، واسم المستخدم المُحاوَل. وهو لا يخزّن كلمة المرور المُرسَلة عمدًا. لا أحتاج إلى كلمة مرور أي شخص. كل ما أحتاج إلى معرفته هو أن عنوان IP أمضى عشرين دقيقة يحاول المصادقة على تثبيت WordPress غير موجود.

إنه في الأساس باب رقمي مرسوم على جدار من الطوب.

مصيد WordPress أكثر من مجرد مزحة

المصيد طريف، لكنه ينتج أيضًا إشارة أمنية مفيدة. وبما أن الموقع لا يستخدم WordPress فعليًا، فإن طلبات الموارد الخاصة بـ WordPress تصبح مثيرة للاهتمام فورًا.

إذا بدأ شخص ما يطلب /wp-admin أو /wp-login.php أو /wp-config.php أو /xmlrpc.php، فأنا أعرف مسبقًا أن ذلك الزائر لا يقرأ على الأرجح إحدى مقالاتي. قد يكون الطلب مجرد جزء من فحص آلي لنقاط الضعف على مستوى الإنترنت بأكمله، لكنه قد يكون أيضًا استطلاعًا للموقع المحدد.

في كلتا الحالتين، يكون الزائر قد عرّف نفسه بسهولة على أنه شيء يستحق التسجيل.

ثمة شيء مُرضٍ في أن يحاول ماسحٌ تحديد بصمة WordPress بينما تراقب منظومة إدارة المحتوى الفعلية بهدوء من خلف الستار.

لم يكن WordPress نفسه بالضرورة هو المتسبب

ينبغي أن أوضح أمرًا واحدًا. لا يمكنني الجزم بأن WordPress نفسه تسبب في الاختراق. يشغّل WordPress جزءًا هائلًا من الإنترنت، ويمكن تأمينه بالتأكيد عند صيانته على النحو الصحيح.

غالبًا ما تكمن المشكلة الأكبر فيما ينمو حول WordPress بمرور الوقت. فقد يتضمن التثبيت الناضج نواة WordPress، وقالبًا مخصصًا، وعشرين أو ثلاثين إضافة، وحسابات مسؤولين لا يتذكر أحد أنه أنشأها، وأرشيفات نسخ احتياطية، وأنظمة تخزين مؤقت، وأدوات ترحيل، وإضافات مهجورة، وملفات PHP قديمة، وأدوات لقواعد البيانات، وشيفرات متنوعة تراكمت على مدى سنوات عديدة.

يصبح كل مكوّن من تلك المكوّنات شيئًا آخر يجب الوثوق به، وتصحيحه، ومراقبته، وإزالته في نهاية المطاف.

كان تفضيلي هو تبسيط المشكلة. أردت أن أعرف بالضبط ما البرنامج الذي يشغّل موقعي الإلكتروني. إذا تصرّف شيء ما بغرابة الآن، فلست مضطرًا إلى التساؤل عما إذا كان المتسبب هو WordPress، أو قالب، أو Elementor، أو WooCommerce، أو الإضافة رقم 47، أو إضافة التوافق الخاصة بالإضافة رقم 47، أو إحدى الإضافات التي طوّرها شخص اختفى من الإنترنت في 2018.

أعرف أين توجد المسارات. وأعرف أين توجد استعلامات SQL. وأعرف أين تحدث المصادقة. وأعرف أين تُرفع الملفات. وأعرف أي نقاط النهاية تقبل طلبات POST. وأعرف كيف يعمل تكامل Stripe لديّ. وأعرف مصدر طلبات OpenAI. وأعرف أي الأدلة يجب ألا تكون عامة على الإطلاق.

يصعب تحديد قيمة مالية لهذا النوع من الرؤية.

الأمان لا يكتمل أبدًا

أهم ما خرجت به من اكتشاف الاختراق القديم في WordPress هو أن الأمان ليس شيئًا تثبّته مرة واحدة ثم تنساه. لا توجد خانة اختيار تقول "موقع آمن: نعم".

يجب مراجعة سجلات الأمان. ويجب تحديث البرمجيات. ويجب أحيانًا تدوير بيانات الاعتماد. ويجب التحقق من أذونات الملفات. ويجب التحقيق في نشاط قاعدة البيانات غير المتوقع. يجب أن تكون هناك نسخ احتياطية، ولكن يُفضّل ألا تكون على هيئة /backup.zip موجودة داخل الموقع العام بانتظار أن يكتشفها أحد أدوات الفحص.

يجب حذف الملفات القديمة. ويجب تعطيل أدوات التطوير في بيئة الإنتاج. ويجب أن يستخدم المسؤولون مصادقة قوية. ويجب التحقق من الملفات المرفوعة. ويجب جعل استعلامات قاعدة البيانات ذات معاملات. ويجب حماية الأدلة الحساسة. ويجب أن تكون الطلبات المشبوهة مرئية.

وإذا أراد شخص ما قضاء أمسية في محاولة تنفيذ هجوم تخمين شامل على تثبيت WordPress وهمي على موقع لا يشغّل WordPress فعليًا، فعليك أحيانًا أن تُعجب بهذا التفاني.

لماذا ما زلت سعيدًا لأنني تركت WordPress

تركت WordPress في الأصل لأنني كنت أريد موقعًا أسرع وأنظف وأكثر قابلية للتحكم. كنت أريد نظام إدارة محتوى مبنيًا حول سير عمل النشر الخاص بي، بدلًا من قضاء وقتي في تثبيت إضافات للتحايل على إضافات أخرى.

إن اكتشافي أن التثبيت القديم قد اختُرق على ما يبدو منحني سببًا آخر لمواصلة السير في ذلك الاتجاه.

نظام إدارة المحتوى الحالي لدي ليس محصنًا تمامًا. لا شيء مكشوفًا على الإنترنت يكون كذلك. الفرق هو أنني أتحكم الآن في التطبيق. أتحكم في طبقة قاعدة البيانات. أتحكم في المصادقة. أتحكم في مسار رفع الملفات. أتحكم في التوجيه. أتحكم في سجلات الأمان. أتحكم في الوظائف الإدارية الموجودة ومتى يتم تمكينها.

والأهم من ذلك، يمكنني فعلًا أن أرى متى يعبث شخص ما بالأبواب.

وإذا أصرّت تلك الماسحات بشدة على العثور على ووردبريس؟

حسنًا.

لقد تركت لهم واحدًا.

نوعًا ما.