The three previous lessons have given you the vocabulary, the catalogue of threats and the design principles. All of that is inapplicable until you answer a prosaic question: what exactly does Nimbus Reservas have? You cannot protect what you do not know exists, you cannot reduce a surface you have not measured, and you cannot prioritise without knowing who might attack you and with what means. This lesson closes the module by building those three pieces — asset inventory, attack surface and threat actors — and joins them with a first analysis tool: STRIDE applied to a data flow diagram of the Nimbus architecture itself. By the end you will have the complete picture of the terrain we will be working on across the remaining six modules.

Contents

  1. What an asset is and why the inventory is control number one
  2. Types of asset and the Nimbus Reservas inventory
  3. Information classification: public, internal, confidential, restricted
  4. Discovering what you already have: technical inventory with system tools
  5. The attack surface and its five dimensions
  6. Techniques for reducing the surface
  7. Threat actors: who, why and with what capability
  8. A practical introduction to threat modelling with STRIDE
  9. Closing the module

  1. What an asset is and why the inventory is control number one

An asset is any element that has value for the organisation and that therefore deserves protection.

The key word is value, and value is not only financial. A log file is not worth money, but without it Nimbus cannot investigate an incident or prove what happened: its value is evidential. Reputation appears on no balance sheet, but it is what makes a clinic renew the contract.

Why the inventory comes first in every serious list of controls:

  • You cannot protect what you do not know exists. The test server Iván spun up eight months ago "for a demo", with a copy of real data and unpatched ever since, is on no list. It is exactly what an automated scan finds.
  • You cannot prioritise without criticality. If every system looks equally important, they all get protected equally badly.
  • You cannot respond to an incident without knowing what is there. The first question in a breach is "what data could they have accessed?". Without an inventory, the honest answer is "we don't know", which in front of a customer or a regulator is the worst possible answer.
  • You cannot apply any patch with confidence. When the CVE from lesson 01-02 comes out, the question "does it affect us?" is only answered quickly with an inventory.

An uncomfortable fact from the industry: in most significant SME breaches, the entry point was an asset the organisation had forgotten it had. An old subdomain, a test environment, a former employee's account, a disconnected integration with a live credential.

The four fields that turn a list into a useful inventory:

Field Why it is essential
Owner With no responsible person, nobody decides and nobody updates. It is the field most often omitted and the most important
Criticality Determines how much is invested in protecting it and in what order it is recovered after a disaster
Classification Determines how it is handled: encryption, who accesses it, whether it may leave the company
Dependencies What it depends on and what depends on it; without this the impact of its outage cannot be assessed

  1. Types of asset and the Nimbus Reservas inventory

Assets are not just servers. A practical classification distinguishes six types:

flowchart TD
    A[Assets] --> INF["INFORMATION\ndatabases, backups,\nsource code, contracts, logs"]
    A --> SW["SOFTWARE\nAPI, SPA, mobile app,\nthird-party SaaS, images"]
    A --> HW["HARDWARE\nlaptops, phones,\nrouter, office NAS"]
    A --> SER["SERVICES\ncloud, DNS, e-mail,\npayment gateway, connectivity"]
    A --> PER["PEOPLE\nknowledge, credentials,\ndecision-making capacity"]
    A --> INT["INTANGIBLES\nreputation, customer\ntrust, brand"]

The last two are systematically forgotten and they are decisive. Lucía is an asset: she is the only person who knows how to restore the complete infrastructure. If Lucía leaves or is unreachable during an incident, Nimbus has an availability problem as real as a server going down. And reputation is an asset: most of the financial damage of a breach in a SaaS business does not come from the fine, it comes from the customers who do not renew.

2.1 Nimbus Reservas asset inventory (extract)

ID Asset Type Owner Criticality Classification Depends on
A-01 Production PostgreSQL database Information Lucía Critical Restricted A-04, A-05
A-02 Bucket nimbus-adjuntos-prod (scanned reports) Information Lucía Critical Restricted A-05
A-03 Bucket nimbus-backups-prod (backups) Information Lucía Critical Restricted A-05
A-04 REST API (FastAPI, containers) Software Iván Critical Internal A-01, A-05, A-10
A-05 Cloud provider account Service Lucía Critical Restricted
A-06 Code repository and CI/CD (GitHub Actions) Software Marta Critical Confidential A-13
A-07 Web SPA + mobile app Software Iván High Public (binary) A-04
A-08 Domain and DNS nimbusreservas.example Service Marta Critical Internal
A-09 TLS certificates Information Lucía High Confidential A-08
A-10 Application secrets (API keys, DB credentials) Information Lucía Critical Restricted A-05
A-11 Transactional e-mail provider Service Rubén Medium Internal
A-12 Payment gateway (tokens) Service Sara High Confidential
A-13 Team identity accounts (SSO/e-mail) Information Marta Critical Restricted
A-14 40 corporate laptops Hardware Lucía High Internal (they contain confidential data) A-13
A-15 Corporate and guest wifi (Valencia office) Service Lucía Medium Internal
A-16 HR data: payroll and contracts Information Sara High Restricted A-13
A-17 Operational documentation and runbooks Information Lucía High Confidential A-06
A-18 Audit records and logs Information Lucía High Confidential A-05
A-19 Systems consultancy remote access Service Marta Critical Restricted A-13
A-20 Reputation and customer trust Intangible Marta Critical All of them
A-21 Lucía's operational knowledge (sole sysadmin) People Marta High A-17
A-22 Pre-production environment Software Iván Medium To be reviewed A-05

Three observations about this table that are worth more than the table itself:

  1. A-05 (the cloud provider account) is the asset almost every other one depends on. Compromising that account cancels most of the controls simultaneously. In the language of lesson 01-03: it is the point that brings down several defensive layers at once, and that is why it deserves disproportionate protection.
  2. A-19 (the consultancy's access) has critical criticality and Marta as owner, not Lucía. That is deliberate: the risk of that asset is contractual and governance-related, not technical. It is developed in 04-04.
  3. A-22 appears with a classification of "to be reviewed". That is honest and it is what usually happens: nobody is sure whether pre-production holds real data. An inventory that reflects the doubts is more useful than one that hides them; that cell is, in fact, the first security task of the week.

How an inventory is kept alive. The inventory is not a document, it is a process. Three practical rules: (a) define the infrastructure as code, so that the repository is the inventory; (b) require an owner and a classification for any new asset from day one; (c) a short quarterly review looking specifically for what is surplus — accounts, environments, integrations and subdomains that are no longer in use.


  1. Information classification: public, internal, confidential, restricted

Classifying means deciding how much protection each piece of data deserves. Without classification, either everything gets maximum protection (expensive, unsustainable and counter-productive) or nothing gets it consistently.

Four levels are enough for a company like Nimbus. More levels do not add precision: they add confusion.

Level Definition Impact if disclosed Examples in Nimbus Handling rules
Public Intended for open distribution None Marketing website, prices, API documentation, job adverts No restriction; only integrity control (that nobody alters it)
Internal For general use inside the company Low: nuisance, minor advantage to a competitor Org chart, internal procedures, calendar, ordinary meeting minutes Not published; shared with third parties only under NDA
Confidential Its disclosure causes significant harm Medium-high: competitive loss, breach of contract Source code, detailed architecture, customer contracts, financial reports, runbooks Access on a need-to-know basis; encrypted in transit and at rest; does not leave without authorisation
Restricted Maximum protection; serious, legal or personal harm High: penalty, complaint, harm to individuals End customer data (including data that reveals health information), payroll, secrets and keys, backups Named, logged access; mandatory encryption; MFA; copying to local machines forbidden; defined retention

3.1 The three rules that prevent most classification mistakes

Rule 1: classification is inherited upwards. A file containing a single restricted item is restricted. An aggregate report mixing internal and confidential data is confidential. Sets take the classification of their most sensitive element.

Rule 2: aggregation can raise the level. The history of a single appointment is a restricted item. The complete table of 400,000 physiotherapy clinic appointments is qualitatively worse: it does not merely add up, it becomes a map of people with medical complaints. That change of nature is what makes mass exports deserve controls of their own (you designed them in exercise 3 of the previous lesson).

Rule 3: context defines sensitivity. "Ana Ruiz, 15/03, 17:00" looks innocuous. In the diary of a rehabilitation clinic it indirectly reveals health data. Nimbus cannot say "I only manage diaries": it manages diaries whose content is, by context, sensitive.

Note on legal implications: the category of "data that reveals health information" and the associated obligations (lawful bases, reinforced measures, impact assessments) have a specific regulatory treatment that is addressed in lesson 06-03. The concrete categorisation of your organisation's data must be validated with your compliance lead or with a legal professional.

3.2 Classifying also means deciding when to delete

An information asset that is no longer needed stops being an asset and becomes purely a risk liability. The CSVs Rubén generated a year ago, the database dumps on Iván's laptop, the five-year-old backups: they add zero value and all the risk. The retention policy — how long each thing is kept and when it is destroyed — is part of classification, not an appendix.


  1. Discovering what you already have: technical inventory with system tools

The documented inventory is always checked against reality, because reality always holds surprises. Let us start with asset A-01: the database server.

Important: every command in this lesson is run against systems Nimbus owns, with authorisation. Scanning somebody else's systems without express permission is illegal; the ethics and legal framework of these activities are covered in 06-06.

4.1 What is listening on the network

sudo ss -tulpn

Anatomy of the command, option by option:

Option What it does
ss socket statistics: shows the system's network sockets (the modern replacement for netstat)
-t TCP sockets only
-u Also includes UDP
-l Only those in the listening state, that is, waiting for connections
-p Shows the process that owns each socket (requires privileges)
-n Numeric: does not resolve port or host names; faster and with no DNS surprises

Output on the Nimbus database server:

Netid  State   Recv-Q  Send-Q   Local Address:Port   Peer Address:Port  Process
tcp    LISTEN  0       4096         127.0.0.1:5432        0.0.0.0:*      users:(("postgres",pid=812,fd=7))
tcp    LISTEN  0       4096       10.0.2.15:5432          0.0.0.0:*      users:(("postgres",pid=812,fd=7))
tcp    LISTEN  0       128            0.0.0.0:22          0.0.0.0:*      users:(("sshd",pid=640,fd=3))
tcp    LISTEN  0       511            0.0.0.0:9100        0.0.0.0:*      users:(("node_exporter",pid=1104,fd=3))
tcp    LISTEN  0       511            0.0.0.0:8000        0.0.0.0:*      users:(("python",pid=2201,fd=6))
udp    UNCONN  0       0            127.0.0.53:53         0.0.0.0:*      users:(("systemd-resolve",pid=402,fd=12))

How to read this, line by line:

  • Lines 1 and 2 (postgres, port 5432): it listens on 127.0.0.1 (the machine itself only) and on 10.0.2.15 (the private VPC IP). This is correct: 0.0.0.0 does not appear, so it is not listening on public interfaces. Compare it with the finding in lesson 01-02, where it was.
  • Line 3 (sshd, port 22): it listens on 0.0.0.0, that is, on all interfaces. Here you have to look at the second layer: even if the system listens on all of them, the provider's security group can restrict the source. If it does not, this is a finding: administrative access should only arrive via a bastion host or a VPN.
  • Line 4 (node_exporter, port 9100): monitoring metrics, listening on all interfaces. It exposes detailed system information with no authentication. A typical and very frequent finding: it is installed for monitoring and nobody restricts it.
  • Line 5 (python, port 8000): what is a Python process doing listening on the database server? This is exactly the kind of surprise that justifies the exercise. It could be an old demo script, a forgotten development server or something worse. It requires immediate investigation.
  • Line 6 (systemd-resolve, port 53 on 127.0.0.53): the local DNS resolver. Local only: correct.

The golden rule for reading this output: look at the local address first, not at the port. 127.0.0.1 is local only (no exposure). A private IP (10.x, 192.168.x, 172.16-31.x) is internal exposure. 0.0.0.0 or :: means all interfaces, and that is where the work begins.

4.2 Investigating the suspicious process

# What process 2201 is and how long it has been running
ps -p 2201 -o pid,user,etime,cmd
  PID USER      ELAPSED CMD
 2201 ivan     94-06:12 python3 -m http.server 8000 --directory /var/tmp/demo

Translation: Iván spun up a static HTTP server on the day of a demo and it has been running for 94 days, serving the contents of /var/tmp/demo to anybody who reaches port 8000. It is an uninventoried asset, with no declared owner, unpatched and with unknown content. In lesson 01-02 we would call it a configuration vulnerability; here it is what illustrates why the inventory is control number one.

4.3 Cross-checking with the provider's layer

The system is only half the story. The other half is the provider's firewall:

# Inbound rules of the database server's security group
aws ec2 describe-security-groups --group-ids sg-0a1b2c3d \
  --query "SecurityGroups[0].IpPermissions[].{Port:FromPort,Source:IpRanges[].CidrIp}" \
  --output table
-------------------------------
|   Port   |      Source       |
-------------------------------
|  22      |  0.0.0.0/0        |   <-- SSH open to the whole Internet
|  5432    |  10.0.0.0/16      |   <-- correct: the VPC only
|  9100    |  10.0.0.0/16      |   <-- correct
-------------------------------

The complete diagnosis only appears when you cross the two layers. Port 5432 was listening on the private IP and is also restricted to the VPC: two correct layers. Port 22, by contrast, listens on all interfaces and is open to 0.0.0.0/0: any bot on the Internet can try to authenticate against the SSH of the Nimbus database. That is a high-priority finding.

Specialised discovery and scanning tools are covered in 05-01 and 05-03; what matters here is the method: look at your own systems first, with what you already have installed.


  1. The attack surface and its five dimensions

The attack surface is the set of all the points through which an attacker could try to get in, extract data or affect the system.

It is a measurable and reducible property, and that is the good news: unlike threats, the surface is under your control. Every point you eliminate is a point that never has to be defended, monitored or patched again.

flowchart TD
    SA[Nimbus attack surface]
    SA --> RED["1. NETWORK\nPorts, public IPs, subdomains,\nVPN, wifi, exposed endpoints"]
    SA --> SW["2. SOFTWARE AND APIS\nEndpoints, parameters, dependencies,\nimages, forms, uploads"]
    SA --> HUM["3. HUMAN\n38 employees, e-mail, phones,\npublic profiles, support"]
    SA --> FIS["4. PHYSICAL\nOffice, 40 laptops, phones,\nUSB, paper, guest wifi"]
    SA --> CAD["5. SUPPLY CHAIN\nConsultancy, gateway, e-mail,\nlibraries, CI/CD actions"]

5.1 The five dimensions at Nimbus

Dimension What makes it up at Nimbus Most exposed point
Network Public IP of the load balancer, domain and subdomains, VPN, corporate and guest wifi, open ports A forgotten subdomain pointing at a service that no longer exists (subdomain takeover risk)
Software and APIs ~120 API endpoints, the parameters of each one, attachment uploads, Python dependencies, container images, the SPA and the mobile app File upload: it accepts arbitrary content from external users
Human 38 employees with corporate e-mail, Rubén handling tickets all day, public profiles on professional networks Support: it receives messages from strangers and has access to customer data
Physical The Valencia office, 40 laptops (half of them off site), phones, USB ports, printed documents, guest wifi The 19 remote laptops, in cafés, on trains and at home
Supply chain Consultancy with remote access, payment gateway, e-mail provider, ~180 transitive Python dependencies, third-party actions in the CI/CD The consultancy's permanent privileged access

5.2 Two clarifications that change how it is measured

The surface is not static: it breathes. Every deployment by Iván can add endpoints. Every hire adds a person. Every new integration adds a third party. That is why it is measured continually and not once a year.

Exposed surface ≠ total surface. Three things need distinguishing:

  • External surface: what is reachable from the Internet without credentials. It is the most urgent, because anybody in the world can touch it.
  • Authenticated surface: what is reachable with a valid account (including a free trial account, if there is one).
  • Internal surface: what is reachable after the first compromise. This is what determines how far an incident spreads.

Nimbus tends to look only at the first. But remember the "assume breach" principle from the previous lesson: the internal surface is what decides whether a compromised laptop ends up as an anecdote or as ransomware across the whole infrastructure.


  1. Techniques for reducing the surface

Reducing the surface is, by a wide margin, the cheapest way of improving security: what does not exist cannot be attacked, does not have to be patched, does not have to be monitored and does not turn up in the next audit.

Technique What it consists of Concrete application at Nimbus
Eliminate Remove what is not used Shut down the http.server on port 8000; delete the 3 subdomains from old campaigns; uninstall packages from decommissioned services
Close Restrict access to what is used SSH only from the bastion host; node_exporter only from the monitoring network
Consolidate Fewer different components doing the same thing A single identity provider instead of local accounts per system
Isolate Separate so that a compromise does not spread Separate cloud accounts for production and pre-production; guest network with no access to the internal one
Minimise Reduce the content and the privileges of each piece Minimal container images with no shell and no tools; non-root user in the containers
Hide what is unnecessary Do not give information away (as an additional layer, never the only one) Remove version headers, generic error messages that do not reveal the stack
Shorten the lifetime Let what exists exist for a short time Signed URLs lasting 2 minutes; short-lived credentials; temporary environments that destroy themselves

6.1 A worked example: the API container image

# === BEFORE: enormous surface ===
FROM python:3.12                 # ~1 GB, includes compilers, git, a full shell
COPY . /app
RUN pip install -r requirements.txt
CMD ["uvicorn", "main:app", "--host", "0.0.0.0"]
# Runs as root. If anyone manages to execute code, they get a complete system.
# === AFTER: minimised surface ===
FROM python:3.12-slim AS build
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir --target /deps -r requirements.txt

FROM gcr.io/distroless/python3-debian12          # no shell, no package manager, no utilities
COPY --from=build /deps /deps
COPY ./app /app
ENV PYTHONPATH=/deps
USER 10001                                        # unprivileged user, not root
EXPOSE 8000
ENTRYPOINT ["python", "-m", "uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]

What has been reduced and why it matters:

  • A two-stage build: the compilers and the installation tools stay in the first stage and never reach production. An attacker cannot compile anything.
  • A distroless image: there is no sh, no bash, no curl, no apt. Many post-exploitation techniques assume a shell is available; here, quite simply, there is not one.
  • USER 10001: the process does not run as root. Arbitrary code execution does not grant control of the container.
  • A valuable side effect: fewer packages means fewer CVEs to review every week. Reducing the surface also reduces the maintenance workload.

The details of container security are developed in 05-07; here it is enough to see the principle in action.


  1. Threat actors: who, why and with what capability

A threat actor is whoever turns a threat into reality. Knowing them matters because motivation determines the objective and capability determines how far they can go — and both decide where you invest.

Actor Motivation Capability Typical objective Relevant to Nimbus?
Opportunist / script kiddie Curiosity, reputation, practice; often automated with no chosen target Low: public tools, known exploits, mass scanning Whatever is open and unpatched, no matter whose it is Very high. It is 90% of what Nimbus will see
Organised crime Money: ransomware, fraud, data sales Medium-high: purchased initial access, commercial tooling, persistence Companies able to pay and with low tolerance for downtime High. An SME that cannot afford downtime is a profitable target
Insider (malicious, negligent or compromised) Revenge, money, haste, error High by definition: they already have legitimate access Data they can already touch; they can take it without "getting in" High. Including the external consultancy
Hacktivist Ideology, protest, visibility Low-medium: DDoS, website defacement, leaks Organisations with a public profile in a conflict Low: Nimbus has no political profile
Competitor Commercial advantage: customer base, prices, technology Variable; often through insiders or social engineering rather than technical means Commercial and product information Medium, above all via former employees
State-sponsored group (APT) Espionage, geopolitics, pre-positioning Very high: 0-days, resources, months of stealth Critical infrastructure, defence, major technology firms, supply chains Low as a direct target; not nil as collateral damage

7.1 Why Nimbus is affected above all by opportunistic attacks

This is the most important point in this section, because it corrects the most expensive mental error in an SME: "nobody is going to attack us, we're not interesting".

The premise is false because the opportunistic attacker does not choose victims: they find systems. The process is entirely automated:

flowchart LR
    A["Bot scans entire\nInternet ranges"] --> B["Finds an exposed,\nout-of-date service"]
    B --> C["Tries public exploits\nand known credentials"]
    C --> D{"Does it work?"}
    D -->|No| A
    D -->|Yes| E["Initial access\n(often SOLD on\nto another group)"]
    E --> F["Encryption, mining\nor exfiltration"]

Nothing in this chain requires anybody to have heard of Nimbus. Three practical consequences:

  1. Exposure weighs more than appeal. What decides whether you get compromised is not how interesting you are, but whether you have something open and unpatched. That SSH on 0.0.0.0/0 from section 4.3 receives authentication attempts every few minutes, every day, without anybody knowing what Nimbus is.
  2. Basic controls pay off disproportionately. Patching, closing what is not used, MFA on every administrative account and backups out of reach neutralise the vast majority of these actors. You do not need a security operations centre to defend yourself from a bot.
  3. Initial access gets resold. There are brokers who compromise systems and sell the access on to ransomware groups. That is why "they only mined some cryptocurrency, it's not serious" is a dangerous conclusion: whoever got in may have left a door open, and whoever uses it next may have other plans.

Against an APT, the honest conclusion is different: if a group with state resources decided to attack Nimbus specifically, Nimbus cannot stop it. What it can do is detect and limit the reach, which is exactly the "assume breach" approach from lesson 01-03. And there is a relevant nuance: Nimbus could be an intermediate target — not for its data, but for being a supplier to others. Supply chain attacks turn small companies into bridges towards large ones.


  1. A practical introduction to threat modelling with STRIDE

Threat modelling is a structured exercise for answering, against a concrete design: what can go wrong here? It is done before building (security by design) or when reviewing what exists, and it requires no tooling: a diagram and a method are enough.

STRIDE is the most widely used method for getting started. It is a list of six threat categories, each associated with the security property it violates:

Letter Threat Property it violates Question to ask Example in Nimbus
S Spoofing Authenticity Can somebody pass themselves off as somebody else? A fake webhook pretending to be the payment gateway
T Tampering Integrity Can somebody alter data in transit or at rest? Modifying the amount in the request before it reaches the API
R Repudiation Non-repudiation Can somebody deny what they did? Cancelling 200 appointments and claiming it was not them, with no log to contradict it
I Information disclosure Confidentiality Is information leaking to the wrong people? The endpoint with no tenant filter from lesson 01-01
D Denial of service Availability Can legitimate use be prevented? The reporting endpoint with no pagination
E Elevation of privilege Authorisation Can somebody obtain more permissions than they are entitled to? A clinic user who gets hold of an administration role

You will recognise all six: they are the properties from lesson 01-01 seen from the attacker's side. That is the whole trick of STRIDE — it turns a list of properties into a list of questions.

8.1 Step 1: draw the data flow diagram (DFD)

Modelling is done against a diagram, not against the whole application. A DFD has four elements: external entities (actors outside your control), processes (your code), data stores and flows. And a fifth element that is where nearly all the value of the exercise lives: the trust boundaries, lines separating zones with different levels of trust.

flowchart TB
    subgraph EXT["UNTRUSTED ZONE - Internet"]
        U["Patient / end user\n(external entity)"]
        ADM["Clinic staff\n(external entity)"]
        CONS["External consultancy\n(external entity)"]
    end

    subgraph BORDE["BOUNDARY 1 - Public edge"]
        WAF["Load balancer + WAF\n(process)"]
    end

    subgraph APP["BOUNDARY 2 - Private application network"]
        API["FastAPI REST API\n(process)"]
        WRK["Reporting worker\n(process)"]
    end

    subgraph DAT["BOUNDARY 3 - Data zone"]
        DB[("PostgreSQL\ndata store")]
        S3[("Attachments bucket\ndata store")]
        LOG[("Audit and logs\ndata store")]
    end

    subgraph TER["BOUNDARY 4 - Third parties"]
        PAY["Payment gateway"]
        MAIL["Transactional e-mail"]
    end

    U -->|"F1: HTTPS book"| WAF
    ADM -->|"F2: HTTPS manage diary"| WAF
    WAF -->|"F3: internal HTTP"| API
    API -->|"F4: SQL over TLS"| DB
    API -->|"F5: encrypted objects"| S3
    API -->|"F6: audit events"| LOG
    API -->|"F7: tokenised charge"| PAY
    PAY -->|"F8: confirmation webhook"| API
    API -->|"F9: reminder sending"| MAIL
    WRK -->|"F10: aggregate read"| DB
    CONS -->|"F11: administrative remote access"| APP

How to draw a useful DFD (this will help you with the exercise):

  1. Start with the external entities: everything you do not control. That is where the unexpected enters.
  2. Add your processes and data stores.
  3. Draw the flows and number them: the numbers let you enumerate threats in an orderly way and not forget any.
  4. Draw the trust boundaries. Rule of thumb: every time data crosses a boundary, it has to be analysed. That is where the threats concentrate.
  5. Do not draw the whole company. A DFD of one specific flow, done well, is worth more than a giant diagram nobody looks at.

8.2 Step 2: apply STRIDE to the flows and elements

You walk through the diagram element by element asking the six questions. An extract from the Nimbus analysis:

Element / flow Letter Concrete threat Mitigation
F1 User → WAF S Somebody books while passing themselves off as another patient E-mail/SMS verification when booking; authenticated session to manage it
F1 User → WAF D Mass automated bookings that fill a customer's diary Rate limiting per IP, CAPTCHA, limit on bookings per user
F3 WAF → API T Tampering with internal traffic if the network is considered "trusted" TLS on the internal leg as well; mTLS between services (Zero Trust)
F4 API → DB I A query returning another tenant's data Tenant filter + row level security; DB user with least privilege
F4 API → DB E SQL injection allowing unforeseen operations to be run Parameterised queries; a user with no DELETE and no DDL
F5 API → Bucket I Attachments accessible by direct URL without authorisation Private bucket, short-lived signed URLs, ownership verification
F6 API → Logs R An actor with access erases their trail Append-only store, in a separate account; no delete permission for production
F8 Gateway → API S A forged webhook marking an unpaid invoice as paid Verification of the webhook signature; IP allowlist; confirmation against the gateway's API
F10 Worker → DB I The reporting worker reads columns with personal data it does not need Aggregate view with no identifiers; role with minimal permissions (the exercise from 01-03)
F11 Consultancy → App E Permanent, shared administrative access used beyond what is necessary Just-in-time access with expiry, named accounts, session recording, MFA
DB data store D Deletion or encryption by ransomware Immutable backups in another account, out of reach of the production credentials

Three rules for making the exercise productive:

  • Do not hunt for all six letters in every element. Some do not apply. That is normal and it is not a failure of the method.
  • Prioritise the boundaries. The flows that cross a trust line (F1, F2, F8, F11) concentrate the most relevant threats.
  • Every threat must end in a decision: mitigate, accept, transfer or eliminate. A modelling exercise that produces a pretty list and no decisions has achieved nothing. Formalising those decisions — with likelihood, impact and a matrix — is done in 04-01.

  1. Closing the module

This is the point at which the four lessons come together:

flowchart LR
    L1["01-01\nVocabulary and CIA\nWHAT to protect"] --> L2["01-02\nThreats and vulnerabilities\nWHAT to protect it from"]
    L2 --> L3["01-03\nDesign principles\nON WHAT BASIS"]
    L3 --> L4["01-04\nAssets, surface and actors\nWHAT you actually have"]
    L4 --> M2["MODULE 2\nCybersecurity\nHOW THEY ATTACK and HOW TO DEFEND"]

You have the map of the terrain. From here on, each module goes deeper into one part: how attacks work and how to defend against them (2), how information is protected with mathematics (3), how risk is managed and incidents are answered (4), what tools are used (5), what regulation requires (6) and how to apply it all to a complete case (7).


Common Mistakes and Tips

Common mistakes:

  • Confusing an inventory with a list of servers. The inventory includes data, SaaS services, domains, people and third parties. The assets that are not servers are the ones most often forgotten and the ones that cause the most incidents.
  • Doing the inventory once. An inventory from a year ago describes a company that no longer exists.
  • Inventorying with no owner. An asset with no responsible person does not get patched, does not get classified and does not get retired. If you had to pick a single field, pick owner.
  • Classifying everything as confidential. If everything is confidential, nothing is: the team stops distinguishing and treats everything with the same (low) care.
  • Forgetting the internal surface. Many organisations measure themselves only from the outside. The internal surface is what determines the reach of a compromise.
  • Believing "we're not a target". Opportunistic attacks do not choose; they find. It is the most expensive reasoning error in an SME.
  • Threat modelling with no trust boundaries. A DFD with no boundaries turns the exercise into a pretty drawing. The boundaries are where the threats are.
  • Finishing the modelling with no decisions. A list of threats with no assigned mitigation and no owner changes nothing.

Tips:

  • Start the inventory with what faces the Internet and with what holds restricted data. That already covers the bulk of the risk.
  • Spend one hour per quarter exclusively on looking for what is surplus: subdomains, environments, accounts, integrations and unused credentials. It is the most profitable security hour of the quarter.
  • When you review a server, always cross-check two layers: what the system is listening on (ss) and what the provider's firewall allows. A single layer gives a false diagnosis.
  • Do your first STRIDE modelling on a single flow — the booking one, for instance — and finish it. A small, completed model teaches more than an ambitious, abandoned one.
  • Keep the DFD next to the code, in the repository. That way it gets updated when the architecture changes and does not become a dead document.

Exercises

Exercise 1 — Completing and classifying the inventory

During a review, five Nimbus assets turn up that were not in the table in section 2.1. For each one, state: type, reasonable owner, criticality, classification and one immediate action.

  1. The server demo.nimbusreservas.example, spun up 94 days ago by Iván, serving static files on port 8000 from the database server.
  2. A spreadsheet shared by Sara with the names, DNI numbers, salaries and bank accounts of the 38 employees, in a cloud folder with an "anyone with the link can view" share.
  3. A GitHub service account named nimbus-deploy-bot with a personal token that has no expiry and write permissions on every repository.
  4. A NAS in the Valencia office where the databases used to be copied until two years ago; it is still switched on and nobody remembers the administration password.
  5. The WhatsApp group "Nimbus Urgent Support", where Rubén shares screenshots of customer issues.

Exercise 2 — Reducing the attack surface

This is the result of sudo ss -tulpn on the Nimbus application server. For each line, state whether it is acceptable or not, what risk it introduces and what concrete surface-reduction action you would apply.

Netid State  Recv-Q Send-Q  Local Address:Port  Peer Address:Port Process
tcp   LISTEN 0      511           0.0.0.0:8000       0.0.0.0:*     users:(("python",pid=1201,fd=6))
tcp   LISTEN 0      128           0.0.0.0:22         0.0.0.0:*     users:(("sshd",pid=633,fd=3))
tcp   LISTEN 0      511           0.0.0.0:6379       0.0.0.0:*     users:(("redis-server",pid=940,fd=6))
tcp   LISTEN 0      128         127.0.0.1:5000       0.0.0.0:*     users:(("flask",pid=3310,fd=4))
tcp   LISTEN 0      511           0.0.0.0:9100       0.0.0.0:*     users:(("node_exporter",pid=1102,fd=3))
udp   UNCONN 0      0             0.0.0.0:161        0.0.0.0:*     users:(("snmpd",pid=755,fd=8))

Exercise 3 — STRIDE modelling of a new flow

Nimbus is going to launch a new feature: SMS reminders. The flow is:

  1. Clinic staff enable reminders from the web panel.
  2. A worker queries PostgreSQL every hour for the appointments in the next 24 hours.
  3. For each appointment, it calls the API of a new SMS provider (a third party) sending the patient's phone number and a text with the date, the time and the name of the service ("Knee rehabilitation").
  4. The provider returns a message identifier which is stored in the sms_messages table.
  5. The provider sends a webhook to the Nimbus API when the SMS is delivered or fails.

You are asked to: (a) draw the DFD in mermaid with its trust boundaries; (b) identify at least one threat for each letter of STRIDE, stating the affected element or flow; (c) propose a mitigation for each one.


Solutions

Solution 1

# Asset Type Owner Criticality Classification Immediate action
1 demo on port 8000 Software / Service Iván Medium (because of its location: it is on the DB server) To be determined from its content Shut it down today and review what it was serving. If it is needed, recreate it in an isolated environment with automatic expiry
2 Payroll spreadsheet with a public link Information Sara High Restricted Revoke the public link immediately, move to named permissions, review the access log and assess whether there was a data breach
3 nimbus-deploy-bot token with no expiry Information (secret) Marta Critical Restricted Rotate the token, narrow permissions per repository, migrate to short-lived credentials from the CI/CD itself, enable expiry
4 Forgotten NAS with old backups Hardware + Information Lucía High (it contains personal data) Restricted Isolate it from the network, regain access in a controlled way, inventory the content, export whatever has legal value and securely destroy the rest
5 WhatsApp group with customer screenshots Service / Information Rubén (with Marta as process owner) Medium Restricted because of its content Ban the use of personal channels for customer data, migrate to the ticketing tool, delete the history and train the team

Key comments:

  • Case 2 is the most serious in personal data terms and probably the most frequent in real life. An "anyone with the link" share is publication: links get forwarded, indexed and leaked.
  • Case 3 illustrates surface reduction in the supply chain: a token with no expiry and full access to every repository is a master key that never expires.
  • Case 4 shows why the inventory must include retirement: a forgotten asset remains a risk liability for as long as it is switched on.
  • Case 5 is a reminder that the human surface and the third-party surface do not always run through corporate systems.

Solution 2

Line Verdict Risk Action
0.0.0.0:8000 (python/API) Acceptable with a caveat It is the application; it must be reachable, but only from the load balancer Restrict it in the security group so that it only accepts traffic from the load balancer, not from the Internet
0.0.0.0:22 (sshd) Not acceptable if the firewall allows it from outside Continuous brute forcing from bots; direct administrative access Access only from a bastion host or a VPN; key-based authentication, no passwords; no direct root access; logging and alerting
0.0.0.0:6379 (redis) Serious Redis with no authentication by default: read and write access to sessions and cache, and in known scenarios the ability to write files on the system Bind it to 127.0.0.1 or to the private network, enable authentication and TLS, close the port on the firewall. Top priority
127.0.0.1:5000 (flask) Suspicious Not exposed (local only), but what is a Flask development server doing in production? Investigate and remove. Unnecessary internal surface and probably an uninventoried asset
0.0.0.0:9100 (node_exporter) Not acceptable Exposes detailed system metrics with no authentication: versions, processes, file systems Restrict it to the monitoring network; add authentication or mutual TLS if the provider supports it
0.0.0.0:161 (snmpd) Not acceptable SNMP with the default community string (public) leaks a complete system inventory; older versions of the protocol have no encryption Uninstall it if it is not used (which is most likely). If it is used, version 3 with authentication and encryption, restricted by network

The decision rule that sums up the exercise: for every listening service, ask yourself whether anybody needs it; if nobody needs it, remove it; if somebody needs it, restrict who can reach it. By applying just that, this machine goes from six open doors to one, controlled.

Solution 3

(a) DFD of the SMS reminders flow:

flowchart TB
    subgraph EXT["UNTRUSTED ZONE"]
        CLI["Clinic staff\n(external entity)"]
        PAC["Patient\n(receives the SMS)"]
    end
    subgraph APP["APPLICATION ZONE"]
        PANEL["API / web panel\n(process)"]
        WRK["Reminders worker\n(process)"]
    end
    subgraph DAT["DATA ZONE"]
        DB[("PostgreSQL\nappointments + sms_messages")]
        SEC[("Secrets store\nprovider API key")]
    end
    subgraph TER["BOUNDARY - THIRD PARTY"]
        SMS["SMS provider"]
    end

    CLI -->|"G1: enable reminders (HTTPS)"| PANEL
    PANEL -->|"G2: save configuration"| DB
    WRK -->|"G3: read next 24h appointments"| DB
    WRK -->|"G4: read credential"| SEC
    WRK -->|"G5: phone number + service text"| SMS
    SMS -->|"G6: message id"| WRK
    WRK -->|"G7: store id"| DB
    SMS -->|"G8: delivery webhook"| PANEL
    SMS -.->|"G9: SMS"| PAC

(b) and (c) STRIDE threats and mitigations:

Letter Element Threat Mitigation
S Spoofing G8 webhook A third party sends fake webhooks pretending to be the provider, in order to mark undelivered messages as delivered or to inject data Verify the webhook's HMAC signature with the shared secret; validate the source; reject and log anything unsigned (see 03-04)
T Tampering G5 worker → provider Tampering with the message content or the destination number if the channel is not protected Mandatory TLS with certificate validation; never accept unverified certificates; validate the phone number format before sending
R Repudiation G1 enablement The clinic denies having enabled the sending of appointment data by SMS to a third party Record the enablement with actor, time, IP and explicit acceptance of the terms, in a log with no delete permission
I Information disclosure G5 and G9 The main threat of this flow. The text includes the name of the service ("Knee rehabilitation"): it is sent to a third party and shown on the phone's lock screen, visible to anyone. It is information that reveals health data Minimise the content: send only "Reminder: your appointment on 15/03 at 17:00 at Turia Clinic", with no service name. Assess the processing with the compliance lead before launch; processor agreement with the provider; minimal retention; informed consent from the patient
D Denial of service G3/G5 worker The provider rate-limits or goes down and the worker retries in a loop, saturating the database or burning through the credit; or a customer with 10,000 appointments blocks the queue Queue with exponential backoff and a retry limit, a circuit breaker, a limit on messages per tenant per hour, credit and error-rate alerts
E Elevation of privilege G4 secret / worker The worker runs with the general API credential and can read every table; or the provider key leaks into the logs and allows SMS messages to be sent at Nimbus's expense Its own role with minimal permissions (SELECT on an appointments view with no clinical data, INSERT on sms_messages); credential in the secrets store, never in logged environment variables; rotation; a ban on logging the key

A cross-cutting threat worth adding (good practice when modelling): the flow introduces a new third party into the supply chain, with access to patients' phone numbers and, if the content is not minimised, to information about their health. This requires supplier assessment, a data processing agreement, and a decision about what happens to that data when the relationship ends. That is the subject of 04-04 and 06-03.

Note on legal implications: this exercise touches on the processing of personal data and its disclosure to a third party, with data that may reveal health information. The concrete decisions — lawful basis, information to the data subject, contract with the processor, need for an impact assessment — must be validated with your compliance lead or with a legal professional. What is set out here is for training purposes only.


Conclusion

You have closed the module with the most practical of the four lessons. You know that an asset is anything of value — information, software, hardware, services, people and intangibles such as reputation — and you have built the Nimbus inventory with the four fields that make it useful: owner, criticality, classification and dependencies. That inventory has revealed two things no tool would have told you: that the cloud provider account is the asset almost every other one depends on, and that there are cells with doubts in them — such as the classification of pre-production — which are, precisely, the first job outstanding. You have learned to classify information into four levels and the three rules that prevent the usual mistakes: classification is inherited upwards, aggregation can raise the level and context defines sensitivity — which is why a physiotherapy diary is not "just a diary".

You have checked the paperwork against reality using ss -tulpn and discovered a forgotten server that had been running for 94 days, and you have learned the rule that makes that output useful: look at the local address before the port, and always cross-check the system layer with the provider's firewall layer. On top of that picture you have measured the attack surface in its five dimensions — network, software and APIs, human, physical and supply chain — and you have seen that reducing it is the most profitable investment there is: what is not there cannot be attacked, patched or watched. You have met the threat actors and corrected the most expensive reasoning error in any SME: the opportunistic attacker does not choose victims, they find systems, and that is why exposure weighs more than appeal. And you have taken your first steps with STRIDE over a Nimbus data flow diagram, learning that the value of the exercise lies in the trust boundaries and in ending every threat with a decision.

That closes module 1. You have the vocabulary, the catalogue of threats, the design principles and the exact map of what has to be protected at Nimbus. From here on we stop describing the terrain and enter the conflict. In Module 2: Cybersecurity we will define the scope of the discipline and its reference frameworks, work through the types of attack executed against systems like the Nimbus one, study social engineering and phishing in depth — the route through which most real incidents arrive — look at the protective measures that counter them, go deeper into identity, authentication and access control, and analyse case studies of real incidents to draw out the lessons that repeat again and again. We begin with Definition and Scope of Cybersecurity (02-01).

Fundamentals of Information Security Course

Module 1: Introduction to Information Security

Module 2: Cybersecurity

Module 3: Cryptography

Module 4: Risk Management and Protection Measures

Module 5: Security Tools and Techniques

Module 6: Best Practices and Regulations

Module 7: Final Project

© Copyright 2026. All rights reserved