One of the major benefits of Atomic Red Team is that it enables security teams to understand how adversaries leverage MITRE® ATT&CK techniques in the real world, and I’ve been a big fan for years. To me, Atomic Red Team is more than a repository of tests (aka atomics), it’s also a knowledge base, training tool, and more.
Each atomic in the library simulates a known adversary behavior associated with a given technique. Each of these tests are meant to help security professionals understand how a technique works (in other words, what malicious looks like) and enable them to test their defensive controls.
Execution frameworks, new and old
Invoke-Atomic has been the de facto execution framework that many security teams use to test their security controls. In fact, many years ago I made what I believe was a significant contribution to the PowerShell-based execution framework. Invoke-Atomic is now maintained by some extremely talented developers, and I’ve continued to use it. However, as my development focus has shifted towards Python on a day-to-day basis, I’ve increasingly found myself wanting a Python-based execution framework—and so too has the rest of the Atomic Red Team community.
There was a prototype of a Python execution framework in the Atomic Red Team repository, until it was archived a little over a year ago. Ultimately, this framework was never really maintained by the Atomic Red Team community. Since this execution framework lacked support and features, I decided I would tackle the challenge of creating an execution framework in Python to help me test defensive controls across multiple operating systems.
When I started building this tool, I had a few things in mind that I wanted it to do. It needed to be able to:
- execute atomics on any operating system
- run those tests remotely against any operating system
- run as both a command-line utility and a importable Python package
- automate testing via a configuration file of some sort
atomic-operator
With these requirements in mind, I got to work. Now, four months later Swimlane and I are proud to announce the release of a new open-source project called atomic-operator. atomic-operator
is a simple tool (run via command line or importable package) that helps security professionals test their defensive controls by running atomic tests locally or remotely across multiple operating systems.
By utilizing Python, atomic-operator
is at home on macOS, *nix systems, and Windows as well. Since many security professionals are comfortable with Python 3 (3.6 >=), you get all the advantages of an execution framework in your preferred language.
True to the requirements listed above, atomic-operator’s main features include:
- local and remote execution of tests on Windows, macOS, and Linux systems
- atomic testing against AWS-hosted environments
- optional prompting for input arguments
- downloading the Atomic Red Team repository
- test automation via a configuration file
- test administration via a command-line utility and an importable Python package
- much more!
How do I use this thing?!
To get started, you can install atomic-operator
via PyPi by running pip install atomic-operator
in your command shell. NOTE: You may need to modify your Python installation by ensuring that Python is in your environmental system path.
Alternatively, you can also clone the repository directly by executing the following commands in a command shell (assuming you have git installed):
# You must have git installed to clone repositories
git clone https://github.com/swimlane/atomic-operator.git
cd atomic-operator
python setup.py install
I highly recommend that you read atomic-operator
’s documentation and check out its GitHub repository.
Once you have atomic-operator
installed, you’ll want to ensure you have a local copy of the Atomic Red Team repository containing the atomics directory. If you do not have this on your local system, then you can run atomic-operator get_atomics
in your favorite shell to download the repository.
If you already have the atomic-red-team
repository on your system, then you can provide a path to that repo when you use the run command—more on that in a bit.
Besides the method above, there’s only one other direct interface and that is run
. This interface is how you will run atomics locally or remotely. You can checkout the help by typing:
atomic-operator run -- --help
# be mindful of the double -- before --help
There are many parameters available when using the run command. Below is a simple list of the available options, but you can find more information about each one on the Atomic Operator homepage.
Parameter name | Type | Default | Description |
---|---|---|---|
Parameter name:
| Type: list | Default: all | Description : one or more defined techniques by |
Parameter name:
| Type: list | Default: none | Description : one or more atomic test GUIDs |
Parameter name:
| Type: str | Default:
| Description : The path of atomic tests |
Parameter name:
| Type: bool | Default: false | Description : whether or not to check for prereq dependencies ( |
Parameter name:
| Type: bool | Default: false | Description : whether or not you want to retrieve prerequisites |
Parameter name:
| Type: bool | Default: false | Description : whether or not you want to run cleanup command(s) |
Parameter name:
| Type: bool | Default: false | Description : whether or not you want to copy any related source ( |
Parameter name:
| Type: int | Default: true | Description : time duration for each command before timeout |
Parameter name:
| Type: bool | Default: 20 | Description : whether or not you want to output details about tests being run |
Parameter name:
| Type: bool | Default: false | Description : whether you want to prompt for input arguments for each test |
Parameter name:
| Type: bool | Default: false | Description : whether or not you want to return atomics instead of running them |
Parameter name:
| Type: str | Default: false | Description : a path to a |
Parameter name:
| Type: list | Default: none | Description : a list of one or more remote hosts to run a test on |
Parameter name:
| Type: str | Default: none | Description : username for authentication of remote connections |
Parameter name:
| Type: str | Default: none | Description : password for authentication of remote connections |
Parameter name:
| Type: str | Default: none | Description : a path to a SSH Key for authentication of remote connections
|
Parameter name:
| Type: str | Default: none | Description : a private SSH key string used for authentication of remote connections |
Parameter name:
| Type: bool | Default: false | Description : whether or not to verify SSL when connecting over RDP (Windows) |
Parameter name:
| Type: int | Default: 22 | Description : SSH port for authentication of remote connections |
Parameter name:
| Type: int | Default: 5 | Description : SSH timeout for authentication of remote connections. |
Parameter name:
| Type: dict | Default: none | Description : If additional flags are passed into the run command, then we will attempt to match them with defined inputs within atomic tests and replace their value with the provided value |
By way of demonstration, you can paste the following command into your terminal and run it. It will run all relevant atomics associated with T1016: System Network Configuration Discovery on your local system. Note: As you’ll see in the gif below, we ran this test on a Mac, so atomic-operator skips all non macOS tests.
atomic-operator run --techniques "T1016"
And here’s how you would run a specific atomic test remotely on a host:
atomic-operator run --test_guids 'dfb50072-e45a-4c75-a17e-a484809c8553' --hosts '192.168.10.10' --username 'root' --password ‘password' --get_prereqs --check_prereqs --copy_source_files
If you want to use atomic-operator
to run specific tests on specific hosts, then you can do so by passing in a configuration file using the --config_file
parameter. Within this configuration file you can define which tests to run, specify optional input arguments (and their values), and provide one or more inventory objects with the correct credentials to those hosts. The details about the configuration file can be found here.
Dive in!
When I was creating atomic-operator, I wanted a framework that was flexible enough to fit most of my needs, and I hope that it will meet yours as well. Atomic-operator is open source, so, if it doesn’t meet your needs, you can contribute to the project. Otherwise, if you have any questions or issues, please feel free to create an issue in the repository. Additionally, you can reach out to me on the Atomic Red Team Slack at @MSAdministrator or on Twitter.