Phần lớn lỗ hổng nghiêm trọng phát sinh từ giai đoạn thiết kế, không phải coding. Một threat model nhẹ, làm sớm, có owner — giá trị hơn nhiều một báo cáo pentest 100 trang sau khi go-live.
Threat model là gì?
Threat model là quá trình trả lời 4 câu hỏi của Adam Shostack:
- What are we working on? — Vẽ data flow diagram (DFD).
- What can go wrong? — Áp dụng STRIDE để liệt kê threat.
- What are we going to do about it? — Mitigation hoặc accept risk có người chịu trách nhiệm.
- Did we do a good job? — Review lại sau khi triển khai.
STRIDE trong một phút
| Threat | Vi phạm | Ví dụ |
|---|---|---|
| Spoofing | Authentication | Giả mạo user, token bị reuse |
| Tampering | Integrity | Sửa request, sửa data ở DB |
| Repudiation | Non-repudiation | Không có audit log đủ để chứng minh hành động |
| Information disclosure | Confidentiality | Lộ PII, lộ key qua log |
| Denial of service | Availability | Brute force, slowloris, expensive query |
| Elevation of privilege | Authorization | IDOR, escape sandbox, container break-out |
Vẽ DFD đúng cấp
Bốn loại element cần có trên DFD:
- External entity: user, third-party API.
- Process: service, function.
- Data store: DB, S3, queue.
- Data flow: mũi tên giữa các element.
Quan trọng nhất là trust boundary: ranh giới giữa các vùng có mức tin cậy khác nhau (Internet ↔ web tier, app ↔ DB, tenant A ↔ tenant B). Mỗi mũi tên cắt qua trust boundary là một điểm cần xác thực, validate, mã hoá.
Bắt đầu với DFD level 1 (1 service + dependencies trực tiếp). Đừng vẽ level 0 chung chung hoặc đi quá sâu xuống level 3 — sẽ tốn thời gian mà không thêm thông tin ra quyết định.
Áp dụng STRIDE trên từng element
Một mẹo thực dụng: với mỗi element trên DFD, hỏi 6 câu STRIDE. Không cần ép có threat ở mọi ô — bỏ qua nếu không hợp lý. Ghi vào bảng:
| Element | Threat | Mô tả | Mitigation | Owner | Severity |
| -------------- | ------ | ----------------------------------------- | ---------------------- | ----- | -------- |
| Login endpoint | S | Brute force account | Rate limit + MFA | @team | High |
| Login endpoint | I | Lộ user enum qua message lỗi | Generic error message | @team | Medium |
| Upload service | T | File replace race trên storage | Versioning + checksum | @team | Medium |
| Order DB | E | IDOR khi truy vấn /orders/{id} | Authz check theo owner | @team | High |
Chấm điểm rủi ro
Hai phương án phổ biến:
- CVSS v3.1/v4: chuẩn industry, dùng tốt cho vulnerability cụ thể, có vector chuẩn để chia sẻ.
- OWASP Risk Rating: đơn giản (Likelihood × Impact), dễ giải thích cho stakeholder không kỹ thuật.
Chọn 1 phương pháp thống nhất trong tổ chức và viết rõ trong handbook. Đừng để mỗi team tự chế thang điểm — sẽ không so sánh được.
Risk register là tài sản sống
Threat model không phải tài liệu một lần. Risk register cần:
- Có owner cho từng risk.
- Có deadline mitigation hoặc lý do accept.
- Được review mỗi quý hoặc khi có thay đổi kiến trúc lớn.
- Liên kết với issue tracker để mitigation có ticket thực sự.
Khi nào cần LINDDUN, PASTA?
Mặc định dùng STRIDE. Cân nhắc thêm:
- LINDDUN khi service xử lý nhiều PII/PHI và cần threat model về privacy (Linkability, Identifiability, Non-repudiation, Detectability, Disclosure, Unawareness, Non-compliance).
- PASTA khi cần threat model gắn với risk business chi tiết, có 7 stage formal — phù hợp cho hệ thống critical (banking, healthcare).
Kết luận
Threat modeling không phải là magic. Một buổi 60 phút với DFD level 1, STRIDE checklist và risk register đã đủ giúp một service tránh phần lớn lỗi thiết kế. Lặp lại định kỳ, có owner, gắn vào ADR — đó là cách biến threat model thành thói quen kỹ thuật, không phải sự kiện hàng năm.



