As far as I can tell, the only capital-T, formal threat model, is a threat model performed in formal attire
Remember: At its core, threat modelling is a means to try and make a fairly subjective process more objective, repeatable & consistent.
A collaborative process executed by multiple people to identify technical security issues in a solution, often based on design, architecture, or purely software.
An established mnemonic tool to help with repeatable threat modelling
(go down to read more)
Threat action aimed at accessing and use of another user’s credentials, such as username and password.
Threat action intending to maliciously change or modify persistent data, such as records in a database, and the alteration of data in transit between two computers over an open network, such as the Internet.
Threat action aimed at performing prohibited operations in a system that lacks the ability to trace the operations.
Threat action intending to read a file that one was not granted access to, or to read data in transit.
Threat action attempting to deny access to valid users, such as by making a web server temporarily unavailable or unusable.
Threat action intending to gain privileged access to resources in order to gain unauthorized access to information or to compromise a system.
Is better than nothing.
It could be unstructured, or random confluence pages
You may have a standard template!
are better than nothing.
Often they integrate into your cloud solutions to help generate data flow diagrams and the like
They always come with extensive pre-defined list of threats, risks and controls
// @accepts arbitrary file writes to WebApp:FileSystem
// with filename restrictions
// @mitigates WebApp:FileSystem against unauthorised
// access with strict file permissions
func (p *Page) save() error {
filename := p.Title + ".txt"
return ioutil.WriteFile(filename, p.Body, 0600)
}
With this, you annotate your existing source code using comments, such as these.
When you run the threatspec tools, it will output reports, DFDs and other artifacts.
#!/usr/bin/env python3
from pytm.pytm import TM, Server, Datastore, Dataflow, Boundary, Actor, Lambda, Data, Classification
tm = TM("my test tm")
tm.description = "another test tm"
tm.isOrdered = True
User_Web = Boundary("User/Web")
Web_DB = Boundary("Web/DB")
user = Actor("User")
user.inBoundary = User_Web
web = Server("Web Server")
web.OS = "CloudOS"
web.isHardened = True
web.sourceCode = "server/web.cc"
db = Datastore("SQL Database (*)")
db.OS = "CentOS"
db.isHardened = False
db.inBoundary = Web_DB
db.isSql = True
db.inScope = False
db.sourceCode = "model/schema.sql"
comments = Data(
name="Comments",
description="Comments in HTML or Markdown",
classification=Classification.PUBLIC,
isPII=False,
isCredentials=False,
# credentialsLife=Lifetime.LONG,
isStored=True,
isSourceEncryptedAtRest=False,
isDestEncryptedAtRest=True
)
results = Data(
name="results",
description="Results of insert op",
classification=Classification.SENSITIVE,
isPII=False,
isCredentials=False,
# credentialsLife=Lifetime.LONG,
isStored=True,
isSourceEncryptedAtRest=False,
isDestEncryptedAtRest=True
)
my_lambda = Lambda("cleanDBevery6hours")
my_lambda.hasAccessControl = True
my_lambda.inBoundary = Web_DB
my_lambda_to_db = Dataflow(my_lambda, db, "(λ)Periodically cleans DB")
my_lambda_to_db.protocol = "SQL"
my_lambda_to_db.dstPort = 3306
user_to_web = Dataflow(user, web, "User enters comments (*)")
user_to_web.protocol = "HTTP"
user_to_web.dstPort = 80
user_to_web.data = comments
web_to_user = Dataflow(web, user, "Comments saved (*)")
web_to_user.protocol = "HTTP"
web_to_db = Dataflow(web, db, "Insert query with comments")
web_to_db.protocol = "MySQL"
web_to_db.dstPort = 3306
db_to_web = Dataflow(db, web, "Comments contents")
db_to_web.protocol = "MySQL"
db_to_web.data = results
tm.process()
For those into the pythonic arts, PyTM is a good one to check out. Mind you, you do have to write actual python code.
This is Threatdragon from OWASP. Unfortunately, it's not really threat modelling as code
Now I want to spend some time talking about an open source tool I've been tinkering away on the last few years. Threatcl.
Here is a simple example
(go ahead, you can scroll down too)
threatmodel "Tower of London" {
description = "A historic castle"
author = "@xntrik"
attributes {
new_initiative = "true"
internet_facing = "true"
initiative_size = "Small"
}
information_asset "crown jewels" {
description = "including the imperial state crown"
information_classification = "Confidential"
}
usecase {
description = "The Queen can fetch the crown"
}
third_party_dependency "community watch" {
description = "The community watch helps guard the premise"
uptime_dependency = "degraded"
}
threat {
description = "Someone who isn't the Queen steals the crown"
impacts = ["Confidentiality"]
expanded_control "Guards" {
description = "Trained guards patrol tower"
risk_reduction = 75
}
}
}
Plus, now we can use CI/CD, such as github actions, to validate your hcl files, and even publish dashboards.
name: threatcl dashboard
on:
push:
branches:
- main
jobs:
threatcl-dashboard:
permissions:
contents: write
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: threatcl dashboard
uses: threatcl/[email protected]
with:
command: 'dashboard'
files: './hcl-files/*'
outdir: './dashboard'
- name: threatcl custom dashboard
uses: threatcl/[email protected]
with:
command: 'dashboard'
files: './hcl-files/*'
outdir: './custom-dashboard'
dashboard-template: './templates/dashboard-template.tpl'
dashboard-filename: 'db'
threatmodel-template: './templates/threatmodel-template.tpl'
- name: threatcl custom html dashboard
uses: threatcl/[email protected]
with:
command: 'dashboard'
files: './hcl-files/*'
outdir: './html-dashboard'
dashboard-template: './templates/dashboard-template-html.tpl'
dashboard-filename: 'index'
threatmodel-template: './templates/threatmodel-template-html.tpl'
dashboard-html: 'true'
You can see this example here.
Threatcl can generate data flow diagrams too.
Here you can see a rule that will flag a threat model that has a threat without any controls.
(go ahead, you can scroll down too)
- id: threatcl-missing-control
patterns:
- pattern: |
threat {
...
description = "$THREAT"
...
}
- pattern-not: |
threat {
...
expanded_control "$CONTROL_NAME" {
...
}
...
}
message: "The `threat` block '$THREAT' is missing an `expanded_control`"
severity: WARNING
languages: [hcl]
metadata:
category: security
cwe: "CWE-657: Violation of Secure Design Principles"
confidence: LOW
likelihood: LOW
impact: LOW
subcategory:
- audit
See the example here
Here is an example of what a finding looks like:
And guess what? It generated a perfectly valid file on the first attempt.
What does the DFD look like?
Much better.