Education › Security › Stage 1: Foundations

Threat modelling & the attacker mindset

Assets, attackers, attack surfaces and STRIDE; how to think about what can go wrong before it does.

Beginner ~30 min read Module 1 of 16

Security work that starts with a tool list ends with a long bill and the same breaches. Security work that starts with a question ends better: what are we protecting, from whom, and how would they actually get in? Threat modelling is the habit of asking that question early and writing the answers down, so that every later control (a firewall rule, a code review, an alert) exists for a reason you can name. This module gives you the attacker's way of looking at a system and a lightweight method you can run in an hour on a whiteboard.

After this module you can
  • Describe a system as assets, entry points, trust boundaries and data flows
  • Enumerate threats with STRIDE and rank them by likelihood and impact
  • Explain the attack chain from initial access to impact, and where defenders can break it
  • Turn a threat model into concrete, testable controls and accepted risks
  • Run a one-hour threat modelling session for a real feature or service

Think like the attacker, plan like the defender

Attackers are not magicians. They are people with a goal (money, data, access, disruption), a budget of time and skill, and a preference for the easiest path. A threat model is a structured description of your system from that point of view: what is valuable in it, where someone from outside can touch it, and which paths lead from touching it to getting the valuable thing. Defenders who skip this step protect the wrong things beautifully.

Four questions drive every threat model. They come from the threat modelling manifesto and they fit on a sticky note:

  1. What are we working on? Draw the system: components, data stores, external services, the people and machines that call it.
  2. What can go wrong? Enumerate threats systematically, not by brainstorming whatever comes to mind first.
  3. What are we going to do about it? For each threat that matters: mitigate, eliminate, transfer, or accept — and write down which.
  4. Did we do a good job? Check the controls exist, test them, and revisit the model when the system changes.
Note

A threat model is a living document, not a compliance artefact. The useful version is one page per service, updated when a new entry point, data type or dependency appears.

Draw the system: assets, entry points, trust boundaries

Start with a data flow diagram: boxes for processes, cylinders for data stores, arrows for data flows, and stick figures for external entities (users, third-party APIs, other teams' services). Then draw the trust boundaries: dotted lines where the level of trust changes — the internet edge, the boundary between a web tier and a database, the line between a user's browser and your API, the line between one tenant's data and another's. Almost every interesting threat lives on a boundary crossing.

Next, list the assets, meaning the things an attacker would want or the things whose loss would hurt: customer records, credentials and tokens, the ability to run code on your servers, payment flows, availability of the service itself, and your reputation. Rank them. If you cannot say which asset matters most, you cannot prioritise anything downstream.

Finally, mark the entry points: every place input arrives from a less-trusted side of a boundary. Public HTTP endpoints, webhooks, file uploads, message queues, admin consoles, SSH, the CI pipeline, and the dependency manifest are all entry points. The attack surface is the sum of them; the smaller and better-known it is, the easier the rest of this work becomes.

INTERNETEDGEAPPLICATIONDATAE1 /ordersE1 tooE2 webhookjobsscoped queriesreads keyE4 deploysUserbrowser, JWTAttackersame doorPayment providerwebhooksLoad balancerTLS, rate limitsAPIauthn + authzWorkerruns jobsBuild pipelineimages, depsPostgrescustomer PIISecrets storeAPI keys
A data flow diagram with its trust boundaries drawn in: every arrow that crosses a dotted line is an entry point to walk through STRIDE, and the attacker's shortest path runs through the least-trusted crossing.
A minimal written model for a small web service, before any diagramming tool.
text
SYSTEM: order-api (public REST API + worker + Postgres)

ASSETS (ranked)
  1. customer PII in Postgres            (breach = legal + reputation)
  2. payment provider API key            (theft = fraud)
  3. ability to run code on the hosts    (foothold into everything else)
  4. availability during business hours

ENTRY POINTS
  E1  POST /orders, GET /orders/{id}     internet -> api        (auth: user JWT)
  E2  POST /webhooks/payment             payment provider -> api (auth: HMAC signature)
  E3  admin UI on :8443                  office VPN -> api      (auth: SSO + MFA)
  E4  container image + pip dependencies build pipeline -> hosts
  E5  SSH to hosts                       ops laptops -> hosts   (auth: keys)

TRUST BOUNDARIES
  internet | load balancer | api pods | postgres
  build pipeline | production registry

Enumerate threats with STRIDE

Brainstorming produces the threats you already fear. STRIDE produces the ones you forgot, because you walk every data flow and ask six fixed questions. Each letter is a category of threat, and each maps to the security property it violates:

ThreatViolatesExample on order-api
SpoofingAuthenticationA forged webhook claims a payment succeeded
TamperingIntegrityOrder total modified in the request body after client-side validation
RepudiationNon-repudiationAn admin deletes records and there is no log of who did it
Information disclosureConfidentialityStack traces with database details returned on error
Denial of serviceAvailabilityUnbounded page size on GET /orders exhausts the database
Elevation of privilegeAuthorisationA user reads another user's order by changing the id

Apply STRIDE per element: for each entry point and each boundary crossing, ask all six questions. A five-endpoint API with three boundaries yields perhaps forty candidate threats in half an hour. That is fine; the next step is ranking, not fixing everything.

Rank each threat by likelihood (how easy is it, how motivated is the attacker, is it already being exploited in the wild) and impact (which asset, how badly). A simple high/medium/low on each axis is enough; the point is to compare, not to compute. Anything high on both goes to the top of the backlog with a named owner.

Tip

For each threat write one sentence in the form: "An attacker with X access can do Y, causing Z." If you cannot fill in all three, it is not yet a threat, it is a worry.

The attack chain and where to break it

Real intrusions are chains, not single events. A typical sequence: reconnaissance (finding your domains, exposed services, employee emails), initial access (phishing, an exposed credential, an unpatched service), execution and persistence (running code and surviving a reboot), privilege escalation, lateral movement to more valuable systems, collection of data, and finally exfiltration or impact (ransomware, fraud, destruction). The public catalogue of these techniques is the MITRE ATT&CK framework; defenders use it as a checklist of what attackers actually do rather than what they theoretically could.

Chains are good news. Breaking any link stops the attack, and the cheapest links to break are usually early ones: fewer exposed services, credentials that expire, MFA on everything that faces the internet, patches applied on a schedule. A defence-in-depth design assumes the first control will fail and places another behind it: the web application firewall does not stop every injection, so the database user also has no permission to read other tables, so the network also blocks egress from the database host.

  • Reduce the surface: every service you do not expose is a threat category you do not have.
  • Assume breach: design so that one compromised component (a pod, a laptop, a key) does not give away everything.
  • Make lateral movement noisy: segmentation and logging turn a quiet intrusion into an alert.
  • Shorten credential lifetimes: a stolen token that expires in an hour is a much smaller problem than a key from 2021.
Watch out

The most common initial access today is not a clever exploit. It is a leaked credential, a phished login without MFA, or an internet-facing service that missed a patch. Threat models that only list exotic attacks miss the door that is actually open.

From threats to controls

Each ranked threat gets one of four responses. Mitigate: add a control that reduces likelihood or impact (validate the webhook signature, add rate limits, log admin actions). Eliminate: remove the feature or flow that creates the threat (drop the unauthenticated export endpoint nobody uses). Transfer: make it someone else's problem contractually or technically (use the payment provider's hosted checkout so card numbers never touch your system). Accept: decide the risk is tolerable, write down why and who agreed, and set a date to revisit.

A good control is specific and testable. "Improve input validation" is not a control; "reject page_size above 100 with HTTP 400, covered by test test_orders_page_size_cap" is. Record each control next to the threat it addresses, so that six months later someone can ask why that check exists and get an answer.

Threat register entries: the format that survives contact with a backlog.
text
T-07  E1  Elevation: user reads another user's order by guessing the id
      Likelihood HIGH  Impact HIGH  -> MITIGATE
      Control: every /orders/{id} query is scoped by the caller's user_id
      Test:    test_get_order_other_user_returns_404
      Owner:   api team   Status: done 2026-03

T-12  E2  Spoofing: forged payment webhook marks an order as paid
      Likelihood MED   Impact HIGH  -> MITIGATE
      Control: verify HMAC signature with the provider secret; reject if > 5 min old
      Test:    test_webhook_bad_signature_rejected

T-19  E5  Information disclosure: SSH keys on laptops without passphrases
      Likelihood MED   Impact MED   -> ACCEPT until SSM/SSO rollout (Q3), owner: platform lead

Close the loop with the fourth question. Controls drift: a test gets skipped, a firewall rule gets widened during an incident and never narrowed. Revisit the model on a schedule and whenever the diagram changes: new entry point, new data class, new third-party integration. Later modules in this track are, in effect, the standard controls for the most common threats — identity, cryptography, hardening, supply chain, detection and response.

Hands-on practice

Threat-model a service you know in one hour

  1. Pick a real service you have worked on (or the API from the DevOps track's capstone). On paper or a whiteboard draw its data flow diagram: processes, stores, external entities, arrows.
  2. Draw the trust boundaries as dotted lines. There should be at least three: internet edge, between tiers, and between your build system and production.
  3. List the assets and rank them. Force yourself to put one thing at the top.
  4. List every entry point in the format Ex method/path from -> to (auth: ...). Include non-HTTP ones: queues, uploads, SSH, CI, dependencies.
  5. Walk each entry point through the six STRIDE questions and write one-sentence threats: "An attacker with X can do Y, causing Z." Aim for at least fifteen.
  6. Rate each threat high/medium/low for likelihood and impact. Sort. Take the top five.
  7. For each of the top five, write the response (mitigate/eliminate/transfer/accept), a specific control, and the name of a test that would prove the control works.
  8. Save the result as THREAT_MODEL.md in the service's repository and open a pull request so it gets reviewed like code.
Cheat sheet

Threat modelling & the attacker mindset — at a glance

Main things to focus on

  • Four questions: what are we building, what can go wrong, what will we do, did we do a good job
  • Threats live on trust boundaries: draw them before enumerating anything
  • STRIDE per entry point beats brainstorming: spoofing, tampering, repudiation, information disclosure, denial of service, elevation
  • A threat is a sentence: attacker with X can do Y causing Z
  • Rank by likelihood and impact; fix the top of the list, write down what you accept
  • Attacks are chains; break early links (exposure, credentials, patches) cheaply
  • Controls must be specific and testable, and recorded next to the threat

Modelling vocabulary

assetSomething an attacker wants or whose loss hurts; rank them
entry pointWhere input crosses from a less-trusted side; the attack surface is their sum
trust boundaryLine where trust level changes; most threats are boundary crossings
data flow diagramProcesses, stores, flows, external entities, boundaries
threat registerNumbered threats with rating, response, control, test, owner

STRIDE

Spoofing -> authenticationPretending to be a user, service or message source
Tampering -> integrityModifying data or code in transit, at rest, or in the build
Repudiation -> non-repudiationActing without a trustworthy record of who did it
Information disclosure -> confidentialityData reaching someone who should not have it
Denial of service -> availabilityExhausting a resource: CPU, connections, disk, money
Elevation of privilege -> authorisationDoing something the identity is not allowed to do

Rating and response

likelihood x impactHigh/medium/low on each; sort, do not compute
mitigateAdd a control that lowers likelihood or impact
eliminateRemove the feature or flow that creates the threat
transferHosted checkout, insurance, a vendor's control instead of yours
acceptWritten rationale, named approver, revisit date

Attack chain (ATT&CK stages)

recon -> initial accessExposed services, leaked credentials, phishing, unpatched software
execution -> persistenceRun code, survive reboots (cron, services, tokens)
privilege escalation -> lateral movementRoot on one box, then the next box
collection -> exfiltration / impactGather data, move it out, or destroy and extort
break the chain earlyMFA, short-lived credentials, patching, smaller surface

One-page threat model template

SYSTEM / ASSETS (ranked) / ENTRY POINTS / BOUNDARIESThe description, one screen long
T-nn Ex Category: sentenceOne threat per line, referencing the entry point
Control + Test + Owner + StatusWhat proves the threat is handled
Revisit: on diagram change or quarterlyKeep it alive

Common pitfalls

  • Modelling the architecture diagram from the wiki instead of the system as deployed, with its forgotten admin port and test endpoint.
  • Listing threats without an attacker, an action and a consequence, so nothing can be ranked or tested.
  • Spending the session on exotic attacks while phishing, leaked keys and missing patches remain the likely door.
  • Writing "improve validation" as a control; controls need a specific rule and a test.
  • Treating the document as done: the model must change when a new entry point or data type appears.
  • Accepting risks silently; an accepted risk without an owner and a date is an unmanaged risk.
Quiz

Check your understanding

5 questions · 4 to pass · answers are explained as you go. Your best score is saved on this device only.

Progress and quiz scores are saved in this browser only. Back up or restore on the hub.

Was this lesson useful? Tell me what to improve →