Risk Patterns are re-usable collections of Use-cases, Threats, Weaknesses and Countermeasures that can be imported into a threat model as a unit. They are the basic building blocks of threat models in IriusRisk. Risk Patterns differ from Templates in one key respect: The content of a Risk pattern can only be imported into a Component, whereas the content of a Template can be imported into a Product. Risk Patterns contain Use-cases as their top level object, while Templates contain Components.
Risk Patterns and the rules related to those patterns are grouped together in a "Library". The interfaces used to navigate and edit risk patterns are virtually identical to the interfaces used to edit the threat model of a product.
The Threat Model Generation Process
This process is triggered when the "Done" button on a component questionnaire is clicked. We also refer to this process as the threat model "Import process", because it effectively imports risk patterns from the libraries into the component that's being modeled. This is a copy operation that will copy and merge the content of the risk pattern into the threat model for a component. All of the fields recorded in the risk pattern are imported verbatim, e.g. if a countermeasure is in the Implemented state in the risk pattern, then it will be imported as Implemented in the generated threat model.
Designing Risk Patterns
When creating risk patterns the contents should be chosen based on the structure of the questionnaires as well as whether you can re-use the same pattern for multiple components, or under different circumstances. For example, you could take a course-grained approach and create a risk pattern that describes the threats, weaknesses and countermeasures that apply to username and password based authentication for a web application. This will be quite a large pattern with many threats and countermeasures. But it would be a poor choice when it comes to re-use because it can only applied in that one specific architectural case. If you were to design another risk pattern for username and password based authentication against an HTTP API, you'd probably find a large overlap with the content from the previous pattern since many of the threats and countermeasures would be repeated. A more re-usable approach is to break the patterns up into a hierarchy or composable patterns that each model an aspect of the architecture. In this example, you could create three patterns:
- Threats/Countermeasures for username and password authentication against any type of service
- Threats/Countermeasures for username and password authentication against any HTTP service
- Threats/Countermeasures for username and password authentication against a web application using a browser
This would allow you to re-use the first two patterns in other threat models using other architectural components without having to duplicate the content.
How Risk Patterns are merged during the import process
When the user completes the component questionnaire, the rules engine will determine which Risk Patterns are applicable based on the answers. When the risk patterns are imported, they are merged based on the names of the use-cases. For example, consider the following two risk patterns:
"Web Browser: Handles sensitive data" is a pattern of threats and countermeasures that apply when a web browser client handles data that belongs to a security classification with the Confidentiality rating above a certain threshold.
"Web Browser: JSON processing" is a pattern that contains a threat and countermeasures that apply when a web UI displayed in a browser receives and then transforms JSON in some way.
Notice that both of these risk patterns above have a use case called: "Read or Post data". If the user creates a new "Web Front-End" component and the rules that execute during the questionnaire cause both of the above risk patterns to be imported, then the resulting component would contain:
The content of the "Read or Post data" use case is a merged result of the two imported risk patterns.
The name of the component: "Web Front-End" is based on the name of the question the user is asked when selecting the type of component (See "Creating a new component"). The names of the risk patterns are not imported at all in the generated threat model - they exist purely to describe and identify the risk patterns when browsing them in the Library.
Importing Risk Patterns into a Threat Model
Risk patterns are included into a threat model through rules. Only rules that execute for components can import risk patterns, i.e. when creating these rules, choose the "Component" module on the rule. Importing a risk pattern is an Action that can be defined for a rule. Any number of conditions can be defined in order to cause the rule to execute and the pattern or patterns to be imported. For example, the rule that causes the AWS EC2 risk pattern to be imported is defined in the AWS Library as:
The condition is that the question is answered: "Elastic Cloud Compute - EC2" and the action is to import the "AWS EC2" from the "Hydras AWS Foundation" library. More conditions can be added to further narrow down the criteria for importing risk patterns.
In addition, more than one risk pattern can be imported using a single rule, e.g.:
Chained Risk Patterns
The fact that a risk pattern has been imported can also be used as a condition, or part of the condition, to import further risk patterns by using the condition: "Risk Pattern exists" to identify risk patterns that have been imported into the session. This is useful to add more specific risk patterns to the model only if the base or generic pattern is first imported. For example, if a risk pattern exists for "Generic IoT client" that describes the threats and countermeasures that apply to any IoT client under all circumstances, and in addition we defined another risk pattern for "IoT Client: Authentication", that contained the threats and countermeasures for authenticating from an IoT client, then we would create the following series of rules:
Rule: the component is an IoT client
Condition 1: The question: "IoT client" is answered
Action 1: Import the "Generic IoT client" risk pattern
This will cause the risk pattern to be imported as long as the user has selected the IoT client component type. To import the authentication risk pattern we would then create another rule:
Rule: the IoT client implements an authentication system
Condition 1: The risk pattern "Generic IoT client" exists (i.e. it has been imported into the rules session)
Condition 2: The question: "Yes, an authentication system will be created" was answered
Action 1: Import the "IoT Client: Authentication" risk pattern
Chaining rules in this way can avoid duplication in the rules and effectively allows you to create a hierarchical system of rules that can be extended in the future without having to revise the rules for each change.
Beware of infinite loops!
Using the "Risk pattern exists" condition and having subsequent rules that implement the "Import Risk Pattern" action can result in infinite loops in the rules engine. IriusRisk will display an error when these loops are encountered at run-time, but cannot detect them statically when the rules are defined.