Threat Modeling for Beginners: How to Think Like an Attacker to Secure Your Systems

Threat modeling is the structured process of identifying potential threats to a system and designing mitigations before attackers find them. It’s one of the most valuable security practices that’s almost universally underused — especially in small and medium-sized organizations. This guide teaches you the fundamentals using the STRIDE methodology with practical examples.

Why Threat Model?

The goal of threat modeling is to answer four questions:

  1. What are we building?
  2. What can go wrong?
  3. What are we going to do about it?
  4. Did we do a good enough job?

Without threat modeling, security decisions are reactive — you fix problems after they’re exploited. Threat modeling makes security proactive.

STRIDE: The Threat Categories

Microsoft’s STRIDE framework categorizes threats into six types:

# STRIDE Threat Categories:
S - Spoofing Identity      → Impersonating a user or system component
T - Tampering with Data   → Modifying data in transit or at rest
R - Repudiation          → Denying an action occurred (no audit trail)
I - Information Disclosure → Exposing data to unauthorized parties
D - Denial of Service     → Disrupting availability
E - Elevation of Privilege → Gaining unauthorized permissions

Step-by-Step Threat Modeling Process

Step 1: Draw the Data Flow Diagram (DFD)

# Simple web application DFD:
# Components:
[User Browser] --> [Load Balancer] --> [Web Server] --> [App Server] --> [Database]
                                                   --> [Cache (Redis)]
                                                   --> [File Storage (S3)]

# Data flows to document:
# 1. User login (POST /api/auth) - username + password
# 2. API requests (GET/POST /api/data) - with JWT token
# 3. File uploads (POST /api/upload) - binary data
# 4. Database queries (SQL) - sensitive customer data
# 5. Admin access (GET /admin) - privileged operations

# Mark trust boundaries:
# Internet / DMZ boundary (between user and load balancer)
# DMZ / Internal network boundary (between LB and app servers)
# App server / Database boundary (internal, privileged)

Step 2: Apply STRIDE to Each Component

# Example: Analyze the Authentication API endpoint

# SPOOFING threats:
# - Attacker submits another user's credentials
# Mitigation: Strong password policy + MFA + account lockout

# TAMPERING threats:  
# - JWT token modified to elevate privileges
# Mitigation: Sign JWTs with strong secret, verify signature on every request
# - SQL injection to modify database
# Mitigation: Parameterized queries

# REPUDIATION threats:
# - User denies making a request ("I didn't do that!")
# Mitigation: Audit logs with timestamp, user ID, IP, action

# INFORMATION DISCLOSURE threats:
# - Password exposed in logs
# Mitigation: Never log passwords, mask sensitive fields
# - Error messages reveal database structure
# Mitigation: Generic error messages in production

# DENIAL OF SERVICE threats:
# - Brute force login attempts
# Mitigation: Rate limiting, CAPTCHA, account lockout
# - Large file uploads consuming server resources
# Mitigation: File size limits, async processing

# ELEVATION OF PRIVILEGE threats:
# - Regular user accessing admin endpoints
# Mitigation: RBAC authorization check on EVERY endpoint

Step 3: Prioritize with DREAD Scoring

# DREAD scores each threat 1-10:
# D - Damage: How bad is the breach?
# R - Reproducibility: How easily can it be repeated?
# E - Exploitability: How much skill/effort to exploit?
# A - Affected users: How many users impacted?
# D - Discoverability: How easily can attackers find this?

# Example scoring — JWT not validated on admin endpoint:
# Damage:         10 (attacker becomes admin)
# Reproducibility: 9 (trivial to repeat)
# Exploitability:  9 (just modify JWT payload, no signature check)
# Affected users: 10 (all users' data accessible)
# Discoverability: 7 (tools like Burp Suite find this automatically)
# DREAD Score: (10+9+9+10+7)/5 = 9.0 — CRITICAL, fix immediately

# Example scoring — verbose error messages:
# Damage:          3 (helps attacker but not directly exploitable)
# Reproducibility: 9 (always reproducible)
# Exploitability:  8 (just trigger an error)
# Affected users:  2 (one attacker at a time)
# Discoverability: 7 (scanners find these)
# DREAD Score: (3+9+8+2+7)/5 = 5.8 — Medium, fix in next sprint

Free Threat Modeling Tools

# Microsoft Threat Modeling Tool (free):
# Download: microsoft.com/en-us/securityengineering/sdl/threatmodeling
# - Creates DFDs visually
# - Automatically generates STRIDE threats for each component
# - Generates reports

# OWASP Threat Dragon (open source):
# Install: npm install -g threat-dragon
# threat-dragon  # Launches in browser
# - Web-based DFD editor
# - Export to JSON/PDF
# - GitHub integration

# pytm (Python threat modeling library):
pip install pytm

# Example pytm script:
from pytm import TM, Server, Datastore, Dataflow, Boundary, Actor

tm = TM("My Web App")
internet = Boundary("Internet")
dmz = Boundary("DMZ")

user = Actor("User", inBoundary=internet)
webapp = Server("Web App", inBoundary=dmz, isHardened=True)
db = Datastore("Database")

user_to_app = Dataflow(user, webapp, "HTTP Request", protocol="HTTPS")
app_to_db = Dataflow(webapp, db, "SQL Query", protocol="SQL")

tm.process()  # Generates threat report

When to Threat Model

  • New application design — before a single line of code is written
  • Architecture changes — adding new components or integrations
  • Annually — review and update existing threat models
  • After incidents — add new threats discovered through breaches

Wrap Up

Threat modeling doesn’t require expensive consultants or weeks of time. A one-hour whiteboard session using STRIDE can identify dozens of security risks in a new feature before code is written. Build it into your development process and you’ll catch the kinds of vulnerabilities that would otherwise make headlines.