Scroll to discover
Watch a Demo
Skip to content

Introduction to the Open Threat Model standard

The Open Threat Model (OTM) standard is a generic and tool agnostic way of describing a threat model in a simple to use and understand format. It has been designed to allow greater connectivity and interoperability between threat modeling and other parts of the Software Development Lifecycle (SDLC) and cybersecurity ecosystem. Released under Create Commons, anyone can contribute or use the standard.

Threat modeling as a practice is evolving, and so must the technology that surrounds the practice. If you look at what happened with DevOps, the key to scaling the creation and management of infrastructure was a combination of culture changes as well as the commoditisation of infrastructure such as through cloud and Infrastructure as Code (IaC). Threat modeling will inevitably go through a similar shift, and this standard has been to facilitate that evolution. By leveraging existing design artefacts such as IaC, we can automate the threat modeling process, increasing the scalability and maturity of threat modeling as a result.

Key use cases for an open threat modeling standard include:

  • Easily supporting new sources of application and system design. Anyone can write and share parsers or other tools that take source formats such as CloudFormation, Visio, or Docker Compose files.
  • Exchange threat model data within the SDLC and cyber security ecosystem. Having threat models represented in a common format means being able to use that data through integrations.
  • Exchange between organisations. It would be a great outcome if open source projects or even commercial vendors were sharing threat models of their systems in a way that could be ingested and used by organisations adopting those systems.

In this article we’re going to take a close look at the specification and how IriusRisk implements and uses it to automatically create threat models from CloudFormation templates. For the full specification see the Open Threat Model project repository. To learn how to create a simple parser that generates OTM see How to create an OTM parser.

An overview of the OTM specification
It makes sense to start by looking at some key elements and features of the specification. The specification is written as YAML (or JSON) and is broken up into a number of high level objects:

  • otmVersion - The version of the specification used in the file
  • Project metadata - Name, identifier, description, owner of the thing you’re threat modeling
  • Representations - E.g. diagram, code, JIRA story, user interface
  • Assets - Things you care about, sensitive information. E.g. PCI or PII data
  • Components - Bits that make up the representation such as an EC2 instance or an API
  • Trustzones - The differing levels of security and trust. Internet vs Web vs App vs Data tier
  • Dataflows - How information and assets move around between components
  • Threats - The bad stuff, the things that can go wrong
  • Mitigations - The good stuff, probably requires you to do some work

There are few other interesting things to note about the specification:

  • Objects can have arbitrary “attributes”, use them however you like. E.g. custom IDs
  • It provides basic properties to capture essential risk information (CIA triad, trustzone ratings, CWEs, likelihood and impact)
  • Tags to help you classify or group different components etc.
  • X and Y positions can be provided for diagrammatic representations
  • Components and Trustzones can be arbitrarily nested

Project
The project object contains metadata about the thing being threat modelled. The name and id fields are required, but other useful fields include a description, owner, and owner contact. You can use the attributes field to link your project to documentation hosted elsewhere or to the relevant asset in something like a CMDB.

project:
  name: Test project
  id: test-project
  description: This is a test project for the OTM development
  owner: John Doe
  ownerContact: john.doe@example.com
  attributes:
    documentation: “http://mydocs/my-app-123”
    cmdbId: MyApp123

Representations
Any given system can be threat modeled in a number of different ways, and from a number of different perspectives. For example, you can threat model as system based on the cloud infrastructure, or you can threat model the functional elements of the application itself such as login, shopping cart, user comments etc. The OTM specification refers to these different perspectives as representations, and an OTM file can include one or more representations. An architecture diagram representation may have diagrammatic elements such as width and height, where as a code-based representation may have a source code repository and file line numbers.

Here we can see an example of an architecture diagram representation.

representations:
  - name: Architecture Diagram
    id: architecture-diagram
    description: This is a diagram of the project's architecture
    type: diagram
    size:
      width: 1000
      height: 1000
    attributes:
      platform: drawio
      unit: pixel
  ...

This is what a code representation might look like.

  ...
  - name: Application Code
    id: application-code
    type: code
    repository:
      url: https://github.com/my-project
    attributes:
      language: java
      platform: github
      vcs: git

Because an OTM file can include multiple representations, that means you can include the full threat model of a given application or system, from each of the different perspectives.

Trustzones
Trustzones are a core part of any threat model. They provide key context about how components within a threat model are expected to behave and where threats are going to have the biggest impact. If you’ve got a completely untrusted zone such as the Internet connected directly to a highly trusted zone such as a data tier, you may find that a simple configuration error could easily expose the sensitive data to the world. The OTM specification uses a trustRating property to describe the expected level of trust and security of the trustzones.

trustZones:
  - name: Internet
    id: internet
    description: This is the internet trust zone
    risk:
      trustRating: 20
    representations:
      representation: architecture-diagram
      id: internet-box-shape

Components
Components are the building blocks of a threat model. They can include the architectural elements within system such as web servers, data bases, and firewalls. They can also include the functional elements with in a system such as the login page, a shopping cart, or an email sender.

Each component has a human readable name field, but also a type field. This type field helps to describe what type of object it is. For example, in a threat model you could have two different web services Web1 and Web2, both of the same web-service type. While they are different entities in the threat model itself, because they are the same type, we can expect similar threats and controls to apply to them.

Components also have a parent field. Typically this will be a trustzone, but a component can also be nested inside another component. For example, you may have a Rest API component inside an AWS EC2 instance component.

Tags are especially useful for components because they allow you to provide additional values that further describe the components in an arbitrary way. This can be useful for group or filtering.

components:
  - name: Web Service
    id: web-service
    type: web-service
    description: Runs our web application
    parent: 
      trustZone: private
    tags:
      - tomcat

Dataflows
Finally we’ll look at dataflows. These are the literal flows of data between components within a threat model. They can be network-level flows such as HTTP or DNS, or they can be higher level flows such as “user login” or “product search”. Of course, a data flow needs a source and a destination component. It can be unidirectional or bidirectional. And similar to components, tags can be used to provide additional context useful for grouping and filtering.
dataflows:
  - name: Dataflow between webservice and mongo
    id: cc-store-in-db
    description: Credit card information being exchanged in between the web app and the database
    bidirectional: true
    source: web-service
    destination: customer-database
    tags:
      - http
      - https


Using OTM with IriusRisk
IriusRisk has released an OTM API in version 4.1 of the product. This API allows you to provide an OTM file and IriusRisk will automatically build a full threat model using the rules engine an extensive library of components and risk patterns. The first release of the API supports trustzones, components, and dataflows. Threats and mitigations are already in the specification, and support for them in IriusRisk will be coming soon.

The rest of this article will focus on building a threat model in IriusRisk using OTM. We’ll start off with a simple HelloWorld OTM file created by hand in an IDE, and then we’ll build one from a CloudFormation template using the open source Startleft tool. For both of these examples, we’ll need to set a couple of environment variables used to connect with the API:

$ env | grep IRIUS
IRIUS_API_TOKEN=abc-123
IRIUS_SERVER=https://dev.iriusrisk.com


HelloWorld
Here’s a very simple OTM file created by hand in an IDE. Yes, it’s that easy.

otmVersion: 0.1.0
project:
  id: helloworld
  name: Hello World

trustZones:
  - name: Public
    id: 6376d53e-6461-412b-8e04-7b3fe2b397de
    risk:
      trustRating: 10
  - name: Private Secured
    id: 2ab4effa-40b7-4cd2-ba81-8247d29a6f2d
    risk:
      trustRating: 90

components:
  - name: Client
    id: client
    type: generic-client
    parent: 
      trustZone: 6376d53e-6461-412b-8e04-7b3fe2b397de
  - name: REST Service
    id: rest-service
    type: rest-full-web-service
    parent:
      trustZone: 2ab4effa-40b7-4cd2-ba81-8247d29a6f2d

dataflows:
  - name: Client to REST service
    id: client-to-rest
    source: client
    destination: rest-service
    tags:
      - HTTPS


It has two trustzones, two components, and a dataflow. This file can be sent straight to the IriusRisk OTM API using a simple curl command:

curl -XPOST -H "api-token: $IRIUS_API_TOKEN" -F 'otmFile=@helloworld.otm' 'https://dev.iriusrisk.com/api/v1/products/otm'
{ "ref":"helloworld",
  "name":"Hello World",
  "revision":"1",
  "type":"STANDARD",
  "status":"OPEN",
  "priority":"0",
  "tags":null,
  "workflowState":"wsa",
  "udts":[],
  "groups":null,
  "users":null
}


Here is the threat model created by IriusRisk:
image-20220218-124252

As you can see, because the rules engine has executed, it has automatically pulled in threats and countermeasures that would apply to this threat model:
image-20220218-124324

CloudFormation
Now let’s build a more complete threat model from a CloudFormation template. We will use the open source Startleft tool to parse the CloudFormation template into an OTM file, then we’ll upload that OTM file to the IriusRisk API. Finally we’ll look at the threat model created by IriusRisk as a result.

This code snippet shows a section of the CloudFormation template we’ll be using.  As you can see, the file uses Amazon's Elastic Container Service as well as a number of other resources such as CloudWatch alarms.

  service:
    Type: 'AWS::ECS::Service'
    DependsOn: ALBListener
    Properties:
      Cluster: 
        Ref: ECSCluster
      DesiredCount: '1'
      NetworkConfiguration:
        AwsvpcConfiguration:
          Subnets:
            - Ref: PrivateSubnet 
          SecurityGroups:
            - Ref: EcsSecurityGroup
      LoadBalancers:
        - ContainerName: simple-app
          ContainerPort: '80'
          TargetGroupArn: 
            Ref: ECSTG
      Role: 
        Ref: ECSServiceRole
      TaskDefinition: 
        Ref: taskdefinition

Using the Startleft project we can parse it into OTM with a single command.

$ startleft parse --type CloudFormation --map default-cloudformation-mapping.yaml --name "ECS Example" --id ecs-example --otm ecs-otm.yaml ecs.yaml
Writing threat model to 'ecs-otm.yaml'

The mapping file provided describes how to find resources in a CloudFormation Template, and how to map them into an OTM threat model. This gives us an OTM file which look something like:

{
  "otmVersion": "0.1.0",
  "project": {
    "name": "ECS Example",
    "id": "ecs-example"
  },
  ...
  "components": [   
    {
      "id": "1926dedc-c0e8-4539-b304-4fa359d9eeb9",
      "name": "service",
      "type": "elastic-container-service",
      "parent": {
        "component": "36f7c768-b05d-48b8-880f-da9bdaf41258"
      },
      "tags": [
        "AWS::ECS::Service"
      ]
    },
    {
      "id": "4ec0399f-8594-4bb3-9ee8-965153c07d33",
      "name": "taskdefinition",
      "type": "docker-container",
      "parent": {
        "component": "1926dedc-c0e8-4539-b304-4fa359d9eeb9"
      },
      "tags": [
        "AWS::ECS::TaskDefinition"
      ]
    },


We can now upload this OTM to IriusRisk using Startleft.

$ startleft threatmodel ecs-otm.yaml
Uploading OTM files and generating the IriusRisk threat model
Validating OTM file
OTM file is valid
OTM file has consistent IDs

Logging in to IriusRisk we can see it has built a full threat model. This isn’t just a visualisation of all of the resources in a CloudFormation template. What we can see here is an architectural view of the cloud infrastructure.

image-20220218-123136image-20220218-123209

Conclusion
The Open Threat Model standard gives us a flexible way to describe threat models which can be used throughout the SDLC and cybersecurity ecosystem. It’s simple enough to be able to create threat models by hand, and powerful enough to represent full threat models generated from Infrastructure as Code.