
파이썬스러운 위협 모델링 프레임워크
전통적인 위협 모델링은 너무 늦게 도입되거나 때로는 전혀 이루어지지 않는 경우가 많습니다. 또한 수동으로 데이터 흐름과 보고서를 작성하는 것은 매우 시간이 많이 소요됩니다. 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 컨테이너 방식보다 오버헤드가 낮고 더 편리한 대안입니다.
- Linux/MacOS에 Devbox 설치: `curl -fsSL https://get.jetify.com/devbox | bash`
- [Windows/WSL](https://www.jetify.com/docs/devbox/installing-devbox/index#installing-wsl2)에 Devbox 설치
- devbox 최신 버전으로 업데이트: `devbox version update`
- `~/.config/nix/nix.conf` 파일에 GitHub 액세스 토큰 설정: `access-tokens = github.com=YOUR_TOKEN_HERE`
- 프로젝트의 `devbox.json` 파일에 지정된 모든 도구와 패키지를 포함하는 새로운 격리된 셸 환경 생성: `devbox shell`
- 터미널에서 `python`을 입력할 때 사용될 Python 실행 파일의 전체 경로를 `which python` 명령으로 표시합니다. 출력은 다음 경로여야 합니다: `.devbox/nix/profile/default/bin/python`
- 다음 명령을 실행하여 DFD(데이터 흐름 다이어그램)를 `sample.png`라는 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` 사용은 평소와 동일
- `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
db_to_web = Dataflow(db, web, "Comments contents")
db_to_web.protocol = "MySQL"
db_to_web.data = results
web_to_llm = Dataflow(web, llm_api, "Chat completion request")
web_to_llm.protocol = "HTTPS"
web_to_llm.dstPort = 443
tm.process()
또한 pytmGPT를 사용하여 산문에서 모델을 만들 수 있습니다!
다이어그램은 Dot 및 PlantUML 형식으로 출력됩니다.
위의 tm.py 파일에 --dfd 인수를 전달하면 표준 출력으로 출력이 생성되며, 이 출력은 Graphviz의 dot으로 전달되어 데이터 흐름 다이어그램을 생성합니다:```bash
tm.py --dfd | dot -Tpng -o sample.png
이 다이어그램을 생성합니다:
dfd.png
".levels = [1,2]" 속성을 요소에 추가하면 명령 인자 "--levels 1 2"에 따라 (두 플로우 끝이 동일한 DFD 레벨에 있는 경우 해당 요소와 관련된 데이터 흐름도 함께) 렌더링되거나 표시되지 않습니다.
다음 명령은 Sequence 다이어그램을 생성합니다.```bash
tm.py --seq | java -Djava.awt.headless=true -jar plantuml.jar -tpng -pipe > seq.png
이 다이어그램을 생성합니다:
seq.png
다이어그램과 결과는 최종 보고서를 생성하기 위해 템플릿에 포함될 수 있습니다:```bash