السجلات والاستجابة للحوادث
كيف نعرف أننا اختُرقنا، وماذا نفعل حين يقع الحادث؟ ⏱ نحو 40 دقيقة.
- تميّز ما يُسجَّل مما لا يُسجَّل.
- تكتب وسيط تسجيل منظّمًا للأحداث الأمنية.
- تربط السجل بالمراقبة والتنبيه.
- تتبع دورة الاستجابة للحوادث.
١ما لا يُسجَّل لا يُكتشف
فئة A09 في OWASP: نقص التسجيل والمراقبة. أغلب الاختراقات تُكتشف بعد شهور، لأن لا أحد كان ينظر. السجل الجيد هو الفرق بين «نعرف ماذا حدث ومتى» و«لا نعرف أننا اختُرقنا».
لكن التسجيل سلاح ذو حدّين: تسجيل البيانات الحسّاسة يصنع ثغرة تسريب. القاعدة: سجّل الأحداث لا الأسرار.
| سجّل ✓ | لا تسجّل ✗ |
|---|---|
| نجاح وفشل تسجيل الدخول | كلمات المرور (ولو مجزّأة) |
| تغيير الصلاحيات والأدوار | أرقام البطاقات كاملة |
| الوصول لموارد حسّاسة | رموز الجلسات والمفاتيح |
| تجاوز حدّ المعدل (الدرس 13) | بيانات صحّية/شخصية غير ضرورية |
| الأخطاء من جانب الخادم | محتوى الطلب كاملًا دون تنقية |
٢وسيط تسجيل
نسجّل كل حدث أمني سطرًا منظّمًا (JSON) فيه الوقت والمصدر والفعل والنتيجة والمستخدم — بلا أسرار:
const express = require('express');const app = express();app.use(express.json());app.use(express.urlencoded({ extended: false })); function logLine(req, status) { // سجّل الحدث الأمني دون بيانات حسّاسة console.log(JSON.stringify({ time: '2025-10-15T10:00:00Z', ip: req.ip || 'test', method: req.method, path: req.path, status, user: req.userId || null, }));} app.post('/login', (req, res) => { const ok = req.body.pass === 's@rah123'; logLine(req, ok ? 200 : 401); // نسجّل النجاح والفشل، لا كلمة المرور res.status(ok ? 200 : 401).json({ granted: ok });}); app.listen(3000);
انظر الطرفية: سطر لكل محاولة فيه الحالة (200 ثم 401) والمسار والمصدر، دون كلمة المرور. السجل المنظّم يسهّل البحث والتنبيه لاحقًا.
٣من السجل إلى الاستجابة
السجل مادة خام؛ قيمته في المراقبة: تنبيه آلي عند أنماط مريبة (ارتفاع مفاجئ في 401، أو تجاوزات معدل، أو وصول إداري في وقت غريب). وحين يقع حادث، نتبع دورة منظّمة:
| المرحلة | الفعل |
|---|---|
| التحضير | خطة ومسؤوليات وسجلات جاهزة قبل الحادث |
| الكشف | التنبيه يكشف النشاط المريب |
| الاحتواء | عزل المتأثر لوقف الانتشار |
| الاستئصال | إزالة السبب (سدّ الثغرة، إبطال الجلسات) |
| التعافي | إعادة الخدمة ومراقبتها |
| الدروس المستفادة | ماذا نغيّر كيلا يتكرر؟ |
«الدروس المستفادة» تعيدنا إلى «التحضير»: كل حادث يحسّن دفاعك. هذا ناتج التعلم الأخير: اكتشاف الأنشطة غير المصرّح بها وتنفيذ تدابير الوقاية والاستجابة.
توقّع وتحقّق
لماذا نسجّل الأحداث الأمنية؟
أيّ مما يلي لا يُسجَّل؟
أين يُحفظ السجل ليصعب محوه؟
آخر مراحل الاستجابة للحوادث:
الخلاصة
- ما لا يُسجَّل لا يُكتشف؛ ونقص التسجيل فئة
A09فيOWASP. - سجّل الأحداث (دخول، صلاحيات، وصول حسّاس) لا الأسرار (كلمات، رموز، بطاقات).
- السجل المنظّم بعيدًا عن الخادم يُمكّن البحث والتنبيه ويصعب محوه.
- الاستجابة للحوادث دورة: تحضير، كشف، احتواء، استئصال، تعافٍ، دروس مستفادة.
تحدٍّ برمجي: سجّل حدثًا حسّاسًا
متوسطمسار حذف المستخدم إداريّ وخطير لكنه لا يُسجَّل، فلا أثر لمن حذف من. أضف تسجيلًا منظّمًا للحدث دون بيانات حسّاسة.
- سجّل سطرًا عند كل حذف فيه الفعل والمستخدم المنفِّذ والهدف.
- اطبعه بـ
console.log(نصًّا أو JSON). - يبقى الحذف يعمل ويعيد المعرّف المحذوف.
👀 اعرض الاستجابات المطلوبة
- 👤 المدير
POST /admin/delete-user{"id": 7}
- الخادم يعمل ويرد على كل الطلبات بلا أخطاء غير معالَجة
- الحذف يعمل ويعيد المعرّف
- يُسجَّل الفعل في الطرفية
- يستخدم console.log للتسجيل
- لا يسجّل كلمة مرور
💡 تلميح 1
audit تطبع JSON فيه action و user و target.💡 تلميح 2
audit(req, 'delete-user', { target: req.body.id });.💡 تلميح 3
حاول بنفسك أولًا؛ للمسألة أكثر من حلّ صحيح.
const express = require('express');const app = express();app.use(express.json());app.use(express.urlencoded({ extended: false })); function audit(req, action, extra) { console.log(JSON.stringify({ ip: req.ip || 'test', action, user: req.userId || null, ...extra, }));}app.post('/admin/delete-user', (req, res) => { audit(req, 'delete-user', { target: req.body.id }); res.json({ deleted: req.body.id });});app.listen(3000);