
إطار عمل بايثوني لنمذجة التهديدات
غالبًا ما تأتي نمذجة التهديدات التقليدية متأخرة جدًا إلى الحفلة، أو أحيانًا لا تأتي أبدًا. بالإضافة إلى ذلك، يمكن أن يستغرق إنشاء تدفقات البيانات والتقارير اليدوية وقتًا طويلاً للغاية. الهدف من pytm هو تحويل نمذجة التهديدات إلى اليسار، مما يجعل نمذجة التهديدات أكثر أتمتة ومركزية على المطور.
بناءً على مدخلاتك وتعريفك للتصميم المعماري، يمكن لـ pytm إنشاء العناصر التالية تلقائيًا:
إن tm.py هو نموذج مثال. يمكنك تشغيله لإنشاء التقرير وملفات صور المخطط التي يشير إليها:```
mkdir -p tm
./tm.py --report docs/basic_template.md | pandoc -f markdown -t html > tm/report.html
./tm.py --dfd | dot -Tpng -o tm/dfd.png
./tm.py --seq | java -Djava.awt.headless=true -jar $PLANTUML_PATH -tpng -pipe > tm/seq.png
هناك أيضًا مثال `Makefile` يلف كل هذه في أهداف يمكن مشاركتها بسهولة لنماذج متعددة. إذا كان لديك [GNU make](https://www.gnu.org/software/make/) مثبتًا (متاح افتراضيًا على توزيعات لينكس ولكن ليس على OSX)، قم ببساطة بتشغيل:```
make MODEL=the_name_of_your_model_minus_.py
يجب أن يكون لديك إما ملف plantuml.jar في نفس الدليل الذي يحتوي على النموذج الخاص بك، أو تعيين متغير PLANTUML_PATH.
لتجنب تثبيت جميع التبعيات، مثل pandoc أو Java، يمكن تشغيل السكربت داخل حاوية:```
export USE_DOCKER=true make image
make
### البدء - متغير Devbox
لتبسيط استخدام `pytm`، يمكن عزل تبعيات المضيف بالكامل باستخدام [`Devbox`](https://github.com/jetify-com/devbox). وهذا عادة ما يكون بديلاً أقل تكلفة وأكثر ملاءمة من نهج حاوية OCI.
- تثبيت Devbox على Linux/MacOS: `curl -fsSL https://get.jetify.com/devbox | bash`
- تثبيت Devbox على [Windows/WSL](https://www.jetify.com/docs/devbox/installing-devbox/index#installing-wsl2)
- التحديث إلى أحدث إصدار من devbox: `devbox version update`
- قم بتعيين رمز الوصول الخاص بـ GitHub في ملف `~/.config/nix/nix.conf`: `access-tokens = github.com=YOUR_TOKEN_HERE`
- إنشاء بيئة شل جديدة ومعزولة تتضمن جميع الأدوات والحزم المحددة في ملف `devbox.json` للمشروع: `devbox shell`
- عرض المسار الكامل للملف التنفيذي لـ Python الذي سيتم استخدامه عند كتابة `python` في الطرفية باستخدام أمر which python. يجب أن يكون الإخراج المسار التالي: `.devbox/nix/profile/default/bin/python`
- اختبر بتشغيل الأمر التالي، والذي يجب أن ينشئ DFD كملف PNG باسم `sample.png`: `./tm.py --dfd | dot -Tpng -o sample.png`
- الخروج من بيئة شل Devbox: `exit`
## الاستخدام
جميع الوسائط المتاحة:```text
usage: tm.py [-h] [--debug] [--dfd] [--report REPORT]
[--exclude EXCLUDE] [--seq] [--list] [--describe DESCRIBE]
[--list-elements] [--json JSON] [--levels LEVELS [LEVELS ...]]
[--stale_days STALE_DAYS]
optional arguments:
-h, --help show this help message and exit
--debug print debug messages
--dfd output DFD
--report REPORT output report using the named template file (sample
template file is under docs/template.md)
--exclude EXCLUDE specify threat IDs to be ignored
--seq output sequential diagram
--list list all available threats
--colormap color the risk in the diagram
--describe DESCRIBE describe the properties available for a given element
--list-elements list all elements which can be part of a threat model
--json JSON output a JSON file
--levels LEVELS [LEVELS ...]
Select levels to be drawn in the threat model (int
separated by comma).
--stale_days STALE_DAYS
checks if the delta between the TM script and the code
described by it is bigger than the specified value in
days
وسيطة stale_days تحاول تحديد المسافة بالأيام بين البرنامج النصي للنموذج (الذي تكتبه) والكود الذي ينفذ النظام الجاري نمذجته. من الناحية المثالية، يجب أن يكونا متقاربين جدًا في معظم حالات النظام الذي يتم تطويره بنشاط. يمكنك تشغيل هذا بشكل دوري لقياس نبض مشروعك و"حداثة" نموذج التهديد الخاص بك.
العناصر المتاحة حاليًا هي: TM, Element, Server, ExternalEntity, Datastore, Actor, Process, SetOfProcesses, Dataflow, Boundary, Lambda, LLM و Agent.
يمكن سرد الخصائص المتاحة للعنصر باستخدام --describe متبوعًا باسم العنصر:```text
(pytm) ➜ pytm git:(master) ✗ ./tm.py --describe Element Element class attributes: OS definesConnectionTimeout default: False description handlesResources default: False implementsAuthenticationScheme default: False implementsNonce default: False inBoundary inScope Is the element in scope of the threat model, default: True isAdmin default: False isHardened default: False name required onAWS default: False
وسيطة *colormap*، المستخدمة مع *dfd*، تنتج مخطط تدفق البيانات (DFD) مرمز بالألوان حيث يتم طلاء العناصر باللون الأحمر أو الأصفر أو الأخضر اعتمادًا على مستوى المخاطرة (كما تم تحديده من خلال تشغيل القواعد).
## الاستخدام - متغير Devbox
- `devbox shell`
- `pytm` usage as usual
- `exit`
## إنشاء نموذج تهديد
فيما يلي ملف `tm.py` نموذجي يصف تطبيقًا بسيطًا حيث يقوم المستخدم بتسجيل الدخول إلى التطبيق ونشر التعليقات على التطبيق. يقوم خادم التطبيق بتخزين تلك التعليقات في قاعدة البيانات. هناك AWS Lambda تقوم بتنظيف قاعدة البيانات بشكل دوري.```python
#!/usr/bin/env python3
from pytm import TM, Server, Datastore, Dataflow, Boundary, Actor, Lambda, LLM, Data, Classification
tm = TM("my test tm")
tm.description = "another test tm"
tm.isOrdered = True
User_Web = Boundary("User/Web")
Web_DB = Boundary("Web/DB")
user = Actor("User")
user.inBoundary = User_Web
web = Server("Web Server")
web.OS = "CloudOS"
web.isHardened = True
web.sourceCode = "server/web.cc"
db = Datastore("SQL Database (*)")
db.OS = "CentOS"
db.isHardened = False
db.inBoundary = Web_DB
db.isSql = True
db.inScope = False
db.sourceCode = "model/schema.sql"
comments = Data(
name="Comments",
description="Comments in HTML or Markdown",
classification=Classification.PUBLIC,
isPII=False,
isCredentials=False,
# credentialsLife=Lifetime.LONG,
isStored=True,
isSourceEncryptedAtRest=False,
isDestEncryptedAtRest=True
)
results = Data(
name="results",
description="Results of insert op",
classification=Classification.SENSITIVE,
isPII=False,
isCredentials=False,
# credentialsLife=Lifetime.LONG,
isStored=True,
isSourceEncryptedAtRest=False,
isDestEncryptedAtRest=True
)
my_lambda = Lambda("cleanDBevery6hours")
my_lambda.hasAccessControl = True
my_lambda.inBoundary = Web_DB
llm_api = LLM("AI Writing Assistant")
llm_api.isThirdParty = True
llm_api.processesPersonalData = True
llm_api.hasContentFiltering = False
llm_api.hasSystemPrompt = True
llm_api.processesUntrustedInput = True
my_lambda_to_db = Dataflow(my_lambda, db, "(λ)Periodically cleans DB")
my_lambda_to_db.protocol = "SQL"
my_lambda_to_db.dstPort = 3306
user_to_web = Dataflow(user, web, "User enters comments (*)")
user_to_web.protocol = "HTTP"
user_to_web.dstPort = 80
user_to_web.data = comments
web_to_user = Dataflow(web, user, "Comments saved (*)")
web_to_user.protocol = "HTTP"
web_to_db = Dataflow(web, db, "Insert query with comments")
web_to_db.protocol = "MySQL"
web_to_db.dstPort = 3306