Fraser Scott
|
VP of Product
February 22, 2022

Introduction to the Open Threat Model standard

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-123136
image-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.