> ## 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.

# نمذجة التهديدات Threat Modeling للمبتدئين
- URL: https://arabroot.io/articles/نمذجة-التهديدات-threat-modeling-للمبتدئين/
- Published: 2026-10-05T21:00:00.000Z
- Updated: 2026-10-09T09:42:58.000Z
- Description: كيف تسأل ما الذي قد يسوء في تصميم تطبيقك قبل أن تكتب الكود، وتقرر لكل تهديد هل تصلحه أو تقبله، مع قالب جاهز للنسخ.
- Author: فريق عرب رووت
- Tags: الأدلة التقنية, DevOps والتشغيل, DevOps وCI/CD, الاستضافة الذاتية

لنفرض أن فريقك أنهى تطبيقاً للفواتير يعمل بنظام SaaS، وقبل الإطلاق بأسبوع طلب المدير اختبار اختراق Penetration Test، فجاء التقرير بثلاث ملاحظات من النوع الذي يصلح في يوم واحد، وملاحظة رابعة تقول إن أي عميل يستطيع أن يقرأ فواتير عميل آخر بتغيير رقم في الرابط، لأن التطبيق لم يصمم أصلاً على فصل بيانات المستأجرين Tenants. هذه الملاحظة لا تصلح بسطر واحد، فهي تعني تعديل كل استعلام وإضافة عمود إلى الجداول ونقل البيانات القديمة وإعادة الاختبار، والإطلاق بعد أسبوع. والسبب أن السؤال «ما الذي قد يسوء؟» طرح في آخر يوم، على نظام جاهز، بدلاً من أن يطرح في أول يوم على ورقة فيها رسم بسيط للتصميم.

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

- لماذا لا يكفي اختبار الاختراق وفحص الثغرات في آخر المشروع، وما الذي تجده نمذجة التهديدات ولا تجده الأدوات.
- الأسئلة الأربعة لآدم شوستاك Adam Shostack وبيان نمذجة التهديدات Threat Modeling Manifesto.
- الخطوة الأولى: رسم مخطط تدفق البيانات Data Flow Diagram لتطبيق فواتير حقيقي الشكل، مع حدود الثقة Trust Boundaries.
- الخطوة الثانية: البحث عن التهديدات بأسئلة STRIDE الستة، وجدول STRIDE لكل عنصر، ومتى تحتاج LINDDUN أو PASTA أو شجرة الهجوم Attack Tree.
- الخطوة الثالثة: ترتيب المخاطر واتخاذ قرار لكل تهديد، وتحويله إلى تذكرة واختبار.
- الخطوة الرابعة: المراجعة، وكيف يبقى النموذج حياً مع الكود في كل طلب دمج Pull Request.
- الأدوات مفتوحة المصدر وتراخيصها: OWASP Threat Dragon وOWASP pytm وThreagile، وأداة Microsoft المجانية، وألعاب البطاقات.
- تجربة عملية: نصف التطبيق بالكود مع pytm، ونولد المخطط وقائمة التهديدات الحقيقية، ثم نفرز النتائج ونسجل القرارات.
- قالب جاهز للنسخ مع مثال مكتمل من عشرة تهديدات، ثم الأخطاء الشائعة وقائمة تحقق.

## الثغرة التي لا يصلحها كود أفضل: لماذا نبحث عن المشاكل في التصميم Design؟

أغلب ما نعرفه من أدوات الأمان يعمل على شيء موجود: أداة تحليل الكود الثابت Static Analysis واختصاراً SAST تقرأ الكود الذي كتبته، وأداة فحص التطبيق أثناء التشغيل Dynamic Analysis واختصاراً DAST تهاجم التطبيق وهو يعمل، واختبار الاختراق يحاول أن يكسر النظام الحقيقي. وكلها مفيدة، ولكنها تجد في الغالب أخطاء في التنفيذ Implementation Bugs، أي ضابطاً Control موجوداً كتب بشكل خاطئ. أما الضابط الذي لم يفكر فيه أحد أصلاً، مثل فصل بيانات المستأجرين أو سجل التدقيق Audit Log أو حد لحجم التصدير، فلا يوجد له كود لتقرأه الأداة، وهنا يأتي دور نمذجة التهديدات.

وهذا التمييز ليس رأياً، فقائمة OWASP Top 10 لعام 2025 تضع التصميم غير الآمن Insecure Design فئة مستقلة في المرتبة السادسة، وتقول صفحة [A06:2025](https://top10.owasp.org/2025/A06%5F2025-Insecure%5FDesign?ref=arabroot.io) بالنص: «An insecure design cannot be fixed by a perfect implementation as needed security controls were never created to defend against specific attacks»، أي أن التصميم غير الآمن لا يصلحه تنفيذ مثالي، لأن الضوابط المطلوبة لم تصمم أصلاً. ومن توصيات الصفحة نفسها أن تدمج نمذجة التهديدات في جلسات تجهيز المهام Refinement، وأن تستخدم للأجزاء الحساسة مثل المصادقة والتحكم بالوصول ومنطق العمل.

### الحلول الأولى التي تخطر على البال، ولماذا لا تكفي

عندما يقرر فريق صغير أن «يهتم بالأمان»، فإنه يبدأ عادة بأحد الحلول التالية، وكل واحد منها له مكانه ولكنه لا يجيب عن سؤال التصميم:

1. **اختبار اختراق قبل الإطلاق:** المختبر يأتي متأخراً ولوقت محدود، فيجد ما يستطيع الوصول إليه في أيام قليلة، وإذا وجد مشكلة في التصميم فقد جاءت في أغلى توقيت ممكن، كما في مثال الفواتير في بداية المقال.
2. **أداة فحص تعمل في خط CI:** أداة SAST أو DAST تجد حقن SQL Injection أو ترويسة Header ناقصة، ولكنها لا تعرف أن لوحة الإدارة يجب ألا تكون على الإنترنت، ولا أن العميل يجب ألا يرى فواتير غيره، لأن هذه قواعد في رأسك وليست في الكود.
3. **قائمة OWASP Top 10 كقائمة تحقق:** القائمة تصف نفسها بأنها [وثيقة توعية](https://top10.owasp.org/2025/?ref=arabroot.io) Awareness Document لأشهر أنواع المخاطر في تطبيقات الويب، وهي مفيدة كتذكير، ولكنها لا تعرف شيئاً عن نظامك: من يتصل بمن، وأين البيانات الحساسة، وأين تتغير الثقة.
4. **«سوف ننتبه أثناء الكتابة»:** كل مطور ينتبه للجزء الذي يكتبه، ولكن أغلب الثغرات الخطيرة تقع بين الأجزاء: بين ال Reverse Proxy والتطبيق، وبين التطبيق وقاعدة البيانات، وبين خدمتك ومزود خارجي، وهذا المكان لا يملكه مطور واحد.

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

## ما هي نمذجة التهديدات Threat Modeling؟ أربعة أسئلة فقط

يعرف [بيان نمذجة التهديدات Threat Modeling Manifesto](https://www.threatmodelingmanifesto.org/?ref=arabroot.io)، الذي كتبته مجموعة من خمسة عشر مختصاً منهم آدم شوستاك، نمذجة التهديدات بأنها «analyzing representations of a system to highlight concerns about security and privacy characteristics»، أي تحليل تمثيل للنظام (رسم أو وصف) لإظهار المخاوف المتعلقة بخصائص الأمان والخصوصية. لاحظ أن التعريف يتحدث عن تمثيل للنظام، وليس عن النظام نفسه، وهذا يعني أنك تستطيع أن تبدأ قبل أن يوجد سطر واحد من الكود.

والطريقة التي يتفق عليها أغلب الممارسين هي ما يسميه شوستاك في [صفحته عن نمذجة التهديدات](https://shostack.org/resources/threat-modeling?ref=arabroot.io) إطار الأسئلة الأربعة Four Question Framework، وهي نفسها الأسئلة الواردة في البيان:

1. **What are we working on?** ماذا نبني؟ والإجابة رسم للنظام.
2. **What can go wrong?** ما الذي قد يسوء؟ والإجابة قائمة تهديدات.
3. **What are we going to do about it?** ماذا سنفعل حيالها؟ والإجابة قرار لكل تهديد.
4. **Did we do a good enough job?** هل قمنا بعمل جيد بما يكفي؟ والإجابة مراجعة واختبارات. (في صفحة شوستاك نفسها تكتب «Did we do a good job?» دون كلمة enough).

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

![أربع بطاقات في حلقة: البطاقة الأولى What are we working on مع رسم DFD وحدود الثقة، والثانية What can go wrong مع قائمة تهديدات STRIDE لكل عنصر، والثالثة What are we going to do about it مع القرارات الأربعة mitigate وeliminate وtransfer وaccept، والرابعة Did we do a good enough job مع المراجعة والاختبارات، وفي الوسط دائرة تقول ابدأ من جديد عند كل ميزة جديدة أو تغيير في التصميم](https://arabroot.io/content/images/2026/10/threat-modeling-01-four-questions.webp)

الأسئلة الأربعة حلقة وليست خطوات تنتهي، فكل ميزة جديدة تعيدك إلى السؤال الأول

ويضيف البيان خمس قيم Values تلخص روح العمل، وأهمها لفريق صغير اثنتان: «People and collaboration over processes, methodologies, and tools»، أي أن الناس والحوار أهم من الطريقة والأداة، و«Continuous refinement over a single delivery»، أي التحسين المستمر بدلاً من وثيقة تسلم مرة واحدة. ويحذر البيان أيضاً من أنماط خاطئة Anti-patterns، منها «Hero Threat Modeler»، أي الاعتماد على شخص خبير واحد يعرف كل شيء، ومنها السعي إلى الرسم المثالي «Perfect Representation». وقد يتساءل البعض: هل هناك طريقة واحدة صحيحة لنمذجة التهديدات؟ والإجابة نجدها في مقال Microsoft القديم [Uncover Security Design Flaws Using The STRIDE Approach](https://learn.microsoft.com/en-us/archive/msdn-magazine/2006/november/uncover-security-design-flaws-using-the-stride-approach?ref=arabroot.io) من عام 2006: «There are multiple approaches to threat modeling, and anyone who tells you his method is the only right one is mistaken»، لذلك سوف نأخذ في هذا المقال الطريقة الأكثر انتشاراً، وهي مخطط تدفق البيانات مع STRIDE، ثم نذكر البدائل ومتى تناسب.

## التطبيق الذي سوف نحلله: SaaS صغير للفواتير

سوف نستخدم مثالاً واحداً في كل المقال حتى تكون التهديدات حقيقية وليست عامة. لدينا تطبيق فواتير يخدم عدة شركات (كل شركة مستأجر Tenant)، وفيه ما يلي:

- **المتصفح Browser:** العميل يسجل الدخول وينشئ الفواتير، والجلسة محفوظة في ملف تعريف ارتباط Cookie.
- **ال Reverse Proxy:** يستقبل HTTPS من الإنترنت ويمرر الطلبات إلى الخدمات الداخلية عبر HTTP داخل شبكة Docker.
- **ال API:** خدمة التطبيق الأساسية، تقرأ وتكتب في قاعدة البيانات.
- **لوحة الإدارة Admin Panel:** تطبيق منفصل لفريق الدعم، يقرأ من قاعدة البيانات نفسها.
- **قائمة المهام Job Queue وخدمة البريد Email Worker:** ال API يضع مهمة «أرسل الفاتورة» في Redis، والخدمة تأخذها وترسل البريد عبر مزود بريد خارجي بمفتاح API Key.
- **قاعدة البيانات PostgreSQL:** فيها فواتير كل الشركات وبيانات عملائها.

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

## الخطوة الأولى: ماذا نبني؟ ارسم مخطط تدفق البيانات DFD

مخطط تدفق البيانات Data Flow Diagram واختصاراً DFD هو رسم بسيط يبين من أين تأتي البيانات وإلى أين تذهب، وهو الطريقة التي تعتمدها Microsoft منذ سنوات لنمذجة التهديدات. وفي المقال المذكور أعلاه تتكون لغة DFD من أربعة عناصر، ويضاف إليها خامس لنمذجة التهديدات:

- **الكيان الخارجي External Entity:** (ويسمى أيضاً Interactor) طرف خارج سيطرتك يرسل البيانات أو يستقبلها، مثل المستخدم أو متصفحه أو مزود البريد، ويرسم كمستطيل.
- **العملية Process:** كود يعمل ويعالج البيانات، مثل ال API أو ال Reverse Proxy أو خدمة البريد، ويرسم كدائرة.
- **مخزن البيانات Data Store:** مكان تبقى فيه البيانات، مثل قاعدة البيانات أو قائمة المهام أو ملفات الرفع أو ملفات السجلات، ويرسم كخطين متوازيين.
- **تدفق البيانات Data Flow:** بيانات تنتقل بين عنصرين، طلب HTTP أو استعلام SQL أو رسالة في قائمة، ويرسم كسهم.
- **حد الثقة Trust Boundary:** خط متقطع يفصل بين أماكن تختلف فيها الثقة، مثل الإنترنت وشبكتك الداخلية، أو تطبيقك وخدمة طرف ثالث.

والصورة التالية تبين مخطط تطبيق الفواتير بهذه العناصر، والأرقام على الأسهم هي التي سوف نشير إليها في بقية المقال:

![مخطط تدفق بيانات من خمس مناطق تفصلها خطوط حمراء متقطعة: INTERNET فيها Customer browser وAdmin، وEDGE فيها Reverse Proxy، وAPP NETWORK فيها API وAdmin Panel وJob queue وEmail Worker، وTHIRD PARTY فيها Email Provider، وDATABASE NETWORK فيها PostgreSQL. الأسهم المرقمة: 1 من المتصفح إلى ال Proxy عبر HTTPS مع ملف تعريف الارتباط، و2 دخول المدير، و3 من ال Proxy إلى API على HTTP :8080، و4 إلى لوحة الإدارة على HTTP :9000، و5 و6 عبر قائمة المهام إلى Email Worker، و7 إلى مزود البريد عبر HTTPS بمفتاح API، و8 و9 استعلامات SQL إلى PostgreSQL، وفي الأسفل مفتاح رموز DFD](https://arabroot.io/content/images/2026/10/threat-modeling-02-dfd.webp)

كل سهم يعبر خطاً أحمر متقطعاً هو مكان تتغير فيه الثقة، وهو أول ما سوف نسأل عنه

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

- **حدود الثقة ليست حدود الشبكة دائماً:** رسمنا الشبكة الداخلية وقاعدة البيانات في منطقتين منفصلتين لأن صلاحيات الوصول تختلف، فخدمة البريد في الشبكة نفسها مع ال API ولكنها يجب ألا تصل إلى قاعدة البيانات، وهذا قرار يظهر في الرسم قبل أن يظهر في إعداد الشبكة كما شرحنا في دليل [شبكات Docker](https://arabroot.io/articles/%D8%B4%D8%A8%D9%83%D8%A7%D8%AA-docker-%D9%88%D8%A3%D9%81%D8%B6%D9%84-%D8%A7%D9%84%D9%85%D9%85%D8%A7%D8%B1%D8%B3%D8%A7%D8%AA/).
- **السهم 3 يحمل ملف تعريف الارتباط بعد أن ينتهي HTTPS:** فال Reverse Proxy ينهي التشفير ويمرر الطلب بنص واضح داخل الشبكة، وهذا ليس خطأ بالضرورة، ولكنه قرار يجب أن يكتب.
- **مزود البريد خارج حدودك:** فكل ما يمر في السهم 7 من أسماء العملاء ومبالغ الفواتير أصبح عند طرف ثالث، ومفتاح API الذي يرسل به هو مفتاح يستطيع أن يرسل بريداً باسم نطاقك.
- **لوحة الإدارة عملية مستقلة:** لها مسار دخول خاص (السهم 2 ثم 4)، وتصل إلى كل بيانات كل المستأجرين، لذلك هي أعلى عنصر قيمة في الرسم بعد قاعدة البيانات.

### كيف تعرف أن الرسم Diagram جيد بما يكفي؟

لا تحاول أن ترسم كل Container وكل منفذ، فالهدف هو أن يفهم كل من في الغرفة أين تمر البيانات، وليس أن تنتج مخطط بنية Architecture Diagram كامل. ويذكر مقال Microsoft قواعد بسيطة لمراجعة الرسم، نلخصها كما يلي:

- **لا توجد بيانات تظهر من العدم ولا تختفي في العدم:** كل مخزن بيانات يجب أن يكون له من يكتب فيه ومن يقرأ منه، فإذا رسمت قاعدة بيانات تدخلها البيانات ولا يقرؤها أحد فقد نسيت لوحة الإدارة أو التقارير أو النسخ الاحتياطي.
- **لا تنتقل البيانات بالتخاطر:** البيانات لا تذهب من المستخدم إلى القرص مباشرة، فبينهما دائماً عملية تقرأ وتكتب، وهذه العملية هي التي تحتاج إلى التحقق من المدخلات.
- **اجمع العناصر المتشابهة داخل الحد نفسه:** عشر نسخ من ال API خلف موزع الحمل Load Balancer عنصر واحد في الرسم ما دامت كلها بالتقنية نفسها وداخل الحد نفسه.
- **ابدأ بمستوى عام ثم فصل:** رسم السياق Context Diagram يبين النظام كله في صفحة، وإذا احتاج جزء حساس مثل الدفع إلى تفصيل فارسم له رسماً مستقلاً.

ويمكنك أن ترسم المخطط في أي أداة، والأشهر [draw.io](https://www.drawio.com/?ref=arabroot.io) (ويسمى أيضاً diagrams.net) وهو مفتوح المصدر بترخيص [Apache-2.0](https://github.com/jgraph/drawio?ref=arabroot.io) ويحفظ الرسم كملف في المستودع، أو في أدوات نمذجة التهديدات التي سوف نراها لاحقاً، أو بالكود كما سوف نفعل في التجربة العملية.

## الخطوة الثانية: ما الذي قد يسوء؟ اسأل STRIDE

عندما تنظر إلى الرسم وتسأل «ما الذي قد يسوء؟» بدون أي إطار، فسوف تجد ما تتذكره في تلك اللحظة فقط، والمطور الذي عانى من حقن SQL سوف يجده في كل مكان وينسى الباقي. لذلك نحتاج إلى قائمة أسئلة ثابتة، وأشهرها STRIDE، وهي اختصار لست فئات من التهديدات وضعها Loren Kohnfelder وPraerit Garg في Microsoft في أبريل 1999 كما يروي شوستاك في مقال [20 Years of STRIDE](https://shostack.org/blog/20-years-of-stride-looking-back-looking-forward/?ref=arabroot.io). والفكرة الأساسية أن كل فئة تكسر خاصية أمنية واحدة، كما في جدول [مقال Microsoft من عام 2006](https://learn.microsoft.com/en-us/archive/msdn-magazine/2006/november/uncover-security-design-flaws-using-the-stride-approach?ref=arabroot.io)، والصورة التالية تبين الفئات الست مع الخاصية التي تكسرها ومثال من تطبيق الفواتير:

![جدول من ستة صفوف ملونة: S Spoofing انتحال الهوية يكسر Authentication المصادقة، مثال ملف تعريف ارتباط مسروق يعاد إرساله، والحماية ملفات تعريف ارتباط آمنة وOIDC وPasskeys وMFA. T Tampering العبث بالبيانات يكسر Integrity، مثال تعديل JWT إلى role=admin أو تغيير مبلغ الفاتورة. R Repudiation الإنكار يكسر Non-repudiation، مثال مدير يحذف فاتورة ويقول لست أنا. I Information disclosure كشف المعلومات يكسر Confidentiality، مثال المستأجر A يفتح فاتورة المستأجر B. D Denial of service حجب الخدمة يكسر Availability، مثال إغراق /login أو تصدير PDF ضخم. E Elevation of privilege رفع الصلاحيات يكسر Authorization، مثال عميل يستدعي مسار إدارة](https://arabroot.io/content/images/2026/10/threat-modeling-03-stride.webp)

إذا عرفت الخاصية التي يكسرها التهديد، عرفت نوع الحماية التي تبحث عنها

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

### انتحال الهوية Spoofing: هل هذا فعلاً من يدعي أنه هو؟

الانتحال يكسر خاصية المصادقة Authentication، وهو أن يتصرف شخص أو برنامج باسم غيره. في تطبيقنا أوضح مثال هو ملف تعريف ارتباط الجلسة: إذا سرقه مهاجم عبر ثغرة XSS أو من جهاز مشترك أو من سجل طبع الترويسات كاملة، فإنه يرسل الطلبات إلى ال API والتطبيق يراه العميل نفسه. ومثال آخر أقل وضوحاً: هل تتأكد خدمة البريد أن المهمة في قائمة Redis جاءت فعلاً من ال API، أم يستطيع أي شيء في الشبكة أن يضع مهمة؟ والحماية في خصائص ملفات تعريف الارتباط ودورة حياة الجلسة كما في دليل [الجلسات وملفات تعريف الارتباط وJWT](https://arabroot.io/articles/%D8%A7%D9%84%D8%AC%D9%84%D8%B3%D8%A7%D8%AA-%D9%88%D9%85%D9%84%D9%81%D8%A7%D8%AA-%D8%AA%D8%B9%D8%B1%D9%8A%D9%81-%D8%A7%D9%84%D8%A7%D8%B1%D8%AA%D8%A8%D8%A7%D8%B7-%D9%88-jwt-%D9%84%D9%84%D9%85%D8%A8%D8%AA%D8%AF%D8%A6%D9%8A%D9%86/#cookie-attributes)، وفي الدخول الموحد كما في [OAuth وOpenID Connect](https://arabroot.io/articles/%D8%B4%D8%B1%D8%AD-oauth-%D9%88-openid-connect-%D9%84%D9%84%D9%85%D8%A8%D8%AA%D8%AF%D8%A6%D9%8A%D9%86/)، وفي المصادقة الأقوى كما في [مفاتيح المرور Passkeys](https://arabroot.io/articles/%D8%A7%D9%84%D8%AF%D8%AE%D9%88%D9%84-%D8%AF%D9%88%D9%86-%D9%83%D9%84%D9%85%D8%A9-%D9%85%D8%B1%D9%88%D8%B1-passkeys-%D9%88-fido2/). وانتحال الهوية لا يخص المستخدمين فقط، فرسائل البريد التي ترسلها باسم نطاقك يمكن انتحالها أيضاً، وهذا ما تحميه سجلات [SPF وDKIM وDMARC](https://arabroot.io/articles/%D8%B4%D8%B1%D8%AD-spf-%D9%88-dkim-%D9%88-dmarc-%D9%84%D9%84%D9%85%D8%A8%D8%AA%D8%AF%D8%A6%D9%8A%D9%86/).

### العبث بالبيانات Tampering: هل يمكن تغيير البيانات في الطريق أو في المخزن؟

العبث يكسر خاصية السلامة Integrity. ومثاله الكلاسيكي في تطبيقات الويب أن يرسل المتصفح مبلغ الفاتورة أو سعر المنتج في الطلب، فيغيره المستخدم قبل الإرسال، والحل أن يحسب السيرفر المبلغ من البنود ولا يثق بالرقم القادم. ومثال آخر: توكن JWT يحمل `role`، فإذا قبل ال API توكناً دون أن يتحقق من توقيعه أو قبل الخوارزمية `none` كما في [أخطاء JWT المتكررة](https://arabroot.io/articles/%D8%A7%D9%84%D8%AC%D9%84%D8%B3%D8%A7%D8%AA-%D9%88%D9%85%D9%84%D9%81%D8%A7%D8%AA-%D8%AA%D8%B9%D8%B1%D9%8A%D9%81-%D8%A7%D9%84%D8%A7%D8%B1%D8%AA%D8%A8%D8%A7%D8%B7-%D9%88-jwt-%D9%84%D9%84%D9%85%D8%A8%D8%AA%D8%AF%D8%A6%D9%8A%D9%86/#jwt-pitfalls)، فالمستخدم يكتب صلاحياته بنفسه. وفي الرسم، السهم 3 بنص واضح داخل الشبكة يعني أن أي Container مخترق في الشبكة نفسها يستطيع نظرياً أن يغير الطلبات، والقرار هنا إما تشفير داخلي أو عزل الشبكة وقبول المخاطرة بشكل مكتوب.

### الإنكار Repudiation: هل تستطيع أن تثبت من فعل ماذا؟

الإنكار يكسر خاصية عدم الإنكار Non-repudiation، وهو أن يقوم شخص بفعل ثم ينكره ولا يوجد ما يثبت العكس. في تطبيقنا: موظف دعم يحذف فاتورة من لوحة الإدارة أو يغير بريد عميل، ثم يقول «لم أفعل»، فإذا كان سجل التطبيق لا يكتب من فعل ماذا ومتى، أو كان السجل في قاعدة البيانات نفسها التي يستطيع المدير أن يعدلها، فلا يوجد دليل. والحماية سجل تدقيق Audit Log يكتب المستخدم والفعل والمورد والوقت، ويحفظ خارج متناول من يكتب فيه، كما في قسم [التدقيق في دليل IAM وPAM](https://arabroot.io/articles/%D8%A7%D8%AF%D8%A7%D8%B1%D8%A9-%D8%A7%D9%84%D9%87%D9%88%D9%8A%D8%A9-%D9%88%D8%A7%D9%84%D9%88%D8%B5%D9%88%D9%84-iam-%D9%88%D8%A7%D9%84%D9%88%D8%B5%D9%88%D9%84-%D8%A7%D9%84%D9%85%D9%85%D9%8A%D8%B2-pam/#audit)، وهذا السجل نفسه هو أول ما سوف تحتاجه عند الحادثة كما في [الاستعداد قبل الحادثة في دليل DFIR](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/#prepare).

### كشف المعلومات Information Disclosure: من يرى ما لا يجب أن يراه؟

كشف المعلومات يكسر خاصية السرية Confidentiality، وهو أخطر فئة في تطبيق SaaS، لأن أشهر صورها أن يرى مستأجر بيانات مستأجر آخر. في تطبيقنا: الرابط `/invoices/42` يعيد الفاتورة إذا كان المستخدم مسجلاً دون أن يتأكد أن الفاتورة لشركته، وهذه ثغرة IDOR التي شرحناها في دليل [الصلاحيات المركزية](https://arabroot.io/articles/%D8%A7%D9%84%D8%B5%D9%84%D8%A7%D8%AD%D9%8A%D8%A7%D8%AA-%D8%A7%D9%84%D9%85%D8%B1%D9%83%D8%B2%D9%8A%D8%A9-authorization-rbac-%D9%88-rebac/#the-problem)، أما فصل بيانات المستأجرين في التصميم نفسه فموضوع دليل [تعدد المستأجرين Multi-tenancy](https://arabroot.io/articles/%D8%AA%D8%B9%D8%AF%D8%AF-%D8%A7%D9%84%D9%85%D8%B3%D8%AA%D8%A7%D8%AC%D8%B1%D9%8A%D9%86-multi-tenancy-%D9%81%D9%8A-saas-%D9%84%D9%84%D9%85%D8%A8%D8%AA%D8%AF%D8%A6%D9%8A%D9%86/). وهناك صور أخرى في الرسم نفسه: ال API الذي يعيد أي Origin في ترويسة CORS كما في [دليل CORS](https://arabroot.io/articles/%D8%B4%D8%B1%D8%AD-cors-%D9%88%D8%B3%D9%8A%D8%A7%D8%B3%D8%A9-%D8%A7%D9%84%D9%85%D8%B5%D8%AF%D8%B1-%D8%A7%D9%84%D9%88%D8%A7%D8%AD%D8%AF/)، وصفحة الخطأ التي تطبع Stack Trace، والفاتورة التي تذهب كاملة إلى مزود البريد وفيها أكثر مما يحتاجه، وترويسات الاستجابة التي تكشف إصدار السيرفر أو تسمح بعرض الصفحة في موقع آخر كما في دليل [ترويسات الأمان HSTS وCSP](https://arabroot.io/articles/%D8%AA%D8%B1%D9%88%D9%8A%D8%B3%D8%A7%D8%AA-%D8%A7%D9%84%D8%A3%D9%85%D8%A7%D9%86-hsts-%D9%88-csp/).

### حجب الخدمة Denial of Service: هل يستطيع أحد أن يوقف التطبيق؟

حجب الخدمة يكسر خاصية التوفر Availability. ولا نقصد هنا فقط الهجمات الضخمة من آلاف الأجهزة، وإنما الأشياء الصغيرة التي يكفيها شخص واحد: سكربت يرسل آلاف الطلبات إلى `/login`، أو طلب تصدير لكل الفواتير منذ عشر سنوات يشغل كل خدمات التصدير، أو رفع ملف ضخم يملأ القرص، أو آلاف المهام في قائمة البريد فلا تصل فواتير العملاء الحقيقيين. والحماية على مستوى ال Reverse Proxy كما في قسم [الحد من معدل الطلبات Rate Limiting](https://arabroot.io/articles/%D8%AD%D9%85%D8%A7%D9%8A%D8%A9-%D8%AA%D8%B7%D8%A8%D9%8A%D9%82%D8%A7%D8%AA-%D8%A7%D9%84%D9%88%D9%8A%D8%A8-%D8%B9%D9%84%D9%89-%D9%85%D8%B3%D8%AA%D9%88%D9%89-http/#rate-limiting)، وعلى مستوى التطبيق بحدود للحجم ومهلة Timeout وحد لكل مستأجر.

### رفع الصلاحيات Elevation of Privilege: هل يستطيع أحد أن يفعل أكثر مما يحق له؟

رفع الصلاحيات يكسر خاصية التفويض Authorization، وهو أن يحصل مستخدم على قدرات لم تعط له. في تطبيقنا: مسارات الإدارة موجودة في ال API نفسه تحت `/api/admin`، والواجهة لا تعرض الزر للعميل، ولكن الطلب يعمل إذا أرسله يدوياً. أو دور المستخدم يقرأ من حقل في الطلب. والحماية أن يكون التفويض في مكان واحد والرفض هو الافتراضي Deny by Default، كما في دليل [الصلاحيات المركزية Authorization](https://arabroot.io/articles/%D8%A7%D9%84%D8%B5%D9%84%D8%A7%D8%AD%D9%8A%D8%A7%D8%AA-%D8%A7%D9%84%D9%85%D8%B1%D9%83%D8%B2%D9%8A%D8%A9-authorization-rbac-%D9%88-rebac/).

### STRIDE لكل عنصر STRIDE per Element: أي سؤال لأي عنصر؟

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

![على اليسار جدول STRIDE per Element من Microsoft عام 2006: الكيان الخارجي External entity عليه S وR، والعملية Process عليها الحروف الستة، ومخزن البيانات Data store وتدفق البيانات Data flow عليهما T وI وD. وعلى اليمين عناصر تطبيق الفواتير مع الحروف: Customer browser وAdmin وEmail Provider عليها S وR، وReverse Proxy وAPI وAdmin Panel عليها STRIDE، والأسهم بينها وPostgreSQL عليها T I D](https://arabroot.io/content/images/2026/10/threat-modeling-04-stride-per-element.webp)

الجدول يحول STRIDE من ستة أسئلة لكل شيء إلى قائمة أسئلة محددة لكل عنصر

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

- **العمليات تأخذ الأسئلة الستة:** لأنها الكود الذي يستقبل المدخلات ويتخذ القرارات، لذلك أغلب التهديدات في أي نموذج تقع على ال API وال Reverse Proxy ولوحة الإدارة.
- **الأسهم ومخازن البيانات تأخذ T وI وD:** أي هل يمكن تغيير البيانات أو قراءتها أو منع وصولها. ويضيف بعض الممارسين سؤال الإنكار R لمخزن يحفظ سجلات التدقيق، لأن من يعدل السجل يمحو الدليل.
- **الكيانات الخارجية تأخذ S وR:** فأنت لا تتحكم بالمتصفح ولا بمزود البريد، والسؤال الوحيد هو هل تعرف بثقة من هو، وهل تستطيع أن تثبت ما فعله.
- **التهديد يظهر غالباً على السهم الذي يعبر حد الثقة:** ابدأ بالأسهم 1 و2 و7، ثم العمليات التي تستقبلها، فهي الأكثر تعرضاً.

### طرق أخرى: LINDDUN وPASTA وشجرة الهجوم Attack Tree ونظرة المهاجم Attacker

STRIDE ليست الطريقة الوحيدة، وصفحة [OWASP Threat Modeling Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Threat%5FModeling%5FCheat%5FSheet.html?ref=arabroot.io) توصي باختيار الطريقة حسب الهدف، وفيما يلي أشهرها باختصار:

- **LINDDUN للخصوصية Privacy:** STRIDE تسأل عن الأمان، أما [LINDDUN](https://linddun.org/?ref=arabroot.io) فتسأل عن الخصوصية، وهي من جامعة KU Leuven في بلجيكا ونشرت أول مرة عام 2010 ومجانية، وحروفها سبع فئات: Linking (ربط بيانات الشخص من مصادر مختلفة) وIdentifying (معرفة هويته) وNon-repudiation (عدم قدرته على إنكار ما لا يريد أن يعرف عنه) وDetecting (معرفة أنه يستخدم الخدمة) وData Disclosure (كشف بياناته) وUnawareness (عدم علمه بما يحدث لبياناته) وNon-compliance (مخالفة الأنظمة). لاحظ أن عدم الإنكار ميزة في STRIDE وتهديد في LINDDUN، لأن ما يحمي النظام قد يضر خصوصية المستخدم. وإذا كان تطبيقك يحفظ بيانات شخصية فاستخدمها مع STRIDE.
- **PASTA للمخاطر Risk-centric:** اختصار Process for Attack Simulation and Threat Analysis، وضعها Tony UcedaVélez وMarco Morana في كتاب نشرته Wiley عام 2015، وهي سبع مراحل كما في [صفحة VerSprite](https://versprite.com/resources/blog/understanding-7-stages-pasta-threat-modeling/?ref=arabroot.io): تحديد الأهداف، ثم النطاق، ثم تفكيك التطبيق، ثم تحليل التهديدات، ثم تحليل الثغرات، ثم نمذجة الهجمات، ثم تقييم المخاطر والأثر. وهي تبدأ من أهداف العمل وتنتهي بالأثر عليه، لذلك تناسب المؤسسات التي لديها فريق مخاطر، وهي أثقل من أن تبدأ بها في فريق من خمسة مطورين.
- **شجرة الهجوم Attack Tree:** فكرة نشرها Bruce Schneier في مجلة Dr. Dobb's عام 1999 كما في [مقاله](https://www.schneier.com/academic/archives/1999/12/attack%5Ftrees.html?ref=arabroot.io): هدف المهاجم في أعلى الشجرة، والطرق المختلفة للوصول إليه في الفروع تحته. وهي مفيدة لتهديد واحد مهم تريد أن تفهم كل طرقه، مثل «قراءة فواتير مستأجر آخر»، ففروعه IDOR وحساب دعم مخترق ونسخة احتياطية مكشوفة وتصدير بلا فحص.
- **نظرة المهاجم: Kill Chain وMITRE ATT&CK:** نموذج [Cyber Kill Chain](https://www.lockheedmartin.com/en-us/capabilities/cyber/cyber-kill-chain.html?ref=arabroot.io) من Lockheed Martin يقسم الهجوم إلى سبع خطوات يجب أن يكملها المهاجم ليصل إلى هدفه، و[MITRE ATT&CK](https://attack.mitre.org/?ref=arabroot.io) قاعدة معرفة لتكتيكات المهاجمين وتقنياتهم مبنية على ملاحظات من هجمات حقيقية. وهما أقرب إلى فرق الدفاع والمراقبة منهما إلى تصميم تطبيق جديد، ولكنهما يساعدانك على السؤال «إذا دخل المهاجم إلى ال Container الأول، فماذا يفعل بعده؟»، وسوف نشرح ATT&CK في مقال مستقل ضمن [مرحلة الأمن السيبراني](https://arabroot.io/start/#stage-security) بإذن الله.
- **OWASP Top 10 كقائمة تذكير:** كما ذكرنا هي وثيقة توعية وليست نموذج تهديدات، فاستخدمها بعد STRIDE لتسأل «هل نسينا فئة مشهورة؟»، ولا تستخدمها بدلاً من رسم نظامك.

## الخطوة الثالثة: ماذا سنفعل حيالها؟ التخفيف والإزالة والنقل والقبول Risk Response

بعد الخطوة الثانية سوف يكون لديك قائمة قد تكون طويلة، وأسوأ ما يمكن أن تفعله بها أن تحفظها في ملف وتنساها. فكل تهديد يحتاج إلى قرار واحد من أربعة، كما في صفحة [OWASP Threat Modeling Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Threat%5FModeling%5FCheat%5FSheet.html?ref=arabroot.io):

- **التخفيف Mitigate:** تضيف ضابطاً يقلل احتمال حدوث التهديد أو أثره، مثل الحد من معدل الطلبات على `/login`، وهو القرار الأكثر شيوعاً.
- **الإزالة Eliminate:** تحذف الميزة أو العنصر الذي يسبب التهديد، مثل إخراج مسارات الإدارة من ال API العام كلياً، وهذا أقوى قرار لأن الكود غير الموجود لا يمكن مهاجمته.
- **النقل Transfer:** تحمل طرفاً آخر المسؤولية بعقد أو تأمين، مثل ترك بيانات البطاقات عند مزود الدفع فلا تمر بقاعدة بياناتك أصلاً. لاحظ أن النقل لا يعني أنك أصبحت غير مسؤول، فما زلت مسؤولاً عن طريقة ربطك بالمزود.
- **القبول Accept:** تقرر أن المخاطرة مقبولة لأن الحماية أغلى من الضرر أو لأن الوقت لا يسمح الآن، وهذا قرار مشروع بشرط أن يكون مكتوباً وله مالك وتاريخ مراجعة، وليس سكوتاً.

### ترتيب المخاطر Risk Ranking دون أن تغرق في الأرقام

لن تحل كل التهديدات في هذا الإصدار، لذلك تحتاج إلى ترتيب. وتقول صفحة OWASP إن الترتيب يكون على أساس حاصل ضرب الاحتمال Likelihood في الأثر Impact، مع أنها تعترف بأن تقدير الاثنين صعب. والطريقة الأبسط لفريق صغير أن تضع لكل تهديد احتمالاً منخفضاً أو متوسطاً أو مرتفعاً، وأثراً بالمستويات نفسها، وتبدأ من الزاوية العليا، كما تبين الصورة التالية لتهديدات تطبيق الفواتير العشرة التي سوف نراها في [القالب](#template):

![على اليسار شبكة ثلاثة في ثلاثة للاحتمال likelihood والأثر impact، فيها T3 في الزاوية العليا اليمنى، وT1 وT2 وT8 وT10 في خانة احتمال متوسط وأثر مرتفع، وT5 احتمال مرتفع وأثر متوسط، وT4 وT6 وT9 في الوسط، وT7 احتمال منخفض. وعلى اليمين أربع بطاقات: Mitigate خفف مع مثال T5 الحد من الطلبات وfail2ban، وEliminate أزل مع مثال T2 لا مسارات إدارة في ال API العام، وTransfer انقل مع مثال بيانات البطاقات تبقى عند مزود الدفع، وAccept اقبل مع مثال T7 HTTP داخل شبكة Docker واحدة مع مالك وتاريخ مراجعة](https://arabroot.io/content/images/2026/10/threat-modeling-05-decide.webp)

الشبكة البسيطة تكفي لترتيب العمل، والأهم أن يخرج كل تهديد بقرار ومالك

وقد يتساءل البعض: ماذا عن DREAD، طريقة الترتيب التي تعطي كل تهديد خمس درجات؟ والإجابة أن آدم شوستاك، الذي قاد نمذجة التهديدات في دورة التطوير الآمن SDL في Microsoft، يضعها في [صفحته](https://shostack.org/resources/threat-modeling?ref=arabroot.io) تحت عنوان «Deprecated» ويذكر أن خبراء نمذجة التهديدات نادراً ما يستخدمونها، لأنها تركز على الأثر والمخاطر وليس على إيجاد التهديدات، ودرجاتها تختلف كثيراً من شخص لآخر. لذلك لا تضيع وقت الاجتماع في نقاش هل الدرجة 6 أم 7، فالشبكة البسيطة تكفي، وإذا كانت مؤسستك تستخدم سجل مخاطر Risk Register رسمياً فانقل إليه التهديدات المقبولة فقط، كما سوف نشرح في مقالات [مرحلة الحوكمة والمخاطر والامتثال GRC](https://arabroot.io/start/#stage-grc) بإذن الله.

### من التهديد إلى تذكرة Ticket واختبار Security Test

القرار الذي لا يتحول إلى عمل في نظام المهام لن ينفذ، لذلك حول كل قرار تخفيف أو إزالة إلى تذكرة Ticket عادية في نظام المهام نفسه الذي يعمل عليه الفريق، واكتب فيها رقم التهديد حتى تعرف لاحقاً لماذا أضيف هذا الكود. والأفضل من ذلك أن تحول التهديد إلى اختبار أمني Security Test Case يفشل إذا عاد التهديد، فالتهديد T3 (المستأجر A يقرأ فاتورة المستأجر B) يصبح اختبار تكامل Integration Test يسجل الدخول كمستخدم من شركة ويطلب فاتورة شركة أخرى ويتوقع الرد 404، والتهديد T2 يصبح اختباراً يتوقع 403 من كل مسار إدارة بتوكن عميل عادي. وهذه الاختبارات من النوع الذي شرحناه في دليل [أنواع الاختبارات](https://arabroot.io/articles/%D8%A7%D9%86%D9%88%D8%A7%D8%B9-%D8%A7%D9%84%D8%A7%D8%AE%D8%AA%D8%A8%D8%A7%D8%B1%D8%A7%D8%AA-%D9%84%D9%84%D9%85%D8%A8%D8%AA%D8%AF%D8%A6%D9%8A%D9%86-unit-%D9%88-integration-%D9%88-e2e/)، وميزتها أنها تعمل في كل تشغيل لخط CI، فلا يعود التهديد بعد سنة عندما يعيد أحد كتابة المسار.

## الخطوة الرابعة: هل قمنا بعمل جيد بما يكفي؟ المراجعة Validation

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

### نموذج التهديدات Threat Model يعيش مع الكود، لا وثيقة تموت في مجلد

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

- **عند كل تغيير في التصميم:** أي ميزة تضيف سهماً يعبر حد ثقة (مزود خارجي جديد، رفع ملفات، Webhook من طرف آخر، صلاحية جديدة) تحتاج إلى عشر دقائق مع الرسم قبل أن يبدأ الكود.
- **في طلب الدمج Pull Request:** احفظ الرسم وجدول التهديدات في المستودع بجانب الكود، فإذا غير طلب الدمج البنية فعليه أن يحدث النموذج، والمراجع يرى الاثنين معاً كما في [العمل اليومي مع Git](https://arabroot.io/articles/git-merge-%D9%88-rebase-%D9%88-cherry-pick/).
- **النموذج ككود Threat Model as Code:** بدلاً من رسم في أداة رسومية، تكتب العناصر والأسهم في ملف Python أو YAML، وتولد منه الرسم وقائمة التهديدات في خط CI، كما سوف نفعل في التجربة مع pytm.
- **بعد كل حادثة أو ملاحظة من اختبار اختراق:** اسأل لماذا لم يظهر هذا التهديد في النموذج، وأضفه، فالنموذج يتعلم كما يتعلم الفريق.

### جلسة Threat Modeling في نصف ساعة لفريق صغير

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

1. **خمس دقائق للرسم:** من يعرف الميزة يرسمها على السبورة أو في draw.io: العناصر والأسهم وحدود الثقة، دون تفاصيل.
2. **خمس عشرة دقيقة لما قد يسوء:** المرور على كل سهم يعبر حداً ثم العمليات التي تستقبله، مع جدول STRIDE لكل عنصر، وكتابة كل تهديد في سطر دون نقاش الحلول بعد.
3. **سبع دقائق للقرارات:** لكل تهديد قرار واحد ومالك، وما يحتاج إلى بحث يصبح تذكرة بحث.
4. **ثلاث دقائق للسؤال الرابع:** هل نسينا جزءاً؟ ومتى نعود إلى هذا الرسم؟

ومن يحضر؟ المطور الذي سوف يكتب الميزة، ومطور من الفريق يعرف بقية النظام، ومن يعرف التشغيل والشبكة، ومالك المنتج Product Owner لأنه وحده يعرف ما هو الضرر الحقيقي على العمل، وشخص من فريق الأمن إن وجد، على أن يكون ميسراً Facilitator يسأل وليس صاحب الإجابات. والسبب أن البيان يحذر من «المختص البطل» Hero Threat Modeler، فإذا كان شخص واحد يعرف كل التهديدات فقد أصبح هو نقطة الفشل.

## أين تقع نمذجة التهديدات بين SAST وDAST واختبار الاختراق؟

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

![مراحل التطوير من اليسار: Design ثم Code ثم Build / CI ثم Test / staging ثم Release ثم Operate، وتحت كل مرحلة النشاط الأمني: Threat modeling ينظر إلى التصميم والضوابط الناقصة وحدود الثقة، وSAST وفحص الأسرار يقرأ الكود دون تشغيله، وSCA وSBOM وفحص ال Images يفحص ما أخذته من غيرك، وDAST مع OWASP ZAP يهاجم التطبيق العامل من الخارج، واختبار الاختراق Penetration test أشخاص يحاولون كسر النظام الحقيقي، والمراقبة والاستجابة للحوادث ترى الهجمات التي تحدث فعلاً. سهم متقطع يعيد كل ملاحظة وحادثة إلى النموذج، وسهم أحمر يبين أن خطأ التصميم الذي يكتشف في البداية يعني تعديل رسم، وفي النهاية يعني إعادة كتابة ونقل بيانات وإبلاغ المستخدمين](https://arabroot.io/content/images/2026/10/threat-modeling-06-lifecycle.webp)

الأدوات بعد التصميم تجد أخطاء في التنفيذ، أما الضابط الذي لم يصمم أصلاً فلا تجده إلا نمذجة التهديدات أو المهاجم

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

- **نمذجة التهديدات هي النشاط الوحيد قبل الكود:** فهي لا تحتاج إلى تطبيق يعمل، ولذلك هي الأرخص في إصلاح ما تجده.
- **SAST وDAST يجدان أخطاء التنفيذ:** الأول في الكود والثاني في التطبيق العامل، وسوف نشرحهما مع Semgrep وOWASP ZAP في مقالات [مرحلة DevOps](https://arabroot.io/start/#stage-devops) بإذن الله، ومنها مقال مصطلحات DevSecOps.
- **ما تأخذه من غيرك له نموذج تهديدات خاص:** المكتبات وال Docker Images وخط CI/CD نفسه، وهذا موضوع دليل [أمن سلسلة التوريد البرمجية Software Supply Chain](https://arabroot.io/articles/%D8%A7%D9%85%D9%86-%D8%B3%D9%84%D8%B3%D9%84%D8%A9-%D8%A7%D9%84%D8%AA%D9%88%D8%B1%D9%8A%D8%AF-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A9-%D9%84%D9%84%D9%85%D8%A8%D8%AA%D8%AF%D8%A6%D9%8A%D9%86/)، ويمكنك أن تضيف خط CI إلى رسمك كعملية لها أسهم إلى المستودع والسيرفر.
- **اختبار الاختراق يختبر النموذج:** فالمختبر الذي يعرف نموذج التهديدات يوجه وقته إلى الأماكن الأخطر، وكل ما يجده خارج النموذج يعني أن النموذج ناقص.

## الأدوات مفتوحة المصدر Open Source والمجانية

الأداة الأهم هي السبورة والقلم، والأدوات التالية تساعدك على الرسم والحفظ والتوليد، وقد راجعنا تراخيصها وحالتها من مستودعاتها وصفحاتها الرسمية في أكتوبر 2026:

### OWASP Threat Dragon: رسم ونموذج في المتصفح

[OWASP Threat Dragon](https://owasp.org/www-project-threat-dragon/?ref=arabroot.io) تطبيق ويب وسطح مكتب لرسم مخطط تدفق البيانات وتسجيل التهديدات لكل عنصر، وهو مشروع OWASP بمستوى Production وترخيصه [Apache-2.0](https://github.com/OWASP/threat-dragon?ref=arabroot.io)، وآخر إصدار عند كتابة المقال هو [v2.6.2](https://github.com/OWASP/threat-dragon/releases/tag/v2.6.2?ref=arabroot.io) في مايو 2026\. ويحفظ النموذج كملف JSON على جهازك أو في مستودع GitHub أو GitLab أو Bitbucket، وفي الإصدار الثاني واجهة باللغة العربية. وقد شغلناه في Docker بإعداد التطوير المحلي من [صفحة الإعداد](https://www.threatdragon.com/docs/configure/configure.html?ref=arabroot.io) على منفذ محلي فقط:

```bash
docker run -d --name lab-tm-dragon -p 127.0.0.1:38480:3000 \
  -e NODE_ENV=development -e SERVER_API_PROTOCOL=http \
  -e ENCRYPTION_KEYS='[{"isPrimary": true, "id": 0, "value": "'$(openssl rand -hex 16)'"}]' \
  -e ENCRYPTION_JWT_SIGNING_KEY=$(openssl rand -hex 16) \
  -e ENCRYPTION_JWT_REFRESH_SIGNING_KEY=$(openssl rand -hex 16) \
  threatdragon/owasp-threat-dragon:stable
```

ثم فتحنا `http://127.0.0.1:38480` واخترنا Login to Local Session، ثم أحد النماذج التجريبية المرفقة مع الأداة، وهو تطبيق ويب من ثلاث طبقات مأخوذ من OWASP Threat Model Cookbook، وأضفنا إلى الخدمة تهديد انتحال من مثالنا، والصورة التالية تبين النتيجة:

![واجهة Threat Dragon v2.6.2: على اليسار أدوات الرسم Process وStore وActor وData Flow وTrust Boundary، وفي الوسط رسم Three Tier Web App فيه منطقة Internet فيها Web UI ومنطقة Public Cloud فيها Web Service وPostgresSQL، وعنصر Web Service محدد بإطار أحمر لأن عليه تهديداً مفتوحاً، وفي الأسفل لوحة Properties ولوحة Threats فيها بطاقة التهديد رقم 3 Stolen session cookie replayed against the API من نوع Spoofing مع علامة STRIDE](https://arabroot.io/content/images/2026/10/threat-modeling-08-threat-dragon.webp)

في Threat Dragon يتحول العنصر إلى الأحمر عندما يكون عليه تهديد مفتوح، والتهديد يأخذ نوعاً من STRIDE وحالة وشدة وطريقة تخفيف

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

### OWASP pytm: النموذج ككود

[OWASP pytm](https://github.com/OWASP/pytm?ref=arabroot.io) مكتبة Python تصف فيها النظام بالكود: العناصر وحدود الثقة والأسهم والبيانات التي تمر فيها وخصائص كل عنصر، ثم تولد مخطط DFD بصيغة Graphviz ومخطط تسلسل Sequence Diagram وقائمة تهديدات من مكتبة قواعد مدمجة أغلب مراجعها من قائمة [CAPEC](https://capec.mitre.org/?ref=arabroot.io) لأنماط الهجمات. ترخيصها MIT، وآخر إصدار [1.4.0](https://github.com/OWASP/pytm/releases/tag/v1.4.0?ref=arabroot.io) في يوليو 2026 ويحتاج Python 3.11 أو أحدث كما في [PyPI](https://pypi.org/project/pytm/?ref=arabroot.io). نقاط القوة: النموذج ملف في المستودع يراجع في طلب الدمج ويولد في CI. نقاط الضعف: القواعد عامة وتنتج ضجيجاً كثيراً كما سوف ترى في التجربة، وتحتاج إلى من يفرز النتائج.

### Threagile: نموذج YAML وقواعد مخاطر

[Threagile](https://threagile.io/?ref=arabroot.io) أداة مكتوبة بلغة Go تصف فيها البنية والأصول في ملف YAML، فتشغل عليه قواعد مخاطر جاهزة وتولد تقارير ورسوماً، وتعمل من Docker. ترخيصها [MIT](https://github.com/Threagile/threagile?ref=arabroot.io)، والمستودع ما زال يستقبل تعديلات في 2026، ولكن آخر إصدار رسمي هو [v0.9.1](https://github.com/Threagile/threagile/releases/tag/v0.9.1?ref=arabroot.io) من يوليو 2024، والمستودع نفسه يقول إن الواجهة الرسومية ما زالت بعيدة عن الجاهزية، لذلك ثبت الإصدار الذي تستخدمه إذا اعتمدت عليها في CI.

### Microsoft Threat Modeling Tool: مجانية ولكنها ليست مفتوحة المصدر

[Microsoft Threat Modeling Tool](https://learn.microsoft.com/en-us/azure/security/develop/threat-modeling-tool?ref=arabroot.io) أداة مجانية من Microsoft مبنية على STRIDE per Element وتولد التهديدات تلقائياً من الرسم، ولها قوالب Templates قابلة للتعديل نشرتها Microsoft في [مستودع مستقل](https://github.com/microsoft/threat-modeling-templates?ref=arabroot.io) بترخيص MIT. ولكنها كما في [صفحة الإصدارات](https://learn.microsoft.com/en-us/azure/security/develop/threat-modeling-tool-releases?ref=arabroot.io) تعمل على Windows فقط (Windows 10 Anniversary Update أو أحدث مع .NET 4.7.1)، وتحتاج إلى الإنترنت للتحديثات، وآخر إصدار 7.3.51110.1 في نوفمبر 2025، وهي برنامج مغلق المصدر Proprietary. نقاط القوة: توليد تلقائي ناضج وتقارير. نقاط الضعف: Windows فقط، وملفاتها لا تقرأ في أدوات أخرى بسهولة.

### ألعاب البطاقات: Elevation of Privilege وOWASP Cornucopia

إذا كان الفريق لا يحب الاجتماعات، فالبطاقات تحول الأسئلة إلى لعبة. [Elevation of Privilege](https://shostack.org/games/elevation-of-privilege?ref=arabroot.io) لعبة بطاقات صممها آدم شوستاك في Microsoft، كل مجموعة فيها فئة من STRIDE وكل بطاقة تهديد محدد، واللاعب يكسب نقطة إذا ربط بطاقته بعنصر في الرسم، وقد نشرتها Microsoft بترخيص CC BY 3.0 كما في [مستودعها](https://github.com/adamshostack/eop?ref=arabroot.io). و[OWASP Cornucopia](https://cornucopia.owasp.org/?ref=arabroot.io) لعبة مشابهة لتطبيقات الويب والجوال، مجموعاتها المصادقة والتحقق من المدخلات وإدارة الجلسات والتفويض والتشفير، وترخيصها CC BY-SA 4.0.

### مقارنة سريعة بين الأدوات Tools

| الأداة                             | النوع                   | الترخيص                 | التشغيل                   | يناسب                                |
| ---------------------------------- | ----------------------- | ----------------------- | ------------------------- | ------------------------------------ |
| OWASP Threat Dragon                | رسم وتسجيل تهديدات      | Apache-2.0              | ويب أو سطح مكتب أو Docker | فريق يريد واجهة رسومية مجانية        |
| OWASP pytm                         | نموذج ككود بلغة Python  | MIT                     | مكتبة Python مع Graphviz  | فريق يريد النموذج في المستودع وفي CI |
| Threagile                          | نموذج YAML وقواعد مخاطر | MIT                     | Docker أو ملف تنفيذي      | من يحب YAML ويريد تقارير مخاطر       |
| Microsoft Threat Modeling Tool     | رسم وتوليد تهديدات      | مجانية ومغلقة المصدر    | Windows فقط               | فرق Windows وAzure                   |
| draw.io                            | رسم عام                 | Apache-2.0              | ويب أو سطح مكتب           | رسم DFD سريع يحفظ في المستودع        |
| Elevation of Privilege وCornucopia | بطاقات للجلسة           | CC BY 3.0 وCC BY-SA 4.0 | مطبوعة أو على الإنترنت    | بدء الحوار مع فريق جديد على الموضوع  |

وهناك منصات تجارية لنمذجة التهديدات في المؤسسات الكبيرة، مثل [IriusRisk](https://www.iriusrisk.com/?ref=arabroot.io)، وهي خارج نطاق هذا المقال لأننا نركز على ما تستطيع تشغيله بنفسك.

## تجربة عملية: نمذجة تطبيق الفواتير بالكود مع pytm

الآن سوف نصف تطبيق الفواتير نفسه بالكود، ونترك pytm يرسم المخطط ويولد التهديدات، ثم نقرأ النتائج كما يقرؤها فريق حقيقي: ما المفيد وما الضجيج، ثم نسجل القرارات في الملف نفسه. وسوف نشغل كل شيء داخل Container حتى لا نثبت Python وGraphviz على جهازك.

### تجهيز ال Container

أنشئ مجلداً للتجربة وشغل Container من Docker Image الرسمية لPython، ثم ثبت Graphviz (لرسم المخطط) وpytm بإصدار محدد:

```bash
mkdir -p ~/lab-tm && cd ~/lab-tm
docker run -d --name lab-tm-pytm -v "$PWD:/work" -w /work python:3.12-slim sleep infinity
docker exec lab-tm-pytm sh -c "apt-get update -qq && apt-get install -y -qq graphviz >/dev/null && pip install -q pytm==1.4.0"
docker exec lab-tm-pytm sh -c "pip show pytm | head -3; dot -V"
```

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

```text
Name: pytm
Version: 1.4.0
Summary: A Pythonic framework for threat modeling
dot - graphviz version 2.42.4 (0)
```

ومن الآن سوف نكتب الأوامر من داخل ال Container، فادخل إليه بالأمر `docker exec -it lab-tm-pytm bash`.

### الخطوة 1: نصف النظام في ملف tm.py

أنشئ الملف `tm.py` في مجلد التجربة بالمحتوى التالي، وهو المخطط نفسه الذي رسمناه في الخطوة الأولى:

```python
#!/usr/bin/env python3
# Threat model of a small invoicing SaaS (ArabRoot threat modeling explainer)
from pytm import (TM, Actor, Boundary, Dataflow, Datastore, ExternalEntity,
                  Server, Process, Data, Classification, DatastoreType)

tm = TM("Invoices SaaS")
tm.description = "Small multi-tenant invoicing SaaS: browser, reverse proxy, API, PostgreSQL, admin panel and an email provider"
tm.isOrdered = True
tm.mergeResponses = True

internet = Boundary("Internet")
dmz = Boundary("Edge")
app_net = Boundary("App network")
db_net = Boundary("Database network")
vendor = Boundary("Third party")

customer = Actor("Customer browser")
customer.inBoundary = internet
admin = Actor("Admin")
admin.inBoundary = internet

proxy = Server("Reverse Proxy")
proxy.inBoundary = dmz
proxy.protocol = "HTTPS"
proxy.port = 443
proxy.controls.isHardened = True
proxy.controls.sanitizesInput = False
proxy.controls.encodesOutput = False

api = Server("API")
api.inBoundary = app_net
api.usesSessionTokens = True
api.controls.authenticatesSource = True
api.controls.hasAccessControl = True
api.controls.validatesInput = True
api.controls.sanitizesInput = False
api.controls.encodesOutput = True
api.controls.isHardened = False
api.sourceFiles = ["api/"]

admin_panel = Server("Admin Panel")
admin_panel.inBoundary = app_net
admin_panel.controls.authenticatesSource = True
admin_panel.controls.hasAccessControl = True
admin_panel.controls.isHardened = False

worker = Process("Email Worker")
worker.inBoundary = app_net

db = Datastore("PostgreSQL")
db.inBoundary = db_net
db.type = DatastoreType.SQL
db.isSQL = True
db.controls.isEncryptedAtRest = False
db.controls.hasAccessControl = True
db.storesPII = True
db.storesSensitiveData = True

mail = ExternalEntity("Email Provider")
mail.inBoundary = vendor

creds = Data("Login credentials", classification=Classification.SECRET, isCredentials=True, isPII=False)
session = Data("Session cookie", classification=Classification.SECRET, isCredentials=True)
invoice = Data("Invoice data", classification=Classification.SENSITIVE, isPII=True, isStored=True)
email = Data("Invoice email", classification=Classification.SENSITIVE, isPII=True)

f1 = Dataflow(customer, proxy, "Login and API requests", protocol="HTTPS", dstPort=443, data=[creds, session])
f1.controls.isEncrypted = True
f2 = Dataflow(proxy, api, "Forwarded requests", protocol="HTTP", dstPort=8080, data=[session, invoice])
f2.controls.isEncrypted = False
f3 = Dataflow(api, db, "SQL queries", protocol="PostgreSQL", dstPort=5432, data=invoice)
f3.controls.isEncrypted = False
f4 = Dataflow(db, api, "Query results", protocol="PostgreSQL", data=invoice)
f5 = Dataflow(api, proxy, "API responses", protocol="HTTP", data=invoice)
f6 = Dataflow(proxy, customer, "Responses", protocol="HTTPS", data=invoice)
f6.controls.isEncrypted = True
f7 = Dataflow(admin, proxy, "Admin login", protocol="HTTPS", dstPort=443, data=creds)
f7.controls.isEncrypted = True
f8 = Dataflow(proxy, admin_panel, "Admin requests", protocol="HTTP", dstPort=9000, data=session)
f9 = Dataflow(admin_panel, db, "Admin queries", protocol="PostgreSQL", dstPort=5432, data=invoice)
f10 = Dataflow(api, worker, "Send invoice job", protocol="Redis", dstPort=6379, data=email)
f11 = Dataflow(worker, mail, "Send email (API key)", protocol="HTTPS", dstPort=443, data=email)
f11.controls.isEncrypted = True

if __name__ == "__main__":
    tm.process()
```

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

- **العناصر بأنواع DFD:** `Actor` و`ExternalEntity` للكيانات الخارجية، و`Server` و`Process` للعمليات، و`Datastore` لمخزن البيانات، و`Dataflow` للأسهم، و`Boundary` لحدود الثقة، وكل عنصر يوضع في حده بالخاصية `inBoundary`.
- **الضوابط Controls هي ما تعرفه عن كل عنصر:** مثل `validatesInput` و`hasAccessControl`، والقواعد تقرأ هذه الخصائص، فكل خاصية تتركها على قيمتها الافتراضية تعتبرها الأداة غير موجودة. لذلك أجب عنها بصدق، فالكذبة هنا تخفي تهديداً حقيقياً.
- **البيانات لها تصنيف Classification:** بيانات الدخول والجلسة `SECRET` والفواتير `SENSITIVE` وفيها بيانات شخصية `isPII`، وبعض القواعد تعمل فقط على الأسهم التي تحمل بيانات حساسة.
- **رسمنا الردود Responses أيضاً:** مثل `Query results` و`API responses`، والخاصية `mergeResponses` تدمج الطلب ورده في سهم واحد في الرسم.

### الخطوة 2: نولد مخطط تدفق البيانات

الأمر `--dfd` يطبع المخطط بلغة Graphviz، ونمرره إلى `dot` ليحوله إلى صورة:

```bash
python3 tm.py --dfd | dot -Tpng -Gdpi=150 -o dfd.png
```

والصورة التالية تبين المخطط الذي ولدته الأداة من الملف دون أي تعديل:

![مخطط DFD ولدته pytm بأسلوب Graphviz: مربعات متقطعة حمراء لحدود الثقة Internet وEdge وApp network وDatabase network وThird party، وفيها Customer browser وAdmin كمستطيلات، وReverse Proxy وAPI وAdmin Panel وEmail Worker كدوائر، وPostgreSQL كأسطوانة، وEmail Provider كمستطيل، والأسهم مرقمة من 1 إلى 11 بأسمائها مثل Login and API requests وForwarded requests وSQL queries وSend email (API key)](https://arabroot.io/content/images/2026/10/threat-modeling-07-pytm-dfd.webp)

المخطط يولد من الكود، فإذا تغير الكود في طلب دمج تغير الرسم معه

### الخطوة 3: نولد قائمة التهديدات Threats

مكتبة القواعد Rules المدمجة في pytm نراها بالأمر `--list`:

```bash
python3 tm.py --list | wc -l
python3 tm.py --list | head -5
```

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

```text
113
INP01 - Buffer Overflow via Environment Variables
INP02 - Overflow Buffers
INP03 - Server Side Include (SSI) Injection
CR01 - Session Sidejacking
INP04 - HTTP Request Splitting
```

والتقرير يولد من قالب، والقالب الافتراضي في المستودع يخرج صفحة طويلة، لذلك سوف نكتب قالباً من سطر واحد في الملف `table.md` يطبع لكل تهديد رقمه وشدته Severity والعنصر ووصفه:

```text
{findings:repeat:{{item:call:getThreatId}} | {{item:call:getFindingSeverity}} | {{item:call:getFindingTarget}} | {{item:call:getFindingDescription}}
}
```

ثم نولد التقرير ونعد التهديدات ونوزعها حسب الشدة:

```bash
python3 tm.py --report table.md > findings.txt
grep -c . findings.txt
cut -d"|" -f2 findings.txt | grep . | sort | uniq -c | sort -rn
```

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

```text
238
    105  Medium
     92  High
     29  Very High
     10  Low
      2  Very Low 
```

مئتان وثمانية وثلاثون تهديداً لتطبيق من سبع خدمات، وتوزيعها على العناصر كما يلي:

```bash
cut -d"|" -f3 findings.txt | grep . | sort | uniq -c | sort -rn
```

```text
     43  Reverse Proxy
     40  Admin Panel
     36  API
     34  Email Worker
      8  Login and API requests
      8  Forwarded requests
      8  Admin requests
      8  Admin login
      7  Send invoice job
      7  Send email (API key)
      7  SQL queries
      7  Responses
      7  Query results
      7  Admin queries
      7  API responses
      4  PostgreSQL 
```

لاحظ أن التوزيع يطابق جدول STRIDE لكل عنصر الذي رأيناه: العمليات الأربع عليها أغلب التهديدات، والأسهم عليها سبعة أو ثمانية، ومخزن البيانات عليه أربعة.

### الخطوة 4: نفرز النتائج Triage كما يفعل الفريق

هذه القائمة ليست نموذج التهديدات، وإنما مسودة أسئلة. لنأخذ السهم 2، أي الطلبات من ال Reverse Proxy إلى ال API عبر HTTP داخل الشبكة:

```bash
grep "| Forwarded requests |" findings.txt
```

```text
DE01 | Medium | Forwarded requests | Interception
AC05 | Medium | Forwarded requests | Content Spoofing
DE03 | Medium | Forwarded requests | Sniffing Attacks
CR06 | High | Forwarded requests | Communication Channel Manipulation
CR08 | Medium | Forwarded requests | Client-Server Protocol Manipulation
DS06 | Very High | Forwarded requests | Data Leak
DR01 | High | Forwarded requests | Unprotected Sensitive Data
AC23 | High | Forwarded requests | Credentials Disclosure
```

وهذه نتائج مفيدة فعلاً: ملف تعريف ارتباط الجلسة وبيانات الفواتير تمر بنص واضح بعد ال Reverse Proxy، وأي شيء في الشبكة نفسها يستطيع أن يقرأها، وهذا هو السؤال الذي كتبناه عند السهم 3 في رسمنا. أما على ال API فسوف تجد نتائج من نوع آخر:

```bash
grep -E "PHP|LDAP|SOAP|XML" findings.txt | grep "| API |"
```

```text
INP19 | Medium | API | XML External Entities Blowup
INP22 | High | API | XML Attribute Blowup
INP34 | High | API | SOAP Array Overflow
```

وتطبيقنا لا يستخدم XML ولا SOAP أصلاً. وقد يتساءل البعض: لماذا تظهر هذه التهديدات؟ والإجابة في شرط القاعدة نفسها في ملف القواعد `threats.json` داخل المكتبة، فشرط INP19 هو `target.usesXMLParser is False or target.controls.disablesDTD is False`، أي أنه ينطبق حتى عندما تقول إن الخدمة لا تستخدم محلل XML Parser، وشرط INP34 يكفيه أن الخاصية `checksInputBounds` لم تضبط. وهذا ليس عيباً يمنعك من استخدام الأداة، وإنما يذكرك بأن القواعد العامة تسأل أكثر مما يلزم، والفريق هو الذي يقرر، وأن كل نتيجة تقرأ ثم يكتب لها قرار.

### الخطوة 5: نسجل القرارات والافتراضات Assumptions في النموذج نفسه

بعد جلسة المراجعة نضيف القرارات إلى الملف نفسه قبل السطر `if __name__ == "__main__":`، وكل قرار عليه رقم التذكرة:

```python
# ---- decisions after the review meeting (2026-10) ----
from pytm import Assumption

# Not applicable: the stack has no PHP, LDAP, SOAP or XML parsing
tm.assumptions = [Assumption("No PHP, LDAP, SOAP or XML in this stack",
                             exclude={"INP16", "INP09", "INP34", "INP19", "INP21", "INP22"})]

# Mitigate (SEC-12): internal services accept TLS only, callers verify certificates
for server in (api, admin_panel, db):
    server.controls.isEncrypted = True
for caller in (proxy, api, admin_panel):
    caller.controls.authenticatesDestination = True
    caller.controls.checksDestinationRevocation = True

# Mitigate (SEC-14): rate limiting and request size limits on the proxy
proxy.controls.handlesResourceConsumption = True
proxy.controls.isResilient = True

# Mitigate (SEC-15): random server-side session ids with expiry
api.controls.usesStrongSessionIdentifiers = True
```

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

- **الافتراض Assumption قرار مكتوب:** القواعد الست لا تنطبق على تقنيات لا نستخدمها، وبدلاً من أن نحذفها من التقرير بصمت، كتبنا السبب في النموذج، فإذا أضاف أحد لاحقاً محلل XML فسوف يرى الافتراض ويعرف أنه لم يعد صحيحاً.
- **التخفيف يكتب كضابط على العنصر:** TLS داخلي بين الخدمات، والحد من الطلبات على ال Proxy، ومعرف جلسة قوي، وكل واحد منها له تذكرة سوف تنفذ وتختبر.

ثم نولد التقرير مرة أخرى:

```bash
python3 tm.py --report table.md > findings.txt
grep -c . findings.txt
grep "| Forwarded requests |" findings.txt
```

```text
199
DE03 | Medium | Forwarded requests | Sniffing Attacks
CR06 | High | Forwarded requests | Communication Channel Manipulation
DS06 | Very High | Forwarded requests | Data Leak
AC23 | High | Forwarded requests | Credentials Disclosure
```

انخفض العدد من 238 إلى 199، والتهديدات على السهم 2 من ثمانية إلى أربعة، وما بقي يحتاج إلى قرار آخر، فمثلاً DE03 ينطبق ما دام السهم لا يستخدم VPN، وDS06 ينطبق لأننا لم نحدد أعلى تصنيف بيانات يسمح لكل عنصر أن يستقبله بالخاصية `maxClassification`. والملف الذي يحفظ النتائج للأدوات الأخرى نولده بصيغة JSON:

```bash
python3 tm.py --json tm.json
python3 -c "import json; j=json.load(open('tm.json')); print(len(j['findings']), len(j['excluded_findings']))"
```

```text
199 16
```

لاحظ الرقم الثاني: ستة عشر تهديداً استبعدت بالافتراض، ولكنها لم تختف، فهي محفوظة في `excluded_findings` مع اسم الافتراض الذي استبعدها، وهذا هو الفرق بين قرار مكتوب وتهديد محذوف.

### ماذا يحدث إذا وضعت التشفير على السهم نفسه؟

الطريقة التي تبدو طبيعية لتسجيل TLS الداخلي هي أن تضبطه على السهم، أي `f2.controls.isEncrypted = True`، وإذا فعلت ذلك بدلاً من الحلقتين أعلاه فسوف تجد أن السهم 2 ما زال عليه التهديدات الثمانية نفسها، وأن العدد الكلي 217\. والسبب في الكود نفسه: قبل تطبيق القواعد تملأ pytm القيم الافتراضية للأسهم، فتأخذ `isEncrypted` من العنصر الذي يستقبل السهم، وتأخذ `authenticatesDestination` من العنصر الذي يرسله، وتكتب فوق ما وضعته على السهم. لذلك صف التشفير كخاصية في الخدمة التي تقبل TLS فقط، وتحقق دائماً من أن قرارك غير التقرير فعلاً، فالنموذج ككود يحتاج إلى مراجعة مثل أي كود.

### إزالة التجربة

احذف ال Containers التي أنشأناها بأسمائها:

```bash
docker rm -f lab-tm-pytm lab-tm-dragon
```

⚠️

لا تستخدم أوامر التنظيف العامة مثل `docker system prune` أو `docker volume prune` بعد التجربة، لأنها تحذف كل ما ليس قيد التشغيل على الجهاز، ومنها Containers وVolumes لمشاريع أخرى. احذف ما أنشأته بالاسم فقط.

## قالب Template جاهز للنسخ، ومثال من عشرة تهديدات

إذا لم تكن تريد أداة الآن، فهذا القالب يكفي، احفظه كملف `THREATS.md` بجانب الكود وحدثه في كل طلب دمج يغير البنية:

```markdown
# Threat model: <system or feature>

- Scope: <what is in and out>
- Diagram: docs/dfd.drawio (updated: YYYY-MM-DD)
- People: <names and roles who attended>
- Next review: <date or trigger, e.g. "new external provider">

| ID | Element (DFD) | Threat (STRIDE) | Impact | Likelihood | Decision | Mitigation / reason | Owner | Ticket | Status |
|----|---------------|-----------------|--------|------------|----------|---------------------|-------|--------|--------|
| T1 |               |                 |        |            |          |                     |       |        |        |
```

والجدول التالي مثال مكتمل لتطبيق الفواتير، والأرقام نفسها التي وضعناها على شبكة المخاطر:

| ID  | العنصر                         | التهديد (STRIDE)                                                                        | الأثر      | القرار والتخفيف                                                                                       | المالك          | الحالة            |
| --- | ------------------------------ | --------------------------------------------------------------------------------------- | ---------- | ----------------------------------------------------------------------------------------------------- | --------------- | ----------------- |
| T1  | السهم 1 (المتصفح إلى ال Proxy) | S: ملف تعريف ارتباط الجلسة يسرق ويعاد إرساله                                            | مرتفع      | تخفيف: HttpOnly وSecure وSameSite، ومهلة خمول قصيرة، وتغيير المعرف عند الدخول                         | قائد ال Backend | مفتوح (SEC-15)    |
| T2  | API                            | E: عميل يستدعي مسارات /api/admin مباشرة                                                 | مرتفع      | إزالة: نقل مسارات الإدارة إلى لوحة الإدارة فقط، مع اختبار يتوقع 404 من ال API العام                   | قائد ال Backend | قيد التنفيذ       |
| T3  | API إلى PostgreSQL             | I: المستأجر A يقرأ فاتورة المستأجر B بتغيير المعرف                                      | مرتفع جداً | تخفيف: معرف المستأجر في كل استعلام مع Row-Level Security، واختبار تكامل لكل مسار                      | قائد ال Backend | مفتوح             |
| T4  | API                            | T: المتصفح يرسل مبلغ الفاتورة                                                           | متوسط      | تخفيف: السيرفر يحسب المبلغ من البنود ويتجاهل الرقم القادم                                             | مطور الفواتير   | مغلق              |
| T5  | Reverse Proxy                  | D: تخمين كلمات المرور وإغراق /login                                                     | متوسط      | تخفيف: Rate Limiting على المسار وfail2ban                                                             | التشغيل         | مغلق (SEC-14)     |
| T6  | Admin Panel                    | R: موظف دعم يحذف فاتورة وينكر                                                           | متوسط      | تخفيف: سجل تدقيق لا يعدل يرسل إلى خادم السجلات المركزي                                                | قائد ال Backend | مفتوح             |
| T7  | السهم 3 (ال Proxy إلى API)     | I وT: قراءة الطلبات أو تعديلها داخل شبكة Docker                                         | متوسط      | قبول: الخدمات في شبكة Docker معزولة على سيرفر واحد، ويراجع القرار عند نقلها إلى عدة سيرفرات           | التشغيل         | مقبول حتى 2027-01 |
| T8  | Email Worker                   | I: مفتاح API لمزود البريد يتسرب في السجلات أو المستودع فيرسل المهاجم بريداً باسم نطاقنا | مرتفع      | تخفيف: المفتاح في مدير أسرار Secrets Manager وبصلاحية الإرسال فقط، وتدويره، وتنبيه عند ارتفاع الإرسال | التشغيل         | مفتوح             |
| T9  | Email Provider                 | S: رسائل مزورة باسم نطاقنا تصل إلى العملاء                                              | متوسط      | تخفيف: SPF وDKIM وسياسة DMARC بالرفض                                                                  | التشغيل         | مغلق              |
| T10 | Admin                          | S: سرقة كلمة مرور موظف دعم بالتصيد Phishing                                             | مرتفع      | تخفيف: دخول موحد مع Passkeys، ولوحة الإدارة خلف VPN أو قائمة عناوين مسموحة                            | التشغيل         | قيد التنفيذ       |

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

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

- **محاولة نمذجة كل شيء مرة واحدة Boiling the Ocean:** رسم كل خدمة وكل منفذ في الشركة في ورشة من يومين، ثم لا ينتهي الرسم ولا يخرج أي قرار. ابدأ بالميزة التي تعمل عليها الآن أو بالجزء الأخطر، والنموذج يكبر مع الوقت.
- **نمذجة مرة واحدة قبل الإطلاق:** وثيقة جميلة تحفظ في مجلد، وبعد ثلاثة أشهر لا تشبه النظام. اربط التحديث بتغيير التصميم وبطلب الدمج.
- **فريق الأمن وحده:** المختص الأمني لا يعرف أن خدمة البريد تقرأ من قاعدة البيانات مباشرة، والمطور يعرف. نمذجة التهديدات عمل الفريق الذي يبني النظام، وفريق الأمن يساعد ويسأل.
- **الخلط بينها وبين اختبار الاختراق أو فحص الثغرات:** الاختبار والفحص يعملان على نظام موجود ويجدان أخطاء التنفيذ، ونمذجة التهديدات تعمل على التصميم وتجد الضوابط الناقصة، ولا يغني أحدها عن الآخر.
- **قائمة من الأداة دون فرز:** نسخ مئتي نتيجة من pytm أو غيرها إلى نظام المهام يقتل ثقة الفريق بالعملية كلها. كل نتيجة تقرأ وتأخذ قراراً، والضجيج يستبعد بسبب مكتوب.
- **القبول بالسكوت:** تهديد بلا قرار هو تهديد مقبول دون أن يعرف أحد. القبول قرار له مالك وتاريخ مراجعة.
- **النقاش في الدرجات:** نصف ساعة في الخلاف على هل الاحتمال 6 أم 7 بدلاً من البحث عن تهديدات أخرى. الشبكة البسيطة تكفي.
- **نسيان ما خارج الكود:** النسخ الاحتياطية ولوحات الإدارة وخط CI ومفاتيح المزودين جزء من النظام، وغالباً هي أضعف ما فيه.

## قائمة تحقق

- هل يوجد رسم DFD للنظام أو للميزة، فيه العناصر والأسهم وحدود الثقة، ومحفوظ في المستودع؟
- هل مررت على كل سهم يعبر حد ثقة، وعلى كل عملية تستقبله، بأسئلة STRIDE لكل عنصر؟
- إذا كان النظام يحفظ بيانات شخصية: هل سألت أسئلة الخصوصية مع LINDDUN؟
- هل لكل تهديد قرار واحد (تخفيف أو إزالة أو نقل أو قبول) ومالك؟
- هل تحولت قرارات التخفيف والإزالة إلى تذاكر، والمهمة منها إلى اختبارات تعمل في CI؟
- هل كل قبول مكتوب مع السبب وتاريخ المراجعة؟
- هل حضر الجلسة من يبني النظام ومن يشغله ومن يعرف أثره على العمل؟
- هل يوجد سبب واضح لتحديث النموذج (ميزة جديدة، مزود جديد، حادثة، ملاحظة من اختبار اختراق)، ويطلب في مراجعة طلب الدمج؟

## الخلاصة

وصلنا لنهاية الموضوع، وأهم ما فيه:

- نمذجة التهديدات تسأل «ما الذي قد يسوء؟» على التصميم قبل الكود، لأن الضابط الذي لم يصمم أصلاً لا تجده أدوات SAST وDAST، وOWASP تقول إن التصميم غير الآمن لا يصلحه تنفيذ مثالي.
- الطريقة أربعة أسئلة: ماذا نبني، وما الذي قد يسوء، وماذا سنفعل حياله، وهل قمنا بعمل جيد بما يكفي، وهي حلقة تعود إليها مع كل تغيير.
- الخطوة الأولى رسم DFD بخمسة رموز: الكيان الخارجي والعملية ومخزن البيانات والسهم وحد الثقة، وأغلب التهديدات تقع على الأسهم التي تعبر الحدود.
- الخطوة الثانية STRIDE: الانتحال يكسر المصادقة، والعبث يكسر السلامة، والإنكار يكسر عدم الإنكار، والكشف يكسر السرية، والحجب يكسر التوفر، ورفع الصلاحيات يكسر التفويض، وجدول STRIDE per Element يحدد الأسئلة لكل عنصر، وLINDDUN للخصوصية وPASTA للمخاطر وشجرة الهجوم لتهديد واحد مهم.
- الخطوة الثالثة قرار لكل تهديد مع مالك وتذكرة، والترتيب بالاحتمال والأثر يكفي، وDREAD لم يعد مستخدماً عند الخبراء، والتهديد المهم يصبح اختباراً.
- الأدوات: Threat Dragon للرسم بترخيص Apache-2.0، وpytm وThreagile للنموذج ككود بترخيص MIT، وأداة Microsoft مجانية لكنها مغلقة وعلى Windows فقط، وبطاقات Elevation of Privilege وCornucopia لبدء الحوار.
- في التجربة ولد pytm المخطط و238 تهديداً لتطبيق من سبع خدمات، بعضها مفيد وبعضها ضجيج لتقنيات لا نستخدمها، وبعد تسجيل القرارات والافتراضات في الملف نفسه انخفض العدد إلى 199 مع 16 تهديداً مستبعداً بسبب مكتوب.

[![](https://arabroot.io/content/images/2026/10/supply-chain-cover-cover.webp)دليلأمن سلسلة التوريد البرمجية Software Supply Chain للمبتدئينكل ما بين كود غيرك وسيرفرك قد يحمل كود المهاجم، وهنا تعرف التهديدات الحقيقية بحوادث موثقة والدفاع المناسب لكل حلقة.](https://arabroot.io/articles/%D8%A7%D9%85%D9%86-%D8%B3%D9%84%D8%B3%D9%84%D8%A9-%D8%A7%D9%84%D8%AA%D9%88%D8%B1%D9%8A%D8%AF-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A9-%D9%84%D9%84%D9%85%D8%A8%D8%AA%D8%AF%D8%A6%D9%8A%D9%86/)[![](https://arabroot.io/content/images/2026/10/sessions-cookies-jwt-cover-cover.webp)دليلكيف يتذكرك الموقع بعد تسجيل الدخول؟ الجلسات وJWTبروتوكول HTTP لا يتذكر أحداً، فكيف يبقى المستخدم مسجلاً بين الصفحات، ومتى تختار الجلسة على السيرفر ومتى تختار JWT.](https://arabroot.io/articles/%D8%A7%D9%84%D8%AC%D9%84%D8%B3%D8%A7%D8%AA-%D9%88%D9%85%D9%84%D9%81%D8%A7%D8%AA-%D8%AA%D8%B9%D8%B1%D9%8A%D9%81-%D8%A7%D9%84%D8%A7%D8%B1%D8%AA%D8%A8%D8%A7%D8%B7-%D9%88-jwt-%D9%84%D9%84%D9%85%D8%A8%D8%AA%D8%AF%D8%A6%D9%8A%D9%86/)[![](https://arabroot.io/content/images/2026/10/authorization-cover-cover.webp)دليلAuthorization: كيف تجمع قرارات الصلاحيات في مكان واحدلماذا تتحول شروط الصلاحيات المتفرقة في الكود إلى ثغرات، وكيف تنقل القرار إلى محرك سياسات واحد.](https://arabroot.io/articles/%D8%A7%D9%84%D8%B5%D9%84%D8%A7%D8%AD%D9%8A%D8%A7%D8%AA-%D8%A7%D9%84%D9%85%D8%B1%D9%83%D8%B2%D9%8A%D8%A9-authorization-rbac-%D9%88-rebac/)[![](https://arabroot.io/content/images/2026/10/http-protection-cover-cover.webp)دليلحماية تطبيقات الويب بطبقات أمان في ال Reverse Proxyكلمة المرور وحدها لا تحمي تطبيقاً مكشوفاً على الإنترنت، لذلك نضع أمامه طبقات حماية في ال Reverse Proxy نفسه.](https://arabroot.io/articles/%D8%AD%D9%85%D8%A7%D9%8A%D8%A9-%D8%AA%D8%B7%D8%A8%D9%8A%D9%82%D8%A7%D8%AA-%D8%A7%D9%84%D9%88%D9%8A%D8%A8-%D8%B9%D9%84%D9%89-%D9%85%D8%B3%D8%AA%D9%88%D9%89-http/)[![](https://arabroot.io/content/images/2026/10/security-headers-cover-cover.webp)دليلHSTS وCSP: ترويسات الأمان التي يحتاجها كل تطبيقما الذي تطلبه كل ترويسة أمان من المتصفح، ولماذا يصعب التراجع عن HSTS، وكيف تبني سياسة CSP لا تكسر تطبيقك.](https://arabroot.io/articles/%D8%AA%D8%B1%D9%88%D9%8A%D8%B3%D8%A7%D8%AA-%D8%A7%D9%84%D8%A3%D9%85%D8%A7%D9%86-hsts-%D9%88-csp/)[![](https://arabroot.io/content/images/2026/10/testing-types-cover-cover.webp)دليلأنواع الاختبارات للمبتدئين: من Unit إلى E2E مع Playwrightما الذي يكشفه كل نوع من الاختبارات وما الذي يفوته، وكم اختباراً تكتب من كل نوع، وأين يعمل كل منها في خط CI.](https://arabroot.io/articles/%D8%A7%D9%86%D9%88%D8%A7%D8%B9-%D8%A7%D9%84%D8%A7%D8%AE%D8%AA%D8%A8%D8%A7%D8%B1%D8%A7%D8%AA-%D9%84%D9%84%D9%85%D8%A8%D8%AA%D8%AF%D8%A6%D9%8A%D9%86-unit-%D9%88-integration-%D9%88-e2e/)

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

- أكتوبر 2026: كتابة المقال، وتنفيذ التجربة على OWASP pytm 1.4.0 مع Python 3.12 وGraphviz 2.42.4 داخل Docker Engine 29.8، وتشغيل OWASP Threat Dragon v2.6.2 من Docker Image الرسمية، ومراجعة تراخيص الأدوات وحالتها من مستودعاتها وصفحاتها الرسمية.