In my previous blog post on the MITRE ATT&CK evaluations, I developed a scale for rating the individual vendor evaluations and provided source code to help make the results more generally consumable. Since publishing this blog, I’ve been having a number of conversations with clients about the “tainted” modifier in the recent MITRE ATT&CK evaluations, as there seems to be quite a lot of confusion concerning whether or not a tainted detection should be viewed as a positive or negative.

A couple observations I attribute to this confusion are:

  • The word “tainted” carries a negative connotation in the English language. This creates confusion in the modifier definition as a result of the phrase “‘tainted by’ the detection,” which makes it appear that the previous detection may have facilitated, thereby reducing the quality of, the tainted detection.
  • The other two detection modifiers, configuration change and delayed, both negatively modify the quality of the detection due to the product not being able to detect a procedure immediately and out of the box.

To compound this issue, one of the participating vendors has published a press release boasting their lack of “tainted” detections, which I’m afraid is only going to cause more confusion in the market, so I feel it’s necessary for me to show tainted some love and demonstrate how it is one of the most important elements of the MITRE ATT&CK evaluation.

What Does It Mean For A Detection To Be Tainted?

First off, for a detection to receive the tainted modifier, there must have been an earlier detection, and the detection receiving the tainted modifier has to be shown to be related to that particular detection. In lay terms, the product is able to show that multiple malicious events are related on a system. Allow me to provide a brief explanation of what this means in your environment.

Step 1: The Process Tree

On modern operating systems, processes are applications or workloads that are created when a parent process decides to replicate itself, creating a child process and having that child execute that workload. Every time you run a program on your system, this replication process occurs, which over time creates a process tree that may look something like Figure 1.

Step 2: Exploitation

When an adversary wishes to compromise a system, they have to find a way through exploitation or social engineering to get a process to execute their own code. In the MITRE ATT&CK evaluation, this was accomplished by an adversary delivering a malicious file to the end user, who proceeded to click and execute this malicious code. It should be noted that four out of the seven evaluated products alerted immediately on this (Step 1.A.1), so I’ve put an exclamation mark on the compromised process in Figure 2.

Step 3: Tainted Execution

Remember that every time you run a program, you’re creating a child process to execute code (the program). Similarly, after an adversary has exploited a process, they will likely perform other operations on the system in furtherance of their objectives. As we detected the adversary on the system, any children of the compromised process must be viewed as tainted or under the adversary’s control, as we see in Figure 3.

If you’re looking at this graphic and thinking to yourself that it should be a simple task of monitoring the system for the creation of new processes to be able to communicate what an adversary is doing after an initial compromise, you’re right. This capability should be considered part of a minimum viable product (MVP) in the endpoint detection and response (EDR) space and is the heart of what the tainted modifier is communicating.

Step 4: Traversing The Process Tree For Evasion And Privilege Escalation

Unfortunately, the problem of corralling adversaries isn’t quite this simple, as adversaries commonly leverage techniques such as process injection or other types of local exploitation to move across the process tree for evasion and privilege escalation. This breaks the simple model we’ve been working with in one important manner: You can’t just use the process tree as we see in Figure 4. Note that five of the seven evaluated vendors generated alerts for at least one process injection step (T1055), so I’ve also placed an exclamation mark on the attacked process.

There’s a lot going on in this example compromise, as there would be in an actual attack. In this particular exercise, there would be two alerts: the initial attack and the process injection. Note that, because we were able to identify that the process injection was part of the compromise which started with the initial attack, this alert would be flagged as tainted. However, there is nothing about the tainted modifier that implies that the product would not have detected the process injection if it had not alerted on the initial attack. Remember, tainted execution is activity on the system that may be attacker-controlled . . . and yes, you need an initial detection to be able to start building this graph. This is what a forensics team is going to do and is what your product should be striving to automate for you.

In Conclusion, Or, Why Is “Tainted” A Critical And Desirable Detection Modifier?

The desired behavior of our security products should not be to have them generating 2–5 independent alerts in a situation such as this. We need to be able to tie it all back to the initial compromise so that we are generating a single independent alert for the compromise and granting each subsequent detection the “tainted” modifier. Nobody is doing this well, but we need to push the industry in the direction of looking at this graphic and describing this as a single intrusion, with all the enriched data that a Level 1 SOC analyst would need to understand what the adversary was doing at any point.