We all know our beloved Sherlock Holmes. The fictional character that, through the science of deduction, deduces with a great level of precision on the Who, What, When, Where, Why and the How of a crime. He pushes the limits of what any human is capable of, and thinks of all the possible factors and angles to make that logical conclusion.
Okay, ‘but what does Sherlock Holmes have to do with application security?’
While Sherlock is a fictional character, we can draw certain parallels to application security from his approach to deductive investigation. Sherlock uses something akin to a Threat Modeling approach to encompass for all factors prior to making deductions. He starts off with the facts and basics of the case before adding any interpretations. He then thinks of all the possible motivations behind the crime, then followed by the different potential attack methods given the case’s context. What adds great value to his approach is his accounting for factors on a granular level.
Let's look at Sherlock’s method of Threat Modeling.
Image: Threat Model like Sherlock
When drawn parallel to Sherlock's approach, the “facts/basics” of a threat model used in application security is the user stories created using the user functionalities. The “motivation” would be the abuser stories that's created using the different ways you can abuse a functionality. The “attack methods” would be the different attack models that one can think of in order to successfully abuse a functionality. And, the “granularity” in his assessment would be the test cases.
Let’s further look at these components of the threat model.
User Story: A user story is essentially a description of an application feature/requirement written from a user perspective (basics). Lets use file-upload feature of a cloud service for example. The user story would be: “As a User I want to upload files to my cloud drive account to ensure that I have a copy of the file in my cloud account”
Abuser Story: As the name implies, an abuser story is essentially a description of how an attacker would abuse (motives) said feature, keeping in mind the associated business impact. By using user stories of an application, you can think of the different ways one can abuse the functionality, and create abuser stories.
A good abuser story should contain three important elements - an attack persona, an attack vector and an attack outcome. This will allow engineering teams to look at each user story and also understand the various threats that can adversely affect the application.
Using the same example above, the associated abuser story could be: “As an attacker, I want to capture the file while being uploaded allowing me access to the file that the user is uploading to Cloud Drive.” The same feature can have multiple abuser stories. Here is another abuser story for the same feature: “As an attacker, I want to tamper with files of the user being uploaded so the user will have corrupted files that are unavailable to the user.”
Attack Model: Just like how Sherlock thinks of all the possible avenues of attacks based on the facts and motives related to the case, we need to come up with all the possible attack models facing the application. This is where you bring the abuser story to life by focusing on attack vectors and outcomes from the abuser story. The best way to approach this is, think of all the different ways to attack the application to accomplish that abuser story. The attack models should be technical as opposed to abuser stories. There are bound to be overlaps.
Using the DREAD risk assessment model, we can try to quantify the potential threats that could affect the application. By doing so, engineering teams can anticipate high risk threats early on and prioritize their backlogs depending on the DREAD scores of the attack models. This way, threats of higher risk are tested early on and in the eventuality of a vulnerability they can be fixed either within the same sprint or upcoming sprints of a product release.
Let's use the following abuser story as an example to come up with attack models: “As an attacker, I want to capture the file while being uploaded allowing me access to the file that the user is uploading to Cloud Drive.”
Attack model 1: “The attacker can perform ‘Man in the Middle’ attacks against a user on the network and capture file content.”
Attack model 2: “The attacker can leverage Cross Site Scripting to manipulate the upload location of the file, so its downloaded to the attacker's controlled server/application”
So far, we started off with the application features to create user stories, which we used to derive at abuser stories, and then formed threat models for each of those abuse cases. By applying this threat model flow to all features of an application, you would have practically covered for most types of abuse an application might be vulnerable to in its lifecycle. But this isn’t enough for us to attain Sherlock’s level of granularity. That is where Test Cases come into play.
For those of you who don’t know what test cases are, here is a quick 101.
Test Cases: The 'Test case' concept is usually used in functional Quality Assurance (QA) testing. It consists of a sequence of steps with pre-conditions(entry criteria), expected results and post-conditions, which is created for a particular test scenario in order to verify compliance against a specific requirement.
Test cases in the application security context is slightly different. They are different in that, security test cases are written to test for certain parameters or specific vulnerability of an application. It still consists of a sequence of steps that acts as a road map for security testing. With test cases, you can dig deep into each attack models and record each smaller steps required to successfully complete that attack model. This gives us the required granularity that Sherlock uses in accounting for factors that aren’t obvious at first look.
By using the attack models we came up with earlier, we can formulate the pen test cases.
Using our example Attack Model case, “The attacker can perform ‘Man in the Middle’ attacks against a user on the network and capture file content,” we should think of all the different aspects of the application that can give an attacker an avenue for a successful man-in-the-middle attack.
Test case 1: Check if application is always on HTTPS, across the application
Test case 2: Check the strength of SSL/TLS deployment with SSLLabs.com
Test case 3: Check if HSTS header is present in the HTTP Headers from the Cloud Drive
Test case 4: Check if weak ciphers can be negotiated with the Cloud service (TLS)
Test case 5: Check if session fixation is possible against the Cloud Drive's services
The other attack model example: “the attacker can leverage Cross Site Scripting to manipulate the upload location of the file, so its downloaded to the attacker's controlled server/application”.
Test case 1: Check for Persistent Cross Site Scripting in all parameters
Test case 2: Check for Stored Cross Site Scripting in all parameters
Test case 3: Check for DOM-Based Cross Site Scripting in all parameters
Test case 4: Check if Content-Security-Policy Header is enabled in all HTTP requests and is specific to only whitelisted URLs
Test case 5: Check if cloud drive allows loading of third party iFrames
Before you question the significance of test cases in an agile process, let me give you the gist of why it is important. Test cases server three different purposes:
- It facilitates as a road map for security testing from an execution standpoint: With a repository of test cases, you can take on highest priority tests first. Using the DREAD model, you can rank the list of attack models. You can prioritise the ones with higher risk and then move down the value chain.
- It enables efficient security testing: With the identified repository of test cases, teams can look for optimizing their execution by evaluating those test cases that can be automated. Barring those which aren’t technically feasible, all automated security test cases can be executed as part of the regression suite for every iteration.
- It provides traceability: It gives you an accurate idea of the test coverage against the length and breadth of the application. It also helps establish mapping of user features of an application with the security verification checks that needs to be executed against said features.
Here is what a threat model with test cases would look like:
Image: Threat model with test cases
The nature of agile software development is that application development occurs in an iterative fashion, with each iteration focusing on releasing a minimum viable product. By using this threat model with test cases approach, you can categorically enumerate every possible abuse case(s) and test scenario(s) specific to that application right from the ideation stage. Since the risk levels are directly related the business functions of the application’s features, this approach assess an application’s vulnerability from a business implications perspective. Essentially, this allows teams to shift security left by helping developers, QA and DevOps folks in identifying and addressing security issues, during development and beyond . In addition, with the repository of test cases, you can efficiently increase your testing coverage through automation and by focusing on high risk attack models.
So, as Holmes would often say to the good doctor (Watson), “It’s all elementary!”
Planning on taking the next level with DevSecOps? Get your teams trained on iterative Threat Modeling for agile product engineering. Click here to Know More