
IaC 위협 모델러, STRIDE, MITRE ATT&CK 및 PASTA 프레임워크 사용. Terraform, CloudFormation 및 Kubernetes를 위한 REST API, GraphQL 및 Docker 지원.
정적 IaC 위협 모델러로, Terraform, CloudFormation 및 Kubernetes 매니페스트를 파싱하여 STRIDE, MITRE ATT&CK 또는 PASTA 프레임워크를 사용한 구조화된 위협 모델 보고서를 생성합니다. 네트워크 호출, 클라우드 자격 증명이 필요 없으며 완전히 오프라인에서 작동합니다. CLI, REST API 또는 컨테이너화된 서비스로 실행됩니다.
CLI:
pip install threatmap
threatmap scan ./examples --output report.md --fail-on HIGH
Docker:
docker run -v $(pwd):/workspace bogdynn/threatmap:2.1.0 threatmap scan /workspace --output /workspace/report.md
REST API 서버:
threatmap serve --host 0.0.0.0 --port 8000
# 또는 Docker 사용:
docker run -p 8000:8000 bogdynn/threatmap:2.1.0
# API 엔드포인트: /health, /version, /rules, /analyze
GraphQL API:
docker run -p 8000:8000 bogdynn/threatmap:2.1.0
# GraphQL 엔드포인트: http://localhost:8000/graphql
# 쿼리: health, version, rules
# 뮤테이션: analyze(content, filename, framework)
PyPI에서 설치:
pip install threatmap
또는 로컬 개발용:
git clone https://github.com/bogdanticu88/threatmap.git
cd threatmap
pip install -e .
디렉터리를 스캔하고 Markdown 보고서를 stdout으로 출력:
threatmap scan ./terraform/
여러 경로를 스캔하고 JSON 보고서를 파일로 작성:
threatmap scan ./terraform/ ./k8s/ ./cloudformation/ --format json --output report.json
대화형 HTML 보고서 또는 GitHub Security용 SARIF 보고서 생성:
threatmap scan ./infra/ --format html --output report.html
threatmap scan ./infra/ --format sarif --output report.sarif
CI 게이트 — CRITICAL 또는 HIGH 위협이 발견되면 종료 코드 1 반환:
threatmap scan ./infra/ --fail-on HIGH --output threat-report.md
전체 보고서 작성 없이 터미널 요약 테이블만 출력:
threatmap scan ./infra/ --summary
유니코드를 지원하지 않는 환경을 위해 ASCII 전용 심각도 표시기(이모지 없음) 사용:
threatmap scan ./infra/ --ascii --output report.md
다양한 위협 모델링 프레임워크를 사용하여 분석:
# STRIDE (기본값)
threatmap scan ./infra/ --framework stride
# MITRE ATT&CK (전술 및 기술에 매핑)
threatmap scan ./infra/ --framework mitre --format json
# PASTA (자산 중심 위협 모델링)
threatmap scan ./infra/ --framework pasta --format json
STRIDE (73개 규칙)
MITRE ATT&CK (11개 규칙, 14개 전술)
PASTA (12개 규칙, 자산 중심)
threatmap scan ./examples --output report.md를 번들 예제에 대해 실행하면 전체 Markdown 보고서가 생성됩니다. 아래는 대표적인 발췌문입니다.
### T-002 — Spoofing (CRITICAL)
Resource: AWS::EC2::SecurityGroup.WebSecurityGroup
Property: ingress.ssh_rdp_open
Finding: Security group 'WebSecurityGroup' exposes SSH/RDP (port 22/3389) to 0.0.0.0/0.
Mitigation: Remove public SSH/RDP access. Use AWS Systems Manager Session Manager
or a bastion host with IP restrictions.
보고서는 Mermaid flowchart LR 다이어그램을 추가합니다. 노드는 최악의 심각도에 따라 색상이 지정됩니다(🔴 빨강 = CRITICAL, 🟠 주황 = HIGH). 블록을 Mermaid 렌더러에 붙여넣거나 GitHub에서 직접 확인하십시오.
flowchart LR
Internet((Internet))
subgraph Networking
aws_security_group_web_sg{web_sg}
NetworkPolicy_default_deny{default-deny}
azurerm_network_security_group_app_nsg{app_nsg}
end
subgraph Compute
aws_instance_web[web]
end
subgraph Kubernetes
Namespace_myapp[myapp]
Deployment_api[api]
Service_api_svc[api-svc]
Ingress_api_ingress[api-ingress]
end
subgraph Data
aws_s3_bucket_app_data[(app_data)]
aws_db_instance_app_db[(app_db)]
azurerm_storage_account_app_storage[(app_storage)]
end
subgraph Security
azurerm_key_vault_app_kv[app_kv]
end
subgraph Identity
azurerm_role_assignment_app_contributor[/app_contributor/]
end
AWS__S3__Bucket_AppBucket -->|ref| AWS__S3__Bucket_AuditBucket
AWS__CloudTrail__Trail_AppTrail -->|ref| AWS__S3__Bucket_AuditBucket
Internet -->|HTTPS| Ingress_api_ingress
style aws_security_group_web_sg fill:#ff4444,color:#fff
style aws_s3_bucket_app_data fill:#ff4444,color:#fff
style aws_instance_web fill:#ff8800,color:#fff
style Deployment_api fill:#ff8800,color:#fff
style azurerm_key_vault_app_kv fill:#ffcc00,color:#000
style azurerm_network_security_group_app_nsg fill:#ff8800,color:#fff
style azurerm_role_assignment_app_contributor fill:#ff4444,color:#fff
이제 threatmap에는 리소스 간의 관계를 추적하는 그래프 인텔리전스가 포함됩니다. 하나의 리소스(예: 인터넷에 노출된 EC2)가 손상되면 다른 리소스(예: 프라이빗 S3 버킷)로 직접 이어지는 "연쇄"된 위협을 자동으로 식별하여 이를 Elevation of Privilege 공격 경로로 플래그 지정합니다.
프로젝트 루트에 threatmap_rules.yaml을 생성하여 내부 보안 요구 사항을 정의할 수 있습니다.
rules:
- resource_type: "aws_s3_bucket"
property: "force_destroy"
expected: false
stride: "Tampering"
severity: "MEDIUM"
description: "프로덕션 버킷은 force_destroy를 활성화해서는 안 됩니다."
mitigation: "force_destroy = false로 설정하십시오."
이제 대부분의 발견 사항에는 remediation(수정) 필드가 포함됩니다(JSON, HTML 및 SARIF 보고서에서 확인 가능). 이 필드는 보안 문제를 해결하는 데 필요한 정확한 코드 조각을 제공합니다.
STRIDE 분석기 — 제공자별 위협 규칙:
threatmap/analyzers/
├── aws.py # 22개 규칙 — S3, IAM, EC2, RDS, EKS, CloudTrail, KMS, Lambda
├── azure.py # 19개 규칙 — Storage, Key Vault, NSG, RBAC, AKS, ACR, SQL
├── gcp.py # 15개 규칙 — GCS, Firewall, Compute, Cloud SQL, GKE, IAM, KMS
└── kubernetes.py # 17개 규칙 — workloads, RBAC, network, secrets
MITRE ATT&CK 분석기 — MITRE 전술에 매핑된 11개 규칙:
PASTA 분석기 — 자산 중심 초점의 12개 규칙:
API:
/health, /version, /rules, /analyze, /analyze/file/graphql — Query(health, version, rules) 및 Mutation(analyze)각 규칙은 Resource 객체(소스 형식에 관계없이 정규화됨)를 수신하고 조건이 충족되면 Threat를 반환하는 함수입니다. 규칙은 일반 Python 조건문입니다. DSL, 정규식 엔진, 외부 규칙 세트 파일이 없습니다.
심각도는 악용 가능성과 피해 범위를 모두 반영합니다:
| 심각도 | 의미 |
|---|---|
| CRITICAL | 추가 사전 조건 없이 직접 악용 가능 (예: SSH가 0.0.0.0/0에 열려 있음, 와일드카드 IAM 정책, 익명에 대한 cluster-admin 바인딩) |
| HIGH | 한 단계 추가가 필요한 상당한 위험 (예: 공용 액세스가 있는 암호화되지 않은 RDS, EC2 인스턴스의 IMDSv1) |
| MEDIUM | 심층 방어 제어 누락 — 즉각적인 위험은 낮지만 보안 기준 위반 (예: 버전 관리 없음, 로깅 없음, 리소스 제한 없음) |
| LOW | 제한된 독립적 악용 가능성을 가진 모범 사례 격차 (예: Lambda가 VPC에 없음) |
publicly_accessible = true, Principal: "*")에서 실행됩니다.metadata_options 블록이 없으면 IMDSv1이 활성화된 것으로 간주, 이것이 AWS의 기본값이기 때문).(stride_category, resource_name, trigger_property)로 키가 지정되므로 동일한 논리적 문제가 여러 파일 형식에 나타나더라도 두 번 보고되지 않습니다.# .github/workflows/threat-model.yml
name: Threat Model
on: [pull_request]
jobs:
threatmap:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Install threatmap
run: pip install threatmap
- name: Run threat model scan
run: |
threatmap scan ./infra/ \
--format markdown \
--output threat-report.md \
--fail-on HIGH
- name: Upload threat report
if: always()
uses: actions/upload-artifact@v4
with:
name: threat-report
path: threat-report.md
--fail-on HIGH 플래그는 HIGH 또는 CRITICAL 위협이 발견되면 작업이 종료 코드 1로 종료되어 PR 병합을 차단합니다. 업로드된 아티팩트는 리뷰어가 풀 리퀘스트를 떠나지 않고 전체 보고서를 볼 수 있게 합니다.
| 제공자 | 규칙 |
|---|---|
| AWS (Terraform + CloudFormation) | 22 |
| Azure (Terraform) | 19 |
제공자별 적용 범주:
(S=스푸핑, T=변조, R=부인, I=정보 노출, D=서비스 거부, E=권한 상승)
테스트 실행:
pytest tests/ -v
커버리지로 실행:
pytest tests/ --cov=threatmap --cov-report=term-missing
threatmap/analyzers/<provider>.py에 규칙을 추가하세요tests/fixtures/에 픽스처를 추가하세요tests/test_analyzers.py에 어설션을 추가하세요| 형식 | 제공자 | 확장자 |
|---|
| Terraform HCL | AWS, Azure, GCP | .tf |
| CloudFormation | AWS | .yaml, .yml, .json |
| Kubernetes 매니페스트 | Kubernetes | .yaml, .yml |
| ID | 심각도 | STRIDE 범주 | 리소스 | 설명 |
|---|
| T-001 | 🔴 CRITICAL | Information Disclosure | AuditBucket | S3 버킷 'AuditBucket'에 공용 액세스 차단이 구성되지 않았습니다 — 버킷이 공개적으로 액세스 가능할 수 있습니다. |
| T-002 | 🔴 CRITICAL | Spoofing | WebSecurityGroup | 보안 그룹 'WebSecurityGroup'이 0.0.0.0/0에 SSH/RDP(포트 22/3389)를 노출합니다. |
| T-003 | 🔴 CRITICAL | Elevation of Privilege | app_contributor | 역할 할당 'app_contributor'이 권한 있는 역할 'Contributor'를 부여합니다. |
| T-006 | 🟠 HIGH | Information Disclosure | AuditBucket | S3 버킷 'AuditBucket'에 서버 측 암호화가 구성되지 않았습니다. |
| T-008 | 🟠 HIGH | Elevation of Privilege | api | Deployment 'api'의 컨테이너 'api'가 루트로 실행될 수 있습니다(runAsNonRoot=true 또는 runAsUser=0 없음). |
| T-011 | 🟠 HIGH | Elevation of Privilege | web | EC2 인스턴스 'web'이 IMDSv1을 허용합니다 — 메타데이터 서비스에 세션 토큰 없이 액세스 가능하여 SSRF 기반 자격 증명 도용을 가능하게 합니다. |
| GCP (Terraform) | 15 |
| Kubernetes | 17 |
| 합계 | 73 |
| 제공자 | S | T | R | I | D | E |
|---|
| AWS | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Azure | ✓ | ✓ | ✓ | ✓ | — | ✓ |
| GCP | ✓ | ✓ | ✓ | ✓ | — | ✓ |
| Kubernetes | ✓ | ✓ | — | ✓ | ✓ | ✓ |