> ## Content Index
> Fetch the complete content index at: https://arabroot.io/llms.txt
> Use this file to discover other available public pages before exploring further.

# يوم محلل SOC: فرز التنبيهات Alert Triage من التنبيه إلى القرار
- URL: https://arabroot.io/articles/يوم-محلل-soc-فرز-التنبيهات-من-التنبيه-الى-القرار/
- Published: 2026-10-26T22:03:36.000Z
- Updated: 2026-10-28T09:56:47.000Z
- Description: ستة عشر تنبيهاً حقيقياً من Wazuh وSuricata نفرزها واحداً واحداً بالإثراء من Zeek حتى القرار والتصعيد.
- Author: فريق عرب رووت
- Tags: الأدلة التقنية, الأمن السيبراني, Wazuh, لينكس والسيرفرات

صباح الأحد في شركة التوزيع الصغيرة التي بنينا لها المراقبة في المقالين السابقين، وصلت ريم إلى مكتبها في الثامنة، وهي المحللة الوحيدة في نوبة الصباح، فوجدت في الطابور ستة عشر تنبيهاً من يوم السبت: تسعة من Wazuh على سيرفر المتجر web01، وسبعة من Suricata على حركة الشبكة نفسها. بعضها بالمستوى 12، وبعضها بالأولوية 1، وكلها تبدو مهمة إذا قرأت عنوانها فقط: «تخمين كلمات مرور»، «حقن SQL»، «Shellshock»، «ملف PHP جديد في مجلد الموقع»، «الأمر id رد بأنه root». وأمامها سؤالان قبل أن يصل المدير في التاسعة: أي هذه التنبيهات حادثة حقيقية يجب أن يعرف بها الآن، وأيها ضجيج يجب أن يغلق بسبب مكتوب؟

هذا العمل اسمه فرز التنبيهات Alert Triage، وهو أكثر ما يفعله محلل مركز العمليات الأمنية SOC في يومه، وأقل ما يكتب عنه بالتفصيل. فالمقالات عن Wazuh وSuricata تنتهي عادة عند ظهور التنبيه، كأن ظهوره هو النهاية، والحقيقة أن التنبيه بداية سؤال، والإجابة عنه تحتاج طريقة ثابتة. والتنبيهات الستة عشر في هذا المقال ليست مثالاً مكتوباً باليد، وإنما مخرجات حقيقية من مختبرين شغلناهما يوم 25 أكتوبر 2026: تنبيهات Wazuh من [مقال مراقبة السيرفرات مع Wazuh](https://arabroot.io/articles/%D9%85%D8%B1%D8%A7%D9%82%D8%A8%D8%A9-%D8%A7%D9%84%D8%B3%D9%8A%D8%B1%D9%81%D8%B1%D8%A7%D8%AA-%D9%85%D8%B9-wazuh-%D9%85%D9%86-%D8%A7%D9%84%D8%B3%D8%AC%D9%84-%D8%A7%D9%84%D9%89-%D8%AD%D8%B8%D8%B1-%D8%A7%D9%84%D9%85%D9%87%D8%A7%D8%AC%D9%85/)، وتنبيهات Suricata وسجلات Zeek من ملف الحركة في [مقال Suricata وZeek](https://arabroot.io/articles/%D8%A7%D9%83%D8%AA%D8%B4%D8%A7%D9%81-%D8%A7%D9%84%D8%AA%D8%B3%D9%84%D9%84-%D9%81%D9%8A-%D8%A7%D9%84%D8%B4%D8%A8%D9%83%D8%A9-ids-%D9%85%D8%B9-suricata-%D9%88-zeek/)، وقد أعدنا تشغيل ملف الحركة نفسه في هذا المقال، ثم بنينا أداة فرز صغيرة تجمع الطابور وتثريه، ومشينا مع ريم على كل تنبيه حتى القرار.

[![](https://arabroot.io/content/images/2026/10/wazuh-lab-cover-cover.webp)دليلمراقبة السيرفرات مع Wazuh: من السجل Log إلى حظر المهاجمشغلنا Wazuh مع وكيل على سيرفر تجريبي، فكشف تخمين كلمات مرور SSH وحظر المهاجم تلقائياً، ونبه على ملف PHP دخيل خلال ثانية.](https://arabroot.io/articles/%D9%85%D8%B1%D8%A7%D9%82%D8%A8%D8%A9-%D8%A7%D9%84%D8%B3%D9%8A%D8%B1%D9%81%D8%B1%D8%A7%D8%AA-%D9%85%D8%B9-wazuh-%D9%85%D9%86-%D8%A7%D9%84%D8%B3%D8%AC%D9%84-%D8%A7%D9%84%D9%89-%D8%AD%D8%B8%D8%B1-%D8%A7%D9%84%D9%85%D9%87%D8%A7%D8%AC%D9%85/)[![](https://arabroot.io/content/images/2026/10/suricata-zeek-cover-cover.webp)دليلمراقبة الشبكة واكتشاف التسلل IDS مع Suricata وZeekمختبر حقيقي يقرأ الحركة نفسها بأداتين، فيكشف Suricata الهجمات المعروفة ويكتب Zeek سجلاً لكل اتصال، مع الضبط وفقد الحزم.](https://arabroot.io/articles/%D8%A7%D9%83%D8%AA%D8%B4%D8%A7%D9%81-%D8%A7%D9%84%D8%AA%D8%B3%D9%84%D9%84-%D9%81%D9%8A-%D8%A7%D9%84%D8%B4%D8%A8%D9%83%D8%A9-ids-%D9%85%D8%B9-suricata-%D9%88-zeek/)

وسوف نناقش في هذا المقال ما يلي:

- يوم المحلل من استلام النوبة إلى تسليمها، ولماذا لا يقرأ التنبيهات بترتيب وصولها.
- خطوات الفرز الخمس: الفهم، والإثراء Enrichment، والقرار، والتصعيد Escalation، والتوثيق.
- الأحكام: الصحيح True Positive والخاطئ False Positive والفائت False Negative، والحكم الخامس الذي يخطئ فيه المبتدئون: الصحيح المتوقع Benign True Positive.
- الخطورة والأولوية: لماذا جعلت أول نسخة من أداتنا اثني عشر تنبيهاً من ستة عشر في الأولوية الأولى، وكيف أصلحناها.
- تجربة عملية: نعيد ملف الحركة إلى Suricata وZeek، ونجمع تنبيهات Wazuh، ونرتب الطابور بسكربت يثري كل تنبيه من سجلات Zeek وملف الأصول.
- الفرز تنبيهاً تنبيهاً، من الأولوية الأولى إلى الرابعة، مع ملاحظة الفرز Triage Note لكل قرار.
- تجربة «ماذا لو»: قائمة السماح Allowlist الضيقة التي تسكت الضجيج، والواسعة التي أخفت تنبيه نجاح.
- التصعيد إلى المستجيب، والقياس، والضبط Tuning، وأخطاء شائعة، وقائمة تحقق.

## يوم المحلل: من استلام النوبة إلى تسليمها

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

![خمس مراحل من اليمين: استلام النوبة بما بقي مفتوحاً وأي حادثة جارية وأي تغيير في القواعد، ثم ترتيب الطابور لستة عشر تنبيهاً من Wazuh وSuricata بالأولوية لا بالوقت، ثم الفرز بخمس خطوات لكل تنبيه، ثم التصعيد بقضية وأدلتها للمستجيب، ثم الضبط والتسليم بطلب تعديل قاعدة وملاحظة للنوبة التالية، وتحتها أن التنبيهات من مختبرين حقيقيين يوم 25 أكتوبر 2026](https://arabroot.io/content/images/2026/10/soc-triage-01-day.webp)

أغلب اليوم في المرحلة الثالثة، وأخطر الأخطاء في الثانية: أن تقرأ بترتيب الوصول

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

ولماذا يحتاج هذا العمل إنساناً أصلاً، وقد كتبنا القواعد وضبطنا مستوياتها؟ لأن القاعدة تعرف ما في السطر الذي أمامها فقط، ولا تعرف أن الموظفة سارة رقت زميلها عمر إلى مدير بطلب من مديرها أمس، ولا أن سيرفر الفحص الليلي هو من أرسل طلبات sqlmap. وهذا ما تقوله الضوابط الأساسية للأمن السيبراني أيضاً، فالضابط 2-12-3-4 في [وثيقة ECC-2:2024](https://cdn.nca.gov.sa/api/files/public/upload/86e09090-44e4-481f-bc28-355673607654%5FECC--2024-EN.pdf?ref=arabroot.io) يطلب المراقبة المستمرة لسجلات الأحداث Continuous Monitoring، والمراقبة لا تعني أن الأداة تعمل، وإنما أن أحداً يقرأ ويقرر، كما شرحنا في [الضوابط الأساسية بلغة بسيطة](https://arabroot.io/articles/%D8%A7%D9%84%D8%B6%D9%88%D8%A7%D8%A8%D8%B7-%D8%A7%D9%84%D8%A7%D8%B3%D8%A7%D8%B3%D9%8A%D8%A9-%D9%84%D9%84%D8%A7%D9%85%D9%86-%D8%A7%D9%84%D8%B3%D9%8A%D8%A8%D8%B1%D8%A7%D9%86%D9%8A-nca-ecc-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A8%D8%B3%D9%8A%D8%B7%D8%A9/).

## خطوات الفرز الخمس

كل تنبيه في الطابور، مهما كان مصدره، يمر على نفس الخطوات، والصورة التالية تبين السؤال الذي تجيب عنه كل خطوة:

![خمس خطوات: افهم Triage وسؤالها ماذا تقول القاعدة بالضبط محاولة أم نجاح وعلى أي أصل، ثم أثر Enrich وسؤالها ماذا رد السيرفر ومن صاحب الجهاز وهل تكرر وماذا حدث قبله وبعده، ثم قرر Decide صحيح أم خاطئ أم صحيح متوقع وما الخطورة P1 إلى P4، ثم صعد Escalate هل يحتاج المستجيب الآن أم مالك النظام أم يكفي الإغلاق، ثم وثق Document ما رأيت وبماذا قررت ولماذا، وملاحظة أن كل خطوة تكتب سطرها في الملاحظة وأنت تعمل](https://arabroot.io/content/images/2026/10/soc-triage-02-five-steps.webp)

الخطوات ثابتة، والوقت في كل خطوة يختلف بحسب التنبيه

1. **افهم Triage:** اقرأ القاعدة لا عنوانها. ماذا تبحث عنه بالضبط؟ هل تطلق على الطلب أم على الرد؟ هل تقول إن أحداً حاول، أم إن شيئاً نجح؟ فالقاعدة «Possible CVE-2014-6271 Attempt» تقول في اسمها إنها محاولة، بينما «id check returned root» تقول إن رداً خرج من السيرفر يشبه مخرج أمر نجح، والفرق بينهما هو الفرق بين محاولة يرسلها كل فاحص على الإنترنت ونجاح يستحق أن يتوقف له كل شيء.
2. **أثر Enrich:** أضف إلى التنبيه ما لا يعرفه. من صاحب الجهاز المستهدف وما أهميته؟ ماذا رد السيرفر، وكم بايتاً خرج؟ هل ظهر المصدر نفسه في تنبيهات أخرى اليوم أو هذا الشهر؟ ماذا حدث على نفس الجهاز قبل التنبيه بدقائق وبعده؟ وأهم مصادر الإثراء هي التي بنيتها بنفسك: سجلات Zeek، وملف الأصول، وتاريخ التنبيهات.
3. **قرر Decide:** الحكم، أي صحيح أم خاطئ أم صحيح متوقع، ثم الخطورة، وكلاهما مكتوب بسبب.
4. **صعد Escalate:** القرار لا يكفي، فإلى أين يذهب؟ يغلق، أو يذهب إلى مالك النظام بطلب، أو يفتح قضية للمستجيب.
5. **وثق Document:** ملاحظة الفرز Triage Note، ولا تكتب في الآخر، وإنما وأنت تعمل، سطراً لكل خطوة، لأن ما تتذكره بعد ساعة أقل بكثير مما رأيته.

وفي الخطوة الثانية يقضي المحلل أغلب وقته، والخطوة الأولى هي التي تختصره أو تطيله، فالمحلل الذي يعرف القاعدة جيداً يعرف ماذا يبحث في الإثراء، والذي لم يقرأها يبحث في كل شيء. لذلك فمن أهم ما يتعلمه المحلل الجديد أن يفتح نص القاعدة نفسها، كما فعلنا مع قاعدة id في مقال Suricata، فوجدنا أن كاتبها نفسه وضع لها `signature_severity Informational` و`confidence Medium`، أي أنه يقول لك تحقق قبل أن تقلق.

## الأحكام: صحيح وخاطئ وفائت، والحكم الخامس

أول ما تتعلمه ريم في هذا العمل أن السؤال «هل التنبيه صحيح؟» له أكثر من جواب، والصورة التالية تجمعها مع مثال من طابورها لكل واحد:

![أربعة مربعات: صحيح True Positive القاعدة أطلقت والشيء حدث مثل ملف PHP جديد في مجلد الموقع 100110، وخاطئ False Positive القاعدة أطلقت ولم يحدث ما تصفه مثل id check returned root على صفحة ثابتة، وفائت False Negative الشيء حدث ولم تطلق قاعدة مثل Shellshock عندما كان الـ Checksum فارغاً، وسليم True Negative مثل طلبي الصفحة الرئيسية، وبجانبها لوحة خامسة: صحيح ولكنه متوقع Benign True Positive عندما يفحص سيرفر الفحص الليلي المصرح به، والحل إسكات لهذا المصدر ولهذه القواعد فقط بتاريخ انتهاء](https://arabroot.io/content/images/2026/10/soc-triage-03-verdicts.webp)

الحكم الخامس هو أكثر ما يملأ الطابور في الشركات، وأكثر ما يعطل بالخطأ

- **الصحيح True Positive:** القاعدة أطلقت، والشيء الذي تصفه حدث فعلاً. وهنا يجب أن تفرق بين صحة الوصف وخطورة الحدث، فتنبيه «محاولة حقن SQL» صحيح إذا كانت هناك محاولة فعلاً، حتى لو فشلت.
- **الخاطئ False Positive:** القاعدة أطلقت، ولم يحدث ما تصفه، كما يعرفه [مسرد NIST](https://csrc.nist.gov/glossary/term/false%5Fpositive?ref=arabroot.io): تنبيه يشير خطأً إلى وجود ثغرة أو نشاط ضار. ومثاله في الطابور قاعدة id التي رأت نصاً يشبه مخرج الأمر في صفحة ثابتة وضعناها نحن.
- **الفائت False Negative:** الشيء حدث ولم تطلق أي قاعدة، وهو أخطر الأربعة لأنه لا يظهر في أي طابور، ولا تعرفه إلا بالبحث أو بعد فوات الوقت. ومثاله ما رأيناه في مقال Suricata عندما أخفى الـ Checksum الفارغ هجوم Shellshock كاملاً.
- **السليم True Negative:** لا شيء حدث، ولا قاعدة أطلقت، وهو الأغلبية الصامتة التي لا يراها أحد.
- **الصحيح المتوقع Benign True Positive:** القاعدة صادقة تماماً، فأداة فحص فحصت فعلاً، ولكن الفحص مصرح به من سيرفر الفحص الليلي. والخطأ الشائع هنا أن يكتب المحلل «False Positive» ويطلب تعطيل القاعدة، فتتعطل للجميع، ويمر الفحص الحقيقي غير المصرح به يوماً ما دون أن يراه أحد. والصحيح أن تبقى القاعدة، ويسكت هذا المصدر وحده، لهذه القواعد وحدها، بسبب مكتوب وتاريخ انتهاء، كما سنجرب في [تجربة قائمة السماح](#what-if).

وفرق آخر يحتاج أن يكون واضحاً: الحدث Event والتنبيه Alert والحادث Incident ليست كلمات مترادفة، كما شرحنا في [مصطلحات الأمن للمبتدئين](https://arabroot.io/articles/%D9%85%D8%B5%D8%B7%D9%84%D8%AD%D8%A7%D8%AA-%D8%A7%D9%84%D8%A7%D9%85%D9%86-%D8%A7%D9%84%D8%B3%D9%8A%D8%A8%D8%B1%D8%A7%D9%86%D9%8A-%D9%84%D9%84%D9%85%D8%A8%D8%AA%D8%AF%D8%A6%D9%8A%D9%86-cve-%D9%88-soc/). فالتنبيه الصحيح لا يعني حادثة، ومحاولة حقن فشلت تنبيه صحيح وليست حادثة، أما ملف PHP جديد في مجلد الموقع لم ينشره أحد فهو حادثة حتى لو لم نعرف بعد من وضعه.

## الخطورة والأولوية: لماذا لا تكفي خطورة القاعدة؟

كل تنبيه يصل ومعه رقم خطورة من الأداة: Suricata يعطي الأولوية Priority من 1 إلى 4 بحسب فئة القاعدة classtype، وWazuh يعطي المستوى Level من 0 إلى 15، ويصف [جدول تصنيف القواعد](https://documentation.wazuh.com/current/user-manual/ruleset/rules/rules-classification.html?ref=arabroot.io) المستوى 5 بأنه خطأ ولده المستخدم مثل كلمة مرور خاطئة، والمستوى 10 بأنه أخطاء متكررة من المستخدم قد تعني هجوماً أو مجرد مستخدم نسي كلمة مروره، والمستوى 12 بأنه حدث عالي الأهمية. والإغراء الطبيعي أن ترتب الطابور بهذه الأرقام، وهذا ما فعلته أول نسخة من أداة الفرز التي بنيناها، فكانت النتيجة اثني عشر تنبيهاً من ستة عشر في الأولوية الأولى P1، أي أن الترتيب لم يرتب شيئاً.

والسبب أن خطورة القاعدة تقول كم يمكن أن يكون الحدث سيئاً إذا كان حقيقياً، ولا تقول ماذا حدث فعلاً. فتنبيه Nikto بالأولوية 1 في Suricata لأن فئته «هجوم على تطبيق ويب»، وهو في الحقيقة أداة تعلن عن نفسها في الترويسة. لذلك بنينا الأولوية في النسخة الثانية من ثلاثة أسئلة:

![أربع لوحات: ماذا تقول القاعدة إنه حدث، نجاح +3 ومحاولة +2 واستطلاع أو تحقق +1 واستجابة 0، ثم على أي أصل، أصل حساس مثل سيرفر المتجر +1 من ملف الأصول، ثم ماذا رد السيرفر، رد بخطأ مثل 404 -1 من سجل Zeek، ثم الأولوية: 4 فأكثر P1 و3 P2 و2 P3 و0 إلى 1 P4، والمحاولة الأولى بخطورة القاعدة وحدها أعطت 12 من 16 في P1، وبعد السؤال الأول 4 في P1 و4 في P2 و7 في P3 و1 في P4](https://arabroot.io/content/images/2026/10/soc-triage-04-priority.webp)

الأولوية ترتب طابور العمل، ولا تغني عن القرار

- **ماذا تقول القاعدة إنه حدث؟** نجاح Success مثل ملف Web Shell موجود أو صلاحية مدير ممنوحة، أو محاولة Attempt مثل طلب حقن، أو استطلاع Recon مثل أداة فحص تعلن عن نفسها، أو تحقق Check مثل ملف جديد يعتمد معناه على مساره، أو استجابة Response مثل الحظر التلقائي الذي نفذته أنظمتنا نفسها. وهذا التصنيف نكتبه نحن لكل قاعدة مرة واحدة في ملف صغير، لأن الأداة لا تعرفه.
- **على أي أصل؟** سيرفر المتجر الذي يحمل بيانات العملاء أهم من حاسوب في المختبر، وهذه المعلومة من ملف الأصول Asset Inventory، وإذا لم يكن لديك ملف أصول فهذا أول ما تبنيه قبل أي أداة فرز.
- **ماذا رد السيرفر؟** طلب حقن رد عليه السيرفر بالرمز 404 أقل إلحاحاً من نفس الطلب برد 200، وهذه المعلومة من Zeek أو من حقل `http.status` في تنبيه Suricata.

والأرقام في الصورة ليست معياراً، وإنما وزن بسيط اخترناه لنرتب طابوراً صغيراً، والمهم فيه الفكرة: أن ما تقوله القاعدة إنه حدث يأتي أولاً، ثم الأصل، ثم النتيجة. وفي مركز عمليات حقيقي تجد نفس الفكرة في حقول مثل «الثقة» Confidence و«أهمية الأصل» في منصات SIEM، وفي حقل `confidence` الذي تضعه ET Open في بيانات قواعدها.

## تجربة عملية: الطابور من ثلاثة مصادر

الآن نبني الطابور على جهازك. نعيد ملف الحركة الحقيقي من مقال Suricata وZeek إلى الأداتين، ونأخذ تنبيهات Wazuh كما خرجت في مقاله، ثم نجمع الكل في طابور واحد بسكربت Python يثريه من سجلات Zeek ومن ملف الأصول ويقترح الأولوية. ولا يحتاج المختبر أي شبكة ولا أي منفذ، فكل شيء يقرأ ملفات.

### إعادة الحركة إلى Suricata وZeek

ننسخ من مجلد المختبر في مقال Suricata أربعة ملفات: ملف الحركة `lab.pcap`، والقواعد المحلية `local.rules`، وملف الإسكات `threshold.config`، وسكربت Zeek `scanner-ua.zeek`، ونتأكد أن ملف الحركة هو نفسه بالهاش:

```bash
sha256sum lab.pcap
docker volume create sci-soc-suricata-lib
MSYS_NO_PATHCONV=1 docker run --rm -v sci-soc-suricata-lib:/var/lib/suricata jasonish/suricata:8.0.7 suricata-update
```

والمخرج سوف يكون كما يلي، بعد اختصار سطور التحديث:

```text
e22a1e97b4782301ff8117cad2fe5d562eb8282c9c662840d3438205c8c21a35 *lab.pcap
26/10/2026 -- 18:32:50 - <Info> -- Writing rules to /var/lib/suricata/rules/suricata.rules: total: 69237; enabled: 53269; added: 69237; removed 0; modified: 0
26/10/2026 -- 18:34:02 - <Info> -- Done.
```

نفس عدد القواعد الذي رأيناه قبل يوم في مقال Suricata، 69,237 قاعدة منها 53,269 مفعلة، وهذا يعني أن تنبيهات اليوم ستكون قابلة للمقارنة بتنبيهات أمس. ثم نعيد الحركة إلى Suricata بنفس الخيارات التي انتهى إليها ذلك المقال، أي `-k none` لأن الحركة ملتقطة من Docker، والقواعد المحلية مع ET Open، وملف الإسكات:

```bash
mkdir -p out/suri out/zeek
MSYS_NO_PATHCONV=1 docker run --rm --name sci-soc-suricata -v sci-soc-suricata-lib:/var/lib/suricata -v "$(pwd -W):/lab" \
  jasonish/suricata:8.0.7 suricata -r /lab/lab.pcap -k none -s /lab/local.rules \
  --set threshold-file=/lab/threshold.config -l /lab/out/suri -v
sort out/suri/fast.log
```

والمخرج سوف يكون كما يلي:

```text
Info: detect: 2 rule files processed. 53274 rules successfully loaded, 0 rules failed, 0 rules skipped
Info: counters: Alerts: 7
10/25/2026-21:07:23.427698  [**] [1:2022028:2] ET WEB_SERVER Possible CVE-2014-6271 Attempt [**] [Classification: Attempted Administrator Privilege Gain] [Priority: 1] {TCP} 10.250.45.20:46734 -> 10.250.45.10:80
10/25/2026-21:07:23.450338  [**] [1:1000001:2] LAB SQL injection pattern in URI (OR 1=1) [**] [Classification: Web Application Attack] [Priority: 1] {TCP} 10.250.45.20:46740 -> 10.250.45.10:80
10/25/2026-21:07:23.474463  [**] [1:1000002:1] LAB Directory traversal attempt (etc/passwd) [**] [Classification: Web Application Attack] [Priority: 1] {TCP} 10.250.45.20:46750 -> 10.250.45.10:80
10/25/2026-21:07:23.498924  [**] [1:2100498:7] GPL ATTACK_RESPONSE id check returned root [**] [Classification: Potentially Bad Traffic] [Priority: 2] {TCP} 10.250.45.10:80 -> 10.250.45.20:46762
10/25/2026-21:07:23.520791  [**] [1:1000005:1] LAB Scanner user agent (Nmap) [**] [Classification: Web Application Attack] [Priority: 1] {TCP} 10.250.45.20:46772 -> 10.250.45.10:80
10/25/2026-21:07:23.623061  [**] [1:1000003:1] LAB Scanner user agent (sqlmap) [**] [Classification: Web Application Attack] [Priority: 1] {TCP} 10.250.45.20:46780 -> 10.250.45.10:80
10/25/2026-21:07:23.682638  [**] [1:1000004:1] LAB Scanner user agent (Nikto) [**] [Classification: Web Application Attack] [Priority: 1] {TCP} 10.250.45.20:46794 -> 10.250.45.10:80
```

نفس التنبيهات السبعة التي ظهرت في مقال Suricata بنفس الأوقات بالمايكروثانية، وهذه فائدة ملف الحركة المحفوظ: تعيده متى شئت فتحصل على نفس النتيجة، فتستطيع أن تجرب عليه أداة فرز أو قاعدة جديدة دون أن تنتظر هجوماً. ولاحظ أن ست تنبيهات من سبعة بالأولوية 1، وهي المشكلة التي تكلمنا عنها في القسم السابق. ثم نعيد الحركة نفسها إلى Zeek، ونطلب منه هذه المرة أن يكتب السجلات بصيغة JSON بالمتغير `LogAscii::use_json=T`، حتى يقرأها السكربت بسهولة:

```bash
MSYS_NO_PATHCONV=1 docker run --rm --name sci-soc-zeek -v "$(pwd -W):/lab" -w /lab/out/zeek zeek/zeek:9.0.0 \
  zeek -C -r /lab/lab.pcap local /lab/scanner-ua.zeek LogAscii::use_json=T
ls out/zeek
```

```text
capture_loss.log
conn.log
dns.log
files.log
http.log
known_hosts.log
known_services.log
loaded_scripts.log
notice.log
packet_filter.log
software.log
ssl.log
stats.log
```

واستغرق تشغيل Suricata كاملاً مع تحميل 53 ألف قاعدة 24 ثانية على جهاز المختبر، وZeek 9 ثوان، والسكربت الذي سنكتبه 7 ثوان أغلبها تشغيل الـ Container، وهذا يعني أن إعادة ملف حركة كاملة لتجربة فكرة أمر يستحق أن تفعله كلما احتجت.

### تنبيهات Wazuh كما خرجت

تشغيل Wazuh كاملاً يحتاج ثلاث Docker Images مجموعها أكثر من 7 جيجابايت وذاكرة قرابة 2.5 GiB كما قسنا في مقاله، ولا نحتاج ذلك هنا، لأن ما نحتاجه هو التنبيهات نفسها، وهي منشورة في المقال كما خرجت من الملف `alerts.json` على المدير يوم 25 أكتوبر. لذلك نقلناها كما هي إلى ملف CSV، بالوقت والقاعدة والمستوى والوصف والمصدر والملف وأسلوب ATT&CK:

```text
time,rule,level,description,src_ip,agent,target,mitre
2026-10-25T19:34:14Z,5763,10,sshd: brute force trying to get access to the system. Authentication failed.,192.168.112.6,web01,,T1110
2026-10-25T19:34:16Z,651,3,Host Blocked by firewall-drop Active Response,192.168.112.6,web01,,
2026-10-25T19:35:11Z,554,5,File added to the system.,,web01,/var/www/html/up.php,
2026-10-25T19:35:11Z,550,7,Integrity checksum changed.,,web01,/var/www/html/index.nginx-debian.html,T1565.001
2026-10-25T19:35:11Z,554,5,File added to the system.,,web01,/root/.ssh/authorized_keys,
2026-10-25T19:36:25Z,100110,12,New PHP file in the web root: /var/www/html/cache.php,,web01,/var/www/html/cache.php,T1505.003
2026-10-25T19:36:25Z,100111,12,SSH authorized_keys changed: /root/.ssh/authorized_keys,,web01,/root/.ssh/authorized_keys,T1098.004
2026-10-25T19:36:30Z,100102,10,shop-api: 5 failed logins from 203.0.113.50 within 60 seconds,203.0.113.50,web01,,T1110
2026-10-25T19:36:32Z,100103,12,"shop-api: omar became admin, changed by sara",,web01,,T1098
```

وتنبيهات المستوى 5 المتكررة لكل محاولة دخول فاشلة، مثل 5503 و5760، تركناها خارج الطابور عن قصد، والسبب أن الإعداد العملي في أغلب الشركات أن يصل إلى طابور المحلل ما كان بالمستوى 7 فأعلى أو ما كان له قاعدة تجميع مثل 5763، وتبقى البقية في الفهرس للبحث، وإلا امتلأ الطابور بسطر لكل كلمة مرور خاطئة.

### ملف الأصول وتصنيف القواعد

السكربت يحتاج ملفين صغيرين يكتبهما الفريق مرة واحدة ويحدثهما: ملف الأصول Assets الذي يقول ما كل عنوان وكل سيرفر ومن يملكه وما أهميته، وملف تصنيف القواعد الذي يقول لكل قاعدة هل تصف نجاحاً أم محاولة أم استطلاعاً:

```text
ip_or_host,name,role,owner,criticality
10.250.45.10,shop-web,online store web server,ecommerce team,high
web01,web01,web server with the shop-api application,ecommerce team,high
10.250.45.20,lab-client,employee workstation (lab),it support,medium
192.168.112.6,attacker,unknown host on the lab network,none,unknown
203.0.113.50,-,external address (documentation range),none,unknown
```

```text
rule,kind,note
1000003,recon,scanner announces itself (sqlmap user agent)
1000004,recon,scanner announces itself (Nikto user agent)
1000005,recon,scanner announces itself (Nmap user agent)
2022028,attempt,Shellshock pattern; success needs a CGI script run by Bash
1000001,attempt,SQL injection pattern in the URI
1000002,attempt,directory traversal in the URI
2100498,success,response looks like the output of id as root
5763,attempt,many failed SSH passwords from one address
651,response,our own active response blocked the address
554,check,new file in a monitored directory; depends on the path
550,check,monitored file changed; depends on who and why
100110,success,new PHP file in the web root (web shell, T1505.003)
100111,success,authorized_keys changed (persistence, T1098.004)
100102,attempt,application brute force
100103,success,user promoted to admin in the application
```

ولاحظ أن العمود الثالث في ملف التصنيف ليس للسكربت، وإنما للمحلل الذي يأتي بعدك، فهو يشرح لماذا صنفت القاعدة هكذا، مثل أن Shellshock لا ينجح إلا إذا كان على السيرفر سكربت CGI تشغله Bash، وهذه الجملة وحدها توفر عشر دقائق من البحث في كل مرة يظهر فيها التنبيه.

### سكربت الفرز triage.py

السكربت يقرأ تنبيهات Suricata من `eve.json`، ويبحث لكل تنبيه عن طلبه في `http.log` من Zeek بعنوان العميل ومنفذه، فيأخذ رمز الرد ومعرف الاتصال `uid`، ثم يقرأ تنبيهات Wazuh، ويحسب الأولوية بالأسئلة الثلاثة، ويرتب الطابور:

```python
"""Builds the morning triage queue from Suricata eve.json, Zeek http.log (JSON) and Wazuh alerts,
   enriches each alert (asset, outcome from Zeek, allowlist) and prints a suggested priority.
   The suggestion helps the analyst order the work; the decision stays with the analyst."""
import csv, json, sys

assets = {r["ip_or_host"]: r for r in csv.DictReader(open("assets.csv"))}
allow = [r for r in csv.DictReader(open("allowlist.csv"))]
kinds = {int(r["rule"]): r["kind"] for r in csv.DictReader(open("rule_kinds.csv"))}
# what the alert says happened matters more than the rule's own severity
KIND = {"success": 3, "attempt": 2, "check": 1, "recon": 1, "response": 0}
zeek = {}
for line in open("out/zeek/http.log"):
    h = json.loads(line)
    zeek[(h["id.orig_h"], h["id.orig_p"])] = h

def crit(key):
    return {"high": 1, "medium": 0}.get(assets.get(key, {}).get("criticality"), 0)

queue = []
for line in open("out/suri/eve.json"):
    e = json.loads(line)
    if e["event_type"] != "alert":
        continue
    a = e["alert"]
    to_client = e["src_port"] == 80                       # response rules: the server is the source
    client = (e["dest_ip"], e["dest_port"]) if to_client else (e["src_ip"], e["src_port"])
    server = e["src_ip"] if to_client else e["dest_ip"]
    z = zeek.get(client, {})
    status = z.get("status_code")
    outcome = "response matched" if to_client else ("reached app" if status and status < 400 else f"failed ({status})")
    kind = kinds.get(a["signature_id"], "attempt")
    allowed = any(r["src_ip"] == client[0] and r["rule"] in ("*", str(a["signature_id"])) for r in allow)
    score = KIND[kind] + crit(server) - (1 if outcome.startswith("failed") else 0)
    score = 0 if allowed else score
    queue.append((e["timestamp"][11:19], "suricata", a["signature_id"], a["signature"][:46], client[0],
                  assets.get(server, {}).get("name", server), f"{kind}, {outcome}"[:16], z.get("uid", "-"), score, allowed))

for w in csv.DictReader(open("wazuh_alerts.csv")):
    kind = kinds.get(int(w["rule"]), "check")
    queue.append((w["time"][11:19], "wazuh", int(w["rule"]), w["description"][:46], w["src_ip"] or w["target"][:20],
                  w["agent"], kind, "-", KIND[kind] + crit(w["agent"]), False))

queue.sort(key=lambda q: (-q[8], q[0]))
print(f"{'prio':4} {'time':8} {'source':8} {'rule':>7}  {'description':46} {'who/what':20} {'asset':10} {'outcome':16} zeek uid")
for t, src, rid, desc, who, asset, outcome, uid, score, allowed in queue:
    p = "SUP" if allowed else ("P1" if score >= 4 else "P2" if score == 3 else "P3" if score == 2 else "P4")
    print(f"{p:4} {t:8} {src:8} {rid:>7}  {desc:46} {who:20} {asset:10} {outcome:16} {uid}")
print(f"\n{len(queue)} alerts: " + ", ".join(f"{p} {sum(1 for q in queue if (('SUP' if q[9] else 'P1' if q[8]>=4 else 'P2' if q[8]==3 else 'P3' if q[8]==2 else 'P4')==p))}" for p in ("P1","P2","P3","P4","SUP")))
```

في الكود أعلاه لاحظ التالي:

- قاعدة id تطلق على رد السيرفر، فالمصدر فيها السيرفر `10.250.45.10:80` والوجهة هي العميل، لذلك يعكس السكربت الاتجاه عندما يكون منفذ المصدر 80، وإلا لبحث في Zeek عن اتصال من السيرفر ولم يجد شيئاً. وهذا تفصيل صغير سنرى أثره الكبير في تجربة قائمة السماح.
- الربط بين Suricata وZeek بعنوان العميل ومنفذه المصدر، لأن هذا الزوج يميز الاتصال في نافذة زمنية قصيرة، وفي بيئة حقيقية فيها ملايين الاتصالات أضف الوقت إلى المفتاح، أو استخدم الحقل `community_id` الذي تستطيع الأداتان كتابته لنفس الاتصال.
- السكربت لا يقرر شيئاً، وإنما يرتب، والكلمة `suggested` في وصفه مقصودة.

### المحاولة الأولى: كل شيء أولوية أولى

في النسخة الأولى من السكربت كانت الأولوية من خطورة القاعدة نفسها: الأولوية 1 في Suricata أو المستوى 10 فما فوق في Wazuh تعطي ثلاث نقاط، والأصل الحساس نقطة، والطلب الذي وصل إلى التطبيق نقطة. وآخر سطر في مخرجها كان كما يلي:

```text
16 alerts: P1 12, P2 1, P3 2, P4 1, SUP 0
```

اثنا عشر تنبيهاً في الأولوية الأولى، منها أدوات الفحص الثلاث ومحاولة قراءة `/etc/passwd` التي ردها 404\. والطابور الذي يقول إن كل شيء عاجل لا يقول شيئاً، وهذا هو إرهاق التنبيهات Alert Fatigue في صورته الأولى: لا يأتي من كثرة التنبيهات فقط، وإنما من أن الترتيب لا يفرق بينها. وبعد إضافة ملف تصنيف القواعد وسؤال «ماذا حدث؟» شغلنا النسخة الثانية:

```bash
MSYS_NO_PATHCONV=1 docker run --rm -v "$(pwd -W):/w" -w /w python:3.13.17-slim python triage.py
```

والمخرج سوف يكون كما يلي:

```text
prio time     source      rule  description                                    who/what             asset      outcome          zeek uid
P1   19:36:25 wazuh     100110  New PHP file in the web root: /var/www/html/ca /var/www/html/cache. web01      success          -
P1   19:36:25 wazuh     100111  SSH authorized_keys changed: /root/.ssh/author /root/.ssh/authorize web01      success          -
P1   19:36:32 wazuh     100103  shop-api: omar became admin, changed by sara                        web01      success          -
P1   21:07:23 suricata 2100498  GPL ATTACK_RESPONSE id check returned root     10.250.45.20         shop-web   success, respons CvXdKl30XktK2hrf61
P2   19:34:14 wazuh       5763  sshd: brute force trying to get access to the  192.168.112.6        web01      attempt          -
P2   19:36:30 wazuh     100102  shop-api: 5 failed logins from 203.0.113.50 wi 203.0.113.50         web01      attempt          -
P2   21:07:23 suricata 2022028  ET WEB_SERVER Possible CVE-2014-6271 Attempt   10.250.45.20         shop-web   attempt, reached CWVjc01h64XM7if1g9
P2   21:07:23 suricata 1000001  LAB SQL injection pattern in URI (OR 1=1)      10.250.45.20         shop-web   attempt, reached CXgMQs25aw0KdTCvi3
P3   19:35:11 wazuh        554  File added to the system.                      /var/www/html/up.php web01      check            -
P3   19:35:11 wazuh        550  Integrity checksum changed.                    /var/www/html/index. web01      check            -
P3   19:35:11 wazuh        554  File added to the system.                      /root/.ssh/authorize web01      check            -
P3   21:07:23 suricata 1000004  LAB Scanner user agent (Nikto)                 10.250.45.20         shop-web   recon, reached a CAviiu3k85wvj8qvd3
P3   21:07:23 suricata 1000005  LAB Scanner user agent (Nmap)                  10.250.45.20         shop-web   recon, reached a CLihmB1FNHeNysNudf
P3   21:07:23 suricata 1000003  LAB Scanner user agent (sqlmap)                10.250.45.20         shop-web   recon, reached a CTSDPD28wSmHAKx3Cl
P3   21:07:23 suricata 1000002  LAB Directory traversal attempt (etc/passwd)   10.250.45.20         shop-web   attempt, failed  CMndb9237PcLEx8bj7
P4   19:34:16 wazuh        651  Host Blocked by firewall-drop Active Response  192.168.112.6        web01      response         -

16 alerts: P1 4, P2 4, P3 7, P4 1, SUP 0
```

في المخرج أعلاه لاحظ التالي:

- أربعة في الأولوية الأولى بدلاً من اثني عشر، وكلها تنبيهات تقول إن شيئاً نجح: ملف PHP جديد، ومفتاح SSH جديد، وترقية إلى مدير، ورد يشبه مخرج الأمر id.
- محاولة قراءة `/etc/passwd` نزلت إلى الأولوية الثالثة، لأن Zeek رأى أن ردها 404، أي أنها محاولة فشلت، وهذا هو الإثراء يعمل قبل أن يفتح المحلل أي شيء.
- عمود `zeek uid` هو مفتاح المحلل إلى القصة الكاملة لكل تنبيه من Suricata، كما سنرى في الفرز. وهذه المعرفات تتغير مع كل تشغيل لـ Zeek، فإذا أعدت التجربة فستجد معرفات مختلفة لنفس الاتصالات.
- والأهم مما فعله السكربت ما لم يفعله: تنبيه الملف `up.php` في الأولوية الثالثة، لأن القاعدة العامة 554 تقول «ملف جديد» فقط، مع أنه نفس نوع الملف الذي رفعته القاعدة 100110 إلى الأولوية الأولى بعد دقيقة. وسبب ذلك أن القاعدة المحلية كتبت بعد الملف الأول، كما في مقال Wazuh. وهذا ما سوف تلتقطه ريم بعينها لا بالسكربت.

## الفرز تنبيهاً تنبيهاً: الأولوية الأولى

الآن تبدأ ريم من أعلى الطابور. وقبل أن تقرأ أول تنبيه لاحظت شيئاً في الأوقات لا يظهر إذا قرأت كل تنبيه وحده: كل تنبيهات web01 بين 19:34 و19:37 من نفس اليوم، أي في ثلاث دقائق. والتنبيهات المتقاربة في الوقت على نفس الأصل ليست أربعة أسئلة، وإنما سؤال واحد له أربعة أطراف، لذلك فتحت ملاحظة واحدة لكل ما حدث على web01، وملاحظة أخرى لحركة المتجر في الساعة 21:07.

### ملف PHP جديد ومفتاح SSH جديد على web01

- **افهم:** القاعدة 100110 تطلق عندما يظهر ملف ينتهي بـ `.php` في `/var/www`، وهو الأسلوب T1505.003 Web Shell في [ATT&CK](https://attack.mitre.org/techniques/T1505/003/?ref=arabroot.io)، والقاعدة 100111 عندما يتغير `authorized_keys`، وهو الأسلوب [T1098.004](https://attack.mitre.org/techniques/T1098/004/?ref=arabroot.io)، أي أن أحداً أضاف مفتاحاً يدخل به متى شاء دون كلمة مرور.
- **أثر:** رجعت إلى نفس الجهاز قبل دقيقتين، فوجدت في الأولوية الثالثة تنبيهين 554 لملف `up.php` وللملف `authorized_keys` نفسه في 19:35:11، وتنبيه 550 لتغير الصفحة الرئيسية في الثانية نفسها، وقبلها تخمين كلمات مرور SSH في 19:34:14 من العنوان `192.168.112.6`، وحظر تلقائي لهذا العنوان بعده بثانيتين. وسألت مالك المتجر عن أي نشر أمس، فقال إنه لا يوجد نشر في عطلة نهاية الأسبوع.
- **قرر:** صحيح True Positive، وحادثة Incident. وملفان PHP جديدان، وتغيير في الصفحة الرئيسية، ومفتاحان في `authorized_keys` لحساب root، كلها في ثلاث دقائق دون نشر، ليس لها تفسير سليم.
- **صعد:** إلى المستجيب فوراً بقضية، والتفاصيل في [قسم التصعيد](#escalation).

والسؤال الذي لم تجب عنه ريم، ولا يجب أن تجيب عنه في الفرز، هو كيف وصل من وضع الملفات؟ فتخمين كلمات المرور فشل، والحظر نفذ قبل أن تظهر الملفات بدقيقة، ولا يوجد في الطابور أي تنبيه دخول ناجح. فإما أن الدخول جاء من طريق آخر لا يراه Wazuh، وإما أن هناك فجوة في السجلات، وكلا الاحتمالين للمستجيب. وفي المختبر نعرف الإجابة: نحن من وضع الملفات بالأمر `docker exec` لنحاكي ما يفعله المهاجم بعد الدخول، وهذا طريق لا يمر بـ SSH ولا بأي سجل يقرؤه الوكيل، وهو بالضبط نوع الفجوة التي يجب أن يكتبها المحلل سؤالاً مفتوحاً في ملاحظته بدل أن يملأها بتخمين.

### ترقية omar إلى مدير

- **افهم:** القاعدة 100103 من تطبيق المتجر نفسه، تطلق عندما يصبح مستخدم بصلاحية `admin`، وتذكر من غير الصلاحية، والوصف يقول إن `sara` رقت `omar`.
- **أثر:** قبلها بدقيقتين تنبيه 100102 بخمس محاولات دخول فاشلة إلى التطبيق من العنوان `203.0.113.50`، والسؤال الطبيعي: هل نجحت المحاولة السادسة بحساب sara، ثم رقت عمر؟ والتنبيه لا يقول من أي عنوان جاء تغيير الصلاحية، فلا تستطيع ريم أن تربط الحدثين من الطابور وحده، فاتصلت بسارة.
- **قرر:** إذا قالت سارة إنها لم تفعل ذلك، فهذا صحيح وحادثة، ويلحق بقضية web01 لأنه نفس الأصل ونفس الدقائق. وإذا قالت إنها فعلت بطلب مكتوب من مديرها، فهو صحيح متوقع، ويغلق بالمرجع، ويبقى سؤال: لماذا تملك سارة صلاحية الترقية أصلاً؟ وهذا طلب للمالك لا للمستجيب، وقد شرحنا مراجعة الصلاحيات في [دورة حياة حساب الموظف](https://arabroot.io/articles/%D8%AF%D9%88%D8%B1%D8%A9-%D8%AD%D9%8A%D8%A7%D8%A9-%D8%AD%D8%B3%D8%A7%D8%A8-%D8%A7%D9%84%D9%85%D9%88%D8%B8%D9%81-jml/).

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

### «id check returned root» على المتجر

هذا التنبيه الرابع في الأولوية الأولى، والوحيد فيها من Suricata، وعنوانه أخطر عنوان في الطابور كله. لذلك تبدأ ريم بالإثراء بمعرف Zeek من عمود الطابور، بسكربت صغير يطبع كل ما سجله Zeek لهذا الاتصال في كل السجلات:

```python
"""Shows everything Zeek recorded for one connection uid: python pivot.py <uid>"""
import json, sys
uid = sys.argv[1]
for log in ("conn", "http", "files", "notice"):
    for line in open(f"out/zeek/{log}.log"):
        r = json.loads(line)
        if r.get("uid") == uid or uid in r.get("conn_uids", []):
            keep = {k: r[k] for k in ("id.orig_h", "id.resp_p", "service", "conn_state", "history", "orig_bytes", "resp_bytes",
                                      "method", "uri", "user_agent", "status_code", "resp_mime_types", "response_body_len", "tags",
                                      "mime_type", "seen_bytes", "sha256", "note", "msg") if k in r}
            print(f"{log:6} {json.dumps(keep, ensure_ascii=False)}")
```

```bash
python pivot.py CvXdKl30XktK2hrf61
```

```text
conn   {"id.orig_h": "10.250.45.20", "id.resp_p": 80, "service": "http", "conn_state": "SF", "history": "ShADadFf", "orig_bytes": 80, "resp_bytes": 275}
http   {"id.orig_h": "10.250.45.20", "id.resp_p": 80, "method": "GET", "uri": "/uid/", "user_agent": "curl/7.88.1", "status_code": 200, "resp_mime_types": ["text/plain"], "response_body_len": 39, "tags": []}
files  {"id.orig_h": "10.250.45.20", "id.resp_p": 80, "mime_type": "text/plain", "seen_bytes": 39, "sha256": "5ef391d886d04116cf84b584ae37ef136f83950ab69b7bfb2a6da7506f7b3a57"}
```

في المخرج أعلاه لاحظ التالي:

- الطلب الذي جاء هذا الرد بسببه طلب عادي للمسار `/uid/` بأداة curl، لا يحمل أي أمر ولا أي محاولة حقن، فالرد لم يخرج لأن أحداً نفذ `id` عبر ثغرة، وإنما لأن المسار نفسه يرد بهذا النص.
- الرد ملف نصي من 39 بايتاً فقط بنفس الطول في كل مرة، وبصمته SHA256 ثابتة، فإذا كانت هذه البصمة هي بصمة ملف ثابت في مجلد الموقع فالحكم واضح.
- والتنبيه في `eve.json` فيه `flow_id` يطابق حدث http لنفس الاتصال في Suricata نفسه، فتستطيع أن تصل إلى نفس المعلومة دون Zeek، ولكن Zeek أعطاك معها بصمة الرد.

فسألت ريم مالك المتجر: ما هذا المسار؟ فقال إنه صفحة اختبار تركها مطور قديم، وفيها نص ثابت. والحكم إنذار خاطئ False Positive من حيث النجاح، فلم ينفذ أحد شيئاً، ولكنه يكشف مشكلة حقيقية صغيرة: صفحة اختبار منسية على سيرفر الإنتاج. فالقرار إغلاق التنبيه بسببه، وطلب للمالك بحذف الصفحة، ولا تعطيل للقاعدة، لأنها القاعدة الوحيدة في الطابور التي تكشف نجاحاً على الشبكة، ويوم يخرج نفس النص من سيرفر لا توجد عليه صفحة كهذه فسوف تكون أهم تنبيه في اليوم.

## الأولوية الثانية: محاولات وصلت إلى السيرفر

### حقن SQL رد عليه السيرفر بالرمز 200

في مقال Suricata قلنا إن الحقل `http.status: 200` في تنبيه الحقن «أهم سطر في التنبيه كله»، لأنه يقول إن السيرفر رد بنجاح. والآن نكمل السؤال الذي بقي مفتوحاً هناك: هل نفذ التطبيق الحقن؟ والإثراء بنفس الطريقة:

```text
conn   {"id.orig_h": "10.250.45.20", "id.resp_p": 80, "service": "http", "conn_state": "SF", "history": "ShADadFf", "orig_bytes": 105, "resp_bytes": 258}
http   {"id.orig_h": "10.250.45.20", "id.resp_p": 80, "method": "GET", "uri": "/?id=1'+OR+'1'='1+--+-", "user_agent": "curl/7.88.1", "status_code": 200, "resp_mime_types": ["text/html"], "response_body_len": 22, "tags": ["HTTP::URI_SQLI"]}
files  {"id.orig_h": "10.250.45.20", "id.resp_p": 80, "mime_type": "text/html", "seen_bytes": 22, "sha256": "dca2117c880535c18a079f27f088c6ee4880a4cc9f2a9d1f8df214c1a106c15e"}
```

ثم سألت السؤال الذكي: ما بصمة الصفحة الرئيسية العادية؟ فطبعت أول طلب عادي في `http.log`، وهو طلب `/` بأداة curl دون أي معامل:

```text
http   {"id.orig_h": "10.250.45.20", "id.resp_p": 80, "method": "GET", "uri": "/", "user_agent": "curl/7.88.1", "status_code": 200, "resp_mime_types": ["text/html"], "response_body_len": 22, "tags": []}
files  {"id.orig_h": "10.250.45.20", "id.resp_p": 80, "mime_type": "text/html", "seen_bytes": 22, "sha256": "dca2117c880535c18a079f27f088c6ee4880a4cc9f2a9d1f8df214c1a106c15e"}
```

![أربع لوحات من اليمين: تنبيه Suricata برقم 1000001 من 10.250.45.20:46740 إلى المنفذ 80 وhttp.status 200، ثم اتصال Zeek في conn.log بالمعرف CXgMQs25aw0KdTCvi3 بالحالة SF والتاريخ ShADadFf و105 و258 بايتاً، ثم الطلب في http.log بالرابط الذي فيه OR 1=1 والرد 200 و22 بايتاً والوسم URI_SQLI، ثم الرد في files.log ببصمة dca2117c وهي نفس بصمة الصفحة الرئيسية العادية، وتحتها القرار: الطلب وصل ورد عليه السيرفر بنجاح لكن الرد هو الصفحة الرئيسية نفسها بالبايت أي أن السيرفر تجاهل المعامل، محاولة حقيقية لم تنجح بأولوية P2، ومالك المتجر يعرف ولا قضية استجابة](https://arabroot.io/content/images/2026/10/soc-triage-05-pivot.webp)

البصمة المتطابقة تقول إن الحقن لم يغير شيئاً في الرد

نفس البصمة بالضبط، ونفس الطول 22 بايتاً، أي أن السيرفر رد على طلب الحقن بالصفحة الرئيسية نفسها، وتجاهل المعامل `id` تماماً، وهذا منطقي لأنه nginx يخدم ملفاً ثابتاً. والحكم صحيح True Positive من حيث المحاولة، فأحد ما أرسل حقناً فعلاً، وفاشل من حيث النتيجة. والقرار ملاحظة لمالك المتجر بأن جهازاً داخلياً، أي الحاسوب `10.250.45.20` بحسب ملف الأصول، يرسل طلبات حقن وفحص، وهذا يحتاج سؤالاً: من يعمل عليه؟ ولا قضية للمستجيب ما دام الرد لم يتغير.

ولاحظ أن مقارنة البصمة لا تنفع دائماً، فالتطبيق الحقيقي يولد الصفحة في كل مرة بوقت أو رمز مختلف، فتختلف البصمة حتى لو لم يتغير شيء مهم. وحينها تقارن الطول ورمز الرد ووقت الاستجابة، وتسأل سجلات التطبيق وقاعدة البيانات نفسها، وهذا ما لا تراه أدوات الشبكة، لذلك يحتاج كل فريق سجلات تطبيق جيدة كما في [سجل التدقيق Audit Trail](https://arabroot.io/articles/%D8%B3%D8%AC%D9%84-%D8%A7%D9%84%D8%AA%D8%AF%D9%82%D9%8A%D9%82-audit-trail-%D9%85%D9%86-%D9%81%D8%B9%D9%84-%D9%85%D8%A7%D8%B0%D8%A7-%D9%88%D9%85%D8%AA%D9%89/).

### Shellshock: محاولة يرسلها الجميع

القاعدة 2022028 تطلق على ترويسة فيها نمط ثغرة [CVE-2014-6271](https://nvd.nist.gov/vuln/detail/CVE-2014-6271?ref=arabroot.io) المعروفة باسم Shellshock، والإثراء من Zeek أعطى نفس النتيجة: الطلب للصفحة الرئيسية، والرد 200 بنفس البصمة `dca2117c…`. والثغرة تحتاج على السيرفر سكربت CGI تشغله Bash، كما كتبنا في ملف تصنيف القواعد، والسيرفر nginx بملفات ثابتة. فالحكم محاولة فاشلة، والقرار إغلاق مع ملاحظة، وإذا ظهر نفس التنبيه على سيرفر فيه CGI فسيكون الحكم مختلفاً، ولهذا يحتاج ملف الأصول عموداً عن التقنيات على كل سيرفر.

### تخمين كلمات المرور: SSH والتطبيق

القاعدة 5763 تعد محاولات SSH الفاشلة، وأطلقت بعد ثماني محاولات في 28 ثانية كما في مقال Wazuh، والحظر التلقائي نفذ بعدها بثانيتين، وهو التنبيه 651 في الأولوية الرابعة. والحكم محاولة صحيحة، والسؤال الذي يغير كل شيء: هل نجح أي دخول من هذا العنوان قبل الحظر أو بعده؟ ولم تجد ريم في الطابور أي تنبيه دخول ناجح، ولكن غياب التنبيه ليس دليلاً، فبحثت في الفهرس عن نجاح الدخول من هذا العنوان، ولم تجد. ولأن هذا العنوان داخل الشبكة، أي `192.168.112.6`، وهو في ملف الأصول «جهاز غير معروف»، فقد أضافته إلى قضية web01 بدل أن تغلقه، فجهاز غير معروف يخمن كلمات المرور على سيرفر المتجر قبل ظهور ملفات غريبة عليه بدقيقة، جزء من القصة حتى لو لم نعرف كيف بعد.

وأما 100102 فخمس محاولات دخول فاشلة إلى التطبيق من `203.0.113.50` خلال دقيقة، وهو عنوان من نطاق التوثيق في المختبر، وفي الواقع سيكون عنواناً على الإنترنت تبحث عنه في مصادر استخبارات التهديدات وتاريخ تنبيهاتك. وقد ربطته ريم بتنبيه الترقية إلى مدير في الأولوية الأولى، لأن الحساب نفسه سارة.

## الأولوية الثالثة والرابعة: ما يغلق بسبب

في الأولوية الثالثة سبعة تنبيهات، ومن السهل أن يغلقها المحلل المتعب دفعة واحدة، وهنا كانت أهم لحظة في صباح ريم:

- **554 للملف `up.php`:** «ملف جديد» بالمستوى 5 فقط، ولكن المسار في مجلد الموقع والامتداد PHP، وهو نفس ما رفعته القاعدة 100110 إلى المستوى 12 بعد دقيقة. فلو أغلقته ريم لأنه في P3، لكانت القضية فيها ملف Web Shell واحد بدل اثنين، والمستجيب سيحذف `cache.php` ويترك `up.php`. لذلك نقلته إلى قضية web01، وكتبت طلباً للضبط: القاعدة 100110 يجب أن تغطي كل ملف PHP جديد في مجلد الموقع، وهي تغطيه الآن، ولكن الملف الذي ظهر قبل كتابتها يحتاج مراجعة يدوية.
- **554 للملف `authorized_keys` و550 للصفحة الرئيسية:** نفس الدقيقة ونفس الجهاز، والفرق في الصفحة الرئيسية ظاهر في الحقل `diff` للتنبيه، فقد تغير العنوان إلى «Hacked by lab»، وهذا تشويه موقع Defacement، فنقلتهما إلى القضية.
- **أدوات الفحص الثلاث Nmap وsqlmap وNikto:** استطلاع من الحاسوب `10.250.45.20` نفسه الذي أرسل الحقن وShellshock، في نفس الثانية تقريباً، فهي قصة واحدة: جهاز داخلي يفحص سيرفر المتجر. والحكم صحيح، والقرار سؤال مكتوب لقسم تقنية المعلومات عن هذا الجهاز ومن يعمل عليه، وإذا كان فحصاً مصرحاً به من شركة الاختبار فهو صحيح متوقع.
- **محاولة قراءة `/etc/passwd`:** ردها 404 وطولها 153 بايتاً، أي صفحة الخطأ العادية، فهي محاولة فاشلة من نفس الجهاز، وتضاف إلى نفس السؤال.
- **651 الحظر التلقائي في الأولوية الرابعة:** ليس هجوماً، وإنما دليل على أن أنظمتنا تصرفت، فيضاف إلى القضية كإجراء تم، وتكتب مدته: 181 ثانية ثم رفع الحظر تلقائياً.

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

## ماذا لو أضفنا الجهاز إلى قائمة السماح Allowlist؟

بعد ظهر الأحد رد قسم تقنية المعلومات: الحاسوب `10.250.45.20` هو جهاز فحص الثغرات الذي اتفقت الشركة عليه، ويفحص المتجر كل ليلة بتذكرة مكتوبة. فطلب أحد الزملاء أن «نسكت هذا الجهاز» حتى لا تظهر تنبيهاته كل صباح. وهنا جربت ريم طريقتين قبل أن تقرر، والصورة التالية تلخص النتيجة:

![لوحتان: في اليمين قائمة ضيقة بالأخضر فيها المصدر 10.250.45.20 مع القواعد 1000003 و1000004 و1000005 بالرقم، أسكتت 3 تنبيهات وبقي الحقن SQL من نفس المصدر في P2 وتنبيه نجاح الأمر id في P1، ولكل سطر سبب ومن وافق وتاريخ انتهاء، وفي اليسار قائمة واسعة بالأحمر فيها المصدر نفسه مع كل القواعد بعلامة النجمة، أسكتت 7 تنبيهات ومعها تنبيه id check returned root فنزلت P1 من 4 إلى 3، لأن قاعدة الرد ترى السيرفر مصدراً والعميل وجهة والسكربت يسكت بعنوان العميل](https://arabroot.io/content/images/2026/10/soc-triage-06-allowlist.webp)

سطر واحد بنجمة أخفى التنبيه الوحيد الذي يكشف نجاحاً على الشبكة

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

```text
src_ip,rule,reason,approved_by,expires
10.250.45.20,1000003,nightly authorised scan (ticket SEC-114),noura,2026-12-31
10.250.45.20,1000004,nightly authorised scan (ticket SEC-114),noura,2026-12-31
10.250.45.20,1000005,nightly authorised scan (ticket SEC-114),noura,2026-12-31
```

```text
P2   21:07:23 suricata 1000001  LAB SQL injection pattern in URI (OR 1=1)      10.250.45.20         shop-web   attempt, reached CXgMQs25aw0KdTCvi3
SUP  21:07:23 suricata 1000004  LAB Scanner user agent (Nikto)                 10.250.45.20         shop-web   recon, reached a CAviiu3k85wvj8qvd3
SUP  21:07:23 suricata 1000005  LAB Scanner user agent (Nmap)                  10.250.45.20         shop-web   recon, reached a CLihmB1FNHeNysNudf
SUP  21:07:23 suricata 1000003  LAB Scanner user agent (sqlmap)                10.250.45.20         shop-web   recon, reached a CTSDPD28wSmHAKx3Cl
16 alerts: P1 4, P2 4, P3 4, P4 1, SUP 3
```

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

```text
src_ip,rule,reason,approved_by,expires
10.250.45.20,*,scanner host (too wide on purpose),noura,2026-12-31
```

```text
P1   19:36:25 wazuh     100110  New PHP file in the web root: /var/www/html/ca /var/www/html/cache. web01      success          -
P1   19:36:25 wazuh     100111  SSH authorized_keys changed: /root/.ssh/author /root/.ssh/authorize web01      success          -
P1   19:36:32 wazuh     100103  shop-api: omar became admin, changed by sara                        web01      success          -
16 alerts: P1 3, P2 2, P3 3, P4 1, SUP 7
```

سبعة تنبيهات أسكتت، ومنها تنبيه «id check returned root»، فنزلت الأولوية الأولى من أربعة إلى ثلاثة. والسبب تفصيل رأيناه في كود السكربت: قاعدة الرد تطلق على حزمة من السيرفر إلى العميل، والسكربت يحدد العميل ويطبق عليه قائمة السماح، فالإسكات الواسع لعنوان جهاز الفحص أسكت أيضاً ردود السيرفر عليه. وفي هذا المختبر كان التنبيه إنذاراً خاطئاً، لكن تخيل اليوم الذي يجد فيه جهاز الفحص ثغرة حقيقية فينفذ `id` فعلاً ويرد السيرفر بأنه root: سيكون هذا أهم تنبيه في السنة، وسيكون مسكتاً بسطر واحد كتبه أحد ليوقف الإزعاج.

والقاعدة العملية من هذه التجربة: أسكت بالمصدر والقاعدة معاً، لا بالمصدر وحده، ولا تضع النجمة في قائمة السماح أبداً، واجعل لكل سطر تاريخ انتهاء، وراجع القائمة كل ثلاثة أشهر كما قلنا عن ملف العتبات في [مقال Suricata](https://arabroot.io/articles/%D8%A7%D9%83%D8%AA%D8%B4%D8%A7%D9%81-%D8%A7%D9%84%D8%AA%D8%B3%D9%84%D9%84-%D9%81%D9%8A-%D8%A7%D9%84%D8%B4%D8%A8%D9%83%D8%A9-ids-%D9%85%D8%B9-suricata-%D9%88-zeek/). وفي Suricata نفسه يكون الإسكات الضيق بالسطر `suppress gen_id 1, sig_id 1000004, track by_src, ip 10.250.45.20` في [ملف العتبات العامة](https://docs.suricata.io/en/latest/configuration/global-thresholds.html?ref=arabroot.io)، أي بالقاعدة والمصدر معاً.

## ملاحظة الفرز Triage Note: كيف تكتبها؟

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

```text
alert      : suricata 1000001 "LAB SQL injection pattern in URI (OR 1=1)", 2026-10-25 21:07:23 UTC
asset      : shop-web 10.250.45.10 (high, ecommerce team)
source     : 10.250.45.20 lab-client (medium, it support)
what I saw : GET /?id=1'+OR+'1'='1+--+- , status 200, 22 bytes (zeek uid CXgMQs25aw0KdTCvi3, tag HTTP::URI_SQLI)
enrichment : response sha256 dca2117c... is the same as the normal home page (GET /), so the parameter was ignored;
             same source sent Shellshock, traversal (404) and three scanner user agents within the same second
verdict    : true positive (attempt), not successful
priority   : P2 -> closed for SOC, question to IT about 10.250.45.20 (who runs it, is it authorised?)
open       : none for this alert; source question tracked in ticket SEC-114
by / when  : reem, 2026-10-26 08:40 UTC
```

وفي الملاحظة أعلاه لاحظ التالي:

- السطر `what I saw` حقائق فقط، والسطر `enrichment` ما أضفته من خارج التنبيه ومن أين، والفصل بينهما يجعل من يقرأ بعدك يعرف ما الذي يستطيع أن يتحقق منه بنفسه.
- الحكم مكتوب بكلمتين: صحيح من حيث المحاولة، وغير ناجح، وهذا أدق من «False Positive» الذي يكتبه كثيرون لكل ما لم ينجح.
- السطر `open` يجبرك أن تكتب ما لم تعرفه، وهو في تنبيهات web01 أطول سطر في الملاحظة: كيف وصلت الملفات إلى السيرفر دون دخول ناجح ظاهر؟
- كتبت ريم الملاحظة بالإنجليزية لأن أداة الحالات وفريق المورد يقرؤونها، ولا مشكلة في أن تكتبها بالعربية إذا كان فريقك عربياً بالكامل، والمهم أن تكون الحقول نفسها في كل ملاحظة.

## التصعيد Escalation: ماذا يذهب إلى المستجيب؟

بعد القرار يذهب كل تنبيه إلى واحد من ثلاثة أماكن، والصورة التالية تبينها مع أمثلة من طابور ريم:

![ثلاث لوحات: إغلاق مع ملاحظة للإنذار الخاطئ أو المتوقع مثل id check على الصفحة الثابتة والفحص المصرح به، وطلب لمالك النظام لمحاولة لم تنجح لكنها تكشف ضعفاً مثل حقن SQL رده الصفحة الرئيسية وتغيير صلاحية omar حتى يؤكد المالك، وقضية للمستجيب لنجاح أو احتمال نجاح على أصل حساس مثل ملف PHP جديد ومفتاح SSH جديد لحساب root على web01 بعد تخمين كلمات المرور، وتحتها ما يذهب مع التصعيد: التنبيهات بأرقامها وأوقاتها والمصدر والأصل وما تحققت منه وما لم تتحقق منه وما فعلته حتى الآن والسؤال المفتوح](https://arabroot.io/content/images/2026/10/soc-triage-07-escalation.webp)

التصعيد الجيد يوفر على المستجيب ساعة، والسيئ يجعله يعيد الفرز من البداية

والقضية التي فتحتها ريم للمستجيب في منصة الحالات، مثل TheHive التي جربناها في [مقال TheHive](https://arabroot.io/articles/%D8%A7%D9%84%D8%A7%D8%B3%D8%AA%D8%AC%D8%A7%D8%A8%D8%A9-%D9%84%D9%84%D8%AD%D9%88%D8%A7%D8%AF%D8%AB-incident-response-%D9%85%D8%B9-thehive/)، فيها تنبيهات Wazuh التسعة من web01 مرتبة بالوقت، ومعها ثلاثة أشياء لا تقل أهمية عن التنبيهات:

- **ما فعلته حتى الآن:** لا شيء على السيرفر نفسه، فلم تعد تشغيله، ولم تحذف الملفات، ولم تغير كلمة مرور، والسبب أن هذه قرارات المستجيب، وكل واحد منها قد يمحو دليلاً كما شرحنا في [التحقيق الرقمي للمبتدئين](https://arabroot.io/articles/%D8%A7%D9%84%D8%AA%D8%AD%D9%82%D9%8A%D9%82-%D8%A7%D9%84%D8%B1%D9%82%D9%85%D9%8A-%D9%84%D9%84%D9%85%D8%A8%D8%AA%D8%AF%D8%A6%D9%8A%D9%86-dfir/). والإجراء الوحيد الذي حدث هو الحظر التلقائي لعنوان التخمين، وقد انتهى بعد 181 ثانية.
- **ما تحققت منه وما لم تتحقق منه:** لا نشر يوم السبت بحسب المالك، ولا دخول SSH ناجح من العنوان المحظور في الفهرس، ولم تتحقق من سجلات الوصول إلى nginx لملفي PHP لأن الوكيل لا يقرؤها.
- **السؤال المفتوح:** كيف وصلت الملفات إلى السيرفر؟ وهل استخدم أحد `up.php` أو `cache.php` بعد رفعهما؟

ومن هنا يبدأ عمل آخر له خطته وكتيباته، أي ما يفعله المستجيب في الساعة الأولى، ومن يبلغ، ومتى يعزل السيرفر، وهذا موضوع المقال التالي في المسار عن خطة الاستجابة وكتيبات التشغيل، ثم مقال [فحص سيرفر Linux مخترق](https://arabroot.io/articles/%D9%81%D8%AD%D8%B5-%D8%B3%D9%8A%D8%B1%D9%81%D8%B1-linux-%D9%85%D8%AE%D8%AA%D8%B1%D9%82-%D8%AF%D9%88%D9%86-%D8%A7%D9%86-%D8%AA%D9%81%D8%B3%D8%AF-%D8%A7%D9%84%D8%A7%D8%AF%D9%84%D8%A9/).

[![](https://arabroot.io/content/images/2026/10/ir-playbooks-cover-cover.webp)دليلخطة الاستجابة للحوادث Incident Response وكتيبات التشغيل Playbooksخطة استجابة وكتيبا حساب مخترق وفدية على NIST SP 800-61r3، مع مختبر نستعيد فيه البيانات من نسخة restic.](https://arabroot.io/articles/%D8%AE%D8%B7%D8%A9-%D8%A7%D9%84%D8%A7%D8%B3%D8%AA%D8%AC%D8%A7%D8%A8%D8%A9-%D9%84%D9%84%D8%AD%D9%88%D8%A7%D8%AF%D8%AB-incident-response-%D9%88%D9%83%D8%AA%D9%8A%D8%A8%D8%A7%D8%AA-%D8%A7%D9%84%D8%AA%D8%B4%D8%BA%D9%8A%D9%84/)[![](https://arabroot.io/content/images/2026/10/thehive-lab-cover-cover.webp)دليلالاستجابة للحوادث Incident Response مع TheHiveحولنا تنبيهاً عن دخول مريب إلى حساب FTP إلى قضية في TheHive بمهام ومؤشرات وأسلوب ATT&CK، وقسنا ما تسمح به الرخصة فعلاً.](https://arabroot.io/articles/%D8%A7%D9%84%D8%A7%D8%B3%D8%AA%D8%AC%D8%A7%D8%A8%D8%A9-%D9%84%D9%84%D8%AD%D9%88%D8%A7%D8%AF%D8%AB-incident-response-%D9%85%D8%B9-thehive/)[![](https://arabroot.io/content/images/2026/10/compromised-linux-cover-cover.webp)دليلفحص سيرفر Linux مخترق دون أن تفسد الأدلةفحصنا سيرفراً مخترقاً في المختبر خطوة خطوة بالطريقة الصحيحة، فوجدنا برنامجاً من ملف محذوف وأمر ls مزروعاً ووقتاً مزوراً، دون أن نفسد دليلاً.](https://arabroot.io/articles/%D9%81%D8%AD%D8%B5-%D8%B3%D9%8A%D8%B1%D9%81%D8%B1-linux-%D9%85%D8%AE%D8%AA%D8%B1%D9%82-%D8%AF%D9%88%D9%86-%D8%A7%D9%86-%D8%AA%D9%81%D8%B3%D8%AF-%D8%A7%D9%84%D8%A7%D8%AF%D9%84%D8%A9/)

## ماذا تقيس بعد شهر؟

بعد شهر من هذا العمل سألت نورة، مديرة القسم، سؤالاً بسيطاً: هل نتحسن؟ والإجابة تحتاج أرقاماً تجمع من ملاحظات الفرز نفسها، وهذا سبب إضافي لأن تكون حقول الملاحظة ثابتة:

- **الوقت من التنبيه إلى القرار:** لكل أولوية على حدة، فالمتوسط العام يخفي أن تنبيهات P1 تنتظر ساعتين في عطلة نهاية الأسبوع.
- **نسبة الإنذارات الخاطئة لكل قاعدة:** لا للطابور كله، فقاعدة واحدة بنسبة عالية تستحق ضبطاً، وعشر قواعد بنسب منخفضة لا تستحق.
- **التنبيهات التي غير المحلل أولويتها:** مثل `up.php` الذي رفعته ريم من P3 إلى قضية، وكل واحد منها اقتراح لتحسين ملف التصنيف أو القواعد.
- **عدد أسطر قائمة السماح المنتهية:** كل سطر انتهى تاريخه ولم يراجع إسكات بلا مالك.
- **الحوادث التي لم تبدأ بتنبيه:** أي الفائتة False Negatives التي عرفت بها من مكان آخر، وكل واحدة منها قاعدة يجب أن تكتب.

ولاحظ أن عدد التنبيهات المغلقة في اليوم ليس في القائمة عن قصد، فالمحلل الذي يقاس بعدد ما يغلق سيتعلم أن يغلق بسرعة، وهذا عكس ما يريده أي فريق.

## الضبط Tuning: من ملاحظة الفرز إلى القاعدة

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

- **رفع ما يجب أن يرتفع:** مثل أي ملف PHP جديد في مجلد الموقع، وقد كتبنا قاعدته 100110 في مقال Wazuh.
- **إسكات الصحيح المتوقع بضيق:** المصدر والقاعدة معاً، مع السبب والموافق وتاريخ الانتهاء.
- **تعديل القاعدة الواسعة لا تعطيلها:** مثل قاعدة محلية تطلق على كل رابط فيه كلمة OR، فتضيقها بنمط أدق وتزيد `rev`.
- **تحديث ملف الأصول وتصنيف القواعد:** فصفحة الاختبار المنسية على المتجر يجب أن تحذف، وإذا لم تحذف فتكتب في ملف الأصول.
- **اختبار كل تعديل على ملف حركة محفوظ:** كما فعلنا في هذا المقال، فتعرف أن التعديل لم يخف شيئاً كان ظاهراً.

وقد شرحنا كيف يعمل التجميع والعتبات داخل محرك الكشف نفسه في [محرك كشف SIEM من الداخل](https://arabroot.io/articles/%D9%83%D9%8A%D9%81-%D9%8A%D8%B9%D9%85%D9%84-%D9%85%D8%AD%D8%B1%D9%83-%D9%83%D8%B4%D9%81-siem-%D9%85%D9%86-%D8%A7%D9%84%D8%AF%D8%A7%D8%AE%D9%84/)، والقرارات الأربعة للضبط في مقال Suricata وZeek.

### حذف المختبر Cleanup

```bash
docker volume rm sci-soc-suricata-lib
docker image rm jasonish/suricata:8.0.7 zeek/zeek:9.0.0
rm -rf out
```

## أخطاء شائعة

- **القراءة بترتيب الوصول:** فتقضي وقتك في أقدم تنبيه وأقلها أهمية، والصحيح أن ترتب بالأولوية ثم تعمل من الأعلى.
- **الحكم من عنوان القاعدة:** «id check returned root» يبدو كارثة، وكان صفحة اختبار ثابتة، و«File added» يبدو عادياً، وكان Web Shell.
- **الأولوية من خطورة القاعدة وحدها:** فيصبح كل شيء أولوية أولى، كما رأينا في المحاولة الأولى: اثنا عشر من ستة عشر.
- **كتابة False Positive لكل ما لم ينجح:** المحاولة الفاشلة تنبيه صحيح، وإغلاقها كخاطئ يفسد أرقام الضبط ويخفي أن أحداً يحاول.
- **تعطيل القاعدة بدل إسكات المصدر:** فيمر الفحص غير المصرح به يوماً ما دون أن يراه أحد.
- **قائمة سماح بنجمة:** رأينا كيف أخفى سطر واحد التنبيه الوحيد الذي يكشف نجاحاً على الشبكة.
- **اعتبار غياب التنبيه دليلاً:** لا يوجد تنبيه دخول ناجح لا يعني أن أحداً لم يدخل، فابحث في الفهرس وفي السجلات.
- **إصلاح السيرفر أثناء الفرز:** حذف الملف المشبوه أو إعادة التشغيل قبل أن يصل المستجيب يمحو الأدلة.
- **ملاحظة بلا سطر «مفتوح»:** ما لم تعرفه أهم لمن بعدك مما عرفته.

## قائمة تحقق لكل تنبيه

| الخطوة       | السؤال                                                        | من أين الجواب؟                                                           |
| ------------ | ------------------------------------------------------------- | ------------------------------------------------------------------------ |
| قبل الطابور  | ما الذي بقي مفتوحاً وما الذي تغير في البيئة والقواعد؟         | ملاحظة التسليم، وسجل التغييرات، وسجل suricata-update                     |
| افهم         | ماذا تبحث عنه القاعدة؟ طلب أم رد؟ محاولة أم نجاح؟             | نص القاعدة وبياناتها confidence وsignature\_severity، وملف تصنيف القواعد |
| أثر: الأصل   | ما هذا السيرفر ومن يملكه وما أهميته؟                          | ملف الأصول                                                               |
| أثر: النتيجة | ماذا رد السيرفر وكم بايتاً، وهل الرد مختلف عن العادي؟         | http.status في التنبيه، وhttp.log وfiles.log في Zeek                     |
| أثر: السياق  | ماذا حدث على نفس الأصل ومن نفس المصدر قبل وبعد؟               | الطابور مرتباً بالوقت، والفهرس، وconn.log                                |
| أثر: الإنسان | هل يعرف المالك أو صاحب الحساب شيئاً؟                          | مكالمة قصيرة، مكتوبة في الملاحظة                                         |
| قرر          | صحيح أم خاطئ أم صحيح متوقع؟ وما الأولوية؟                     | كل ما سبق، مكتوباً بسبب                                                  |
| صعد          | إغلاق، أم طلب للمالك، أم قضية للمستجيب؟                       | النجاح أو احتماله على أصل حساس يعني قضية                                 |
| وثق          | هل يفهم غيرك القرار بعد شهر؟ ما الذي بقي مفتوحاً؟             | ملاحظة الفرز بحقولها الثابتة                                             |
| اضبط         | هل يحتاج هذا التنبيه تعديلاً في القاعدة أو الإسكات أو الأصول؟ | طلب ضبط يراجعه زميل ويختبر على ملف حركة                                  |

## الخلاصة

- فرز التنبيهات خمس خطوات ثابتة لكل تنبيه: افهم، أثر، قرر، صعد، وثق، وأغلب الوقت في الإثراء.
- رتب الطابور بالأولوية لا بالوقت، والأولوية من ماذا تقول القاعدة إنه حدث، ثم أهمية الأصل، ثم ماذا رد السيرفر، لا من خطورة القاعدة وحدها التي جعلت اثني عشر تنبيهاً من ستة عشر أولوية أولى.
- Zeek هو أداة الإثراء الأهم لتنبيهات الشبكة: رمز الرد وطوله وبصمته، فبصمة رد الحقن كانت بصمة الصفحة الرئيسية نفسها، أي أن الحقن لم يغير شيئاً.
- الأحكام خمسة لا أربعة، والصحيح المتوقع يسكت بالمصدر والقاعدة معاً بتاريخ انتهاء، ولا يعطل.
- قائمة السماح الواسعة أخفت في التجربة تنبيه النجاح الوحيد على الشبكة، فلا نجمة في قوائم السماح.
- التنبيهات المتقاربة على نفس الأصل قصة واحدة، والتنبيه في الأولوية الثالثة قد يكون جزءاً من حادثة في الأولى، مثل `up.php`.
- التصعيد الجيد يحمل ما رأيته وما فعلته وما لم تعرفه، ولا يصلح السيرفر قبل المستجيب.

وأقرب المقالات إلى هذا الموضوع في المسار:

[![](https://arabroot.io/content/images/2026/10/ir-playbooks-cover-cover.webp)دليلخطة الاستجابة للحوادث Incident Response وكتيبات التشغيل Playbooksخطة استجابة وكتيبا حساب مخترق وفدية على NIST SP 800-61r3، مع مختبر نستعيد فيه البيانات من نسخة restic.](https://arabroot.io/articles/%D8%AE%D8%B7%D8%A9-%D8%A7%D9%84%D8%A7%D8%B3%D8%AA%D8%AC%D8%A7%D8%A8%D8%A9-%D9%84%D9%84%D8%AD%D9%88%D8%A7%D8%AF%D8%AB-incident-response-%D9%88%D9%83%D8%AA%D9%8A%D8%A8%D8%A7%D8%AA-%D8%A7%D9%84%D8%AA%D8%B4%D8%BA%D9%8A%D9%84/)[![](https://arabroot.io/content/images/2026/10/wazuh-lab-cover-cover.webp)دليلمراقبة السيرفرات مع Wazuh: من السجل Log إلى حظر المهاجمشغلنا Wazuh مع وكيل على سيرفر تجريبي، فكشف تخمين كلمات مرور SSH وحظر المهاجم تلقائياً، ونبه على ملف PHP دخيل خلال ثانية.](https://arabroot.io/articles/%D9%85%D8%B1%D8%A7%D9%82%D8%A8%D8%A9-%D8%A7%D9%84%D8%B3%D9%8A%D8%B1%D9%81%D8%B1%D8%A7%D8%AA-%D9%85%D8%B9-wazuh-%D9%85%D9%86-%D8%A7%D9%84%D8%B3%D8%AC%D9%84-%D8%A7%D9%84%D9%89-%D8%AD%D8%B8%D8%B1-%D8%A7%D9%84%D9%85%D9%87%D8%A7%D8%AC%D9%85/)[![](https://arabroot.io/content/images/2026/10/suricata-zeek-cover-cover.webp)دليلمراقبة الشبكة واكتشاف التسلل IDS مع Suricata وZeekمختبر حقيقي يقرأ الحركة نفسها بأداتين، فيكشف Suricata الهجمات المعروفة ويكتب Zeek سجلاً لكل اتصال، مع الضبط وفقد الحزم.](https://arabroot.io/articles/%D8%A7%D9%83%D8%AA%D8%B4%D8%A7%D9%81-%D8%A7%D9%84%D8%AA%D8%B3%D9%84%D9%84-%D9%81%D9%8A-%D8%A7%D9%84%D8%B4%D8%A8%D9%83%D8%A9-ids-%D9%85%D8%B9-suricata-%D9%88-zeek/)[![](https://arabroot.io/content/images/2026/10/thehive-lab-cover-cover.webp)دليلالاستجابة للحوادث Incident Response مع TheHiveحولنا تنبيهاً عن دخول مريب إلى حساب FTP إلى قضية في TheHive بمهام ومؤشرات وأسلوب ATT&CK، وقسنا ما تسمح به الرخصة فعلاً.](https://arabroot.io/articles/%D8%A7%D9%84%D8%A7%D8%B3%D8%AA%D8%AC%D8%A7%D8%A8%D8%A9-%D9%84%D9%84%D8%AD%D9%88%D8%A7%D8%AF%D8%AB-incident-response-%D9%85%D8%B9-thehive/)[![](https://arabroot.io/content/images/2026/10/build-siem-cover-cover.webp)دليلكيف يعمل محرك كشف SIEM من الداخل؟كيف يجمع SIEM ملايين السجلات ويوحدها ويطبق قواعد الكشف، مع خط أنابيب Vector وLoki وقاعدة Sigma تطلق فعلاً.](https://arabroot.io/articles/%D9%83%D9%8A%D9%81-%D9%8A%D8%B9%D9%85%D9%84-%D9%85%D8%AD%D8%B1%D9%83-%D9%83%D8%B4%D9%81-siem-%D9%85%D9%86-%D8%A7%D9%84%D8%AF%D8%A7%D8%AE%D9%84/)[![](https://arabroot.io/content/images/2026/10/security-careers-cover-cover.webp)دليلأدوار الأمن السيبراني Careers: ماذا يعمل كل دور، ومن أين تبدأ؟تسعة أدوار في الأمن السيبراني من المراجع الرسمية: اليوم العادي والمهارات والأدوات، ومن أي مستوى يبدأ كل دور.](https://arabroot.io/articles/%D8%A7%D8%AF%D9%88%D8%A7%D8%B1-%D8%A7%D9%84%D8%A7%D9%85%D9%86-%D8%A7%D9%84%D8%B3%D9%8A%D8%A8%D8%B1%D8%A7%D9%86%D9%8A-%D9%85%D9%86-%D9%85%D8%AD%D9%84%D9%84-soc-%D8%A7%D9%84%D9%89-grc/)

## سجل التحديثات

- أكتوبر 2026: كتابة المقال، وإعادة ملف حركة مختبر Suricata وZeek يوم 26 أكتوبر 2026 على Suricata 8.0.7 مع ET Open (69,237 قاعدة منها 53,269 مفعلة) وZeek 9.0.0، وتنبيهات Wazuh 4.14.9 من مختبر 25 أكتوبر 2026، وسكربت الفرز على Python 3.13.17.