Testing EDRs for Linux: A Simple Test Case

Written by matuzg | Published 2022/06/22
Tech Story Tags: linux | linode | hacking | pentesting | edr | exploit | security | killchain

TLDRHow to simplify your edr tests while keeping it real, and an easy-to-expand initial access case. I’ll help you with a simple base test case, that you can use to get a glimpse and hopefully easily extend to a proper test. I’m also adding some of the observations we made that can cut some of the complexity if you decide to test it yourselfvia the TL;DR App

These days, I start to have second thoughts about releasing information that could be useful for attackers. So this time I’ll try something different. I will not tell you specifically what we found about the capabilities of specific EDRs on Linux. If you are interested, feel free to reach out, I’m glad to share once I know the information will be in good hands.

However, I’ll help you with a simple base test case, that you can use to get a glimpse and hopefully easily extend to a proper test. I’m also adding some of the observations we made that can cut some of the complexity if you decide to test it yourself.

Another reason I decided to pick this format is that these days security tools are picked frequently by non-security people who do not necessarily have the specialized background to set up realistic test cases and effectively focus their efforts when comparing products. Similarly, security teams often do not have the time to dig deep enough. With the test case in the repository, I believe with a very little background you can get to the post-exploitation part which, in a lot of ways, is more understandable and straightforward for most.

I encourage you if you have an EDR and your shop runs Linux or macOS, spend a few days and take it for a spin!

Here’s the TLDR, if you are testing EDR on Linux you don’t have to care about any of these:

  • The vast majority of detections are based on atomic actions, not process trees and scoring: if you want to simplify your tests just run them straight from the shell and test individual steps separately. Sort of the way Atomic Red Team does.
  • Content of networking is not where EDRs put the emphasis: start with simple HTTP and just reuse your C2 until you run into problems
  • Dynamic loading of functionality matters much less than for Windows: just start with complete payloads and add when needed
  • Providers are fair towards your tests and agents don’t really adapt as much as one might think: you can have your test machine run only the malicious behavior. If you want to double check, just rerun test cases, that avoided detection earlier to see if the box got tainted.

Why testing security products is time-consuming

When you are testing something you want to make sure that your test cases are representative of reality and complex enough. You don’t want your whole scenario detected because of a simple file hash in the beginning, but you also want to avoid concluding that a product is useless because they got unlucky and did not detect your single variant.

If you test EDRs, you ideally set up a realistic baseline environment, and go through each step in the kill chain or tactic in MITRE ATT&CK and for every single stage you have different versions of the same steps each with different level of evasion sophistication.

Clearly, this leads to a huge combination and a tremendous amount of work. So you start cutting some of that complexity.

You can leave out some steps or some levels of sophistication. The problem is that either you ran out of time because you cut the wrong place and you end up concluding the tool is better than it is or you get to the limits of the product and in the end, your self-criticism, or the inevitable pushback from the providers, will remind you: maybe the reason why things did not get detect is that the scenarios were not realistic enough.

There are good arguments for this: reverse shell is not malicious by itself; the thing you did is not a technique that is actually used out there in the wild and detections on real behavior. These are fair points, so now you are stuck. You have to sink quite some more time into further testing or take the arguments at face value.

I’m here to save you that headache

You can cut out a lot of complexity based on the observation we learned the hard way in our tests. If you expect the external challenge to your results I’m also giving you a simple test case that addresses most of the arguments you are going to encounter.

In this repository, you will find a base case of initial access and execution combined with some basic C2 setup using open source tools. I believe you best spend your time working on the rest.

The test scenario is the following: Attackers publish and backdoored NPM package which is your dependency. The package uses a malicious preinstall script to download and run a script that drops a backdoors that establish communication to common open source C2 frameworks.

The scenario does happen in reality: packages do get backdoored using the exact same method, and attackers — as we know very clearly from the conti leaks- do use for example Metasploit. The only exception is that in reality on Linux these malicious packages most often steal secrets (including ssh keys), but you can easily add that as a post-exploitation step.

I also added a vulnerable VM set up with Vagrant that includes a number of ways to escalate privileges so that you don’t have to care about that either.

Good luck with your tests!

Special thanks to Andras, Keith, Marcus, Mark, and Zsolt for the help and guidance on the way, which allowed me to summarise quite extensive research for you and to distill a lot of the technical work in the simplest scenario that you can use for testing EDRs yourself.

Also published here.


Written by matuzg | Security enthusiast into all things efficiency. Current project: https://inthewild.io/
Published by HackerNoon on 2022/06/22