This post documents the process to create and test a new attack technique for Stratus Red Team, a threat emulation tool built in Terraform and Go.
Introduction
I recently had the opportunity to contribute to Stratus Red Team as a part of my research into Entra ID administrative units.
I’ve found open-source contributions can feel daunting if you haven’t been through them before. Based on that, my hope is that this guide can be a friendly nudge for those new to contributing to projects.
The following guide is meant as both:
- A direct reference how to contribute to Stratus Red Team
- An example of what contributing to open-source can look like
The rest of this post will be a fairly intensive walkthrough of this process.
If you’re already familiar with Stratus and open-source contributions, you can skip ahead to “#4. Creating a new attack technique”.
1. Get familiar with Stratus Red Team
Details on Stratus Red Team (a.k.a. “Stratus” for the rest of this post) can be found in its GitHub repository and website:
- https://github.com/DataDog/stratus-red-team
- https://stratus-red-team.cloud/user-guide/getting-started/
Review details on Stratus states (under the documentation’s “Getting Started” and “Examples”) sections, as these cover a full example of using Stratus to emulate a technique.
At this stage, it’s also a good idea to run Stratus against your test environment if you haven’t already. If you don’t already have a test environment, create an account in your cloud(s) of choice:
You can follow the Stratus intro blog to set up, review, and detonate techniques of interest.
2. Project structure
Now that we’ve seen Stratus in action, let’s review the states of Stratus in the context of what code is used to run them:
- Warm Up: Terraform. Create attack prerequisites.
- Detonate: Go. Execute the attack.
- Revert: Go. Undo the attack so it can be detonated again.
- Clean Up: Terraform. Destroy attack prerequisites.
Individual techniques are stored under https://github.com/DataDog/stratus-red-team/tree/main/v2/internal/attacktechniques
, organized by platform and attack type (e.g., persistence
, execution
, etc) folders.
For example, looking at the path for “vm-custom-script-extension”:
azure
folder: All techniques forazure
.execution
folder: All MITRE ATT&CK Tactics of theexecution
category.vm-custom-script-extension
folder: The folder for this specific technique.main.go
: Go code containing functions required to initialize (init
),detonate
, andrevert
this technique.main.tf
: Terraform code containing all prerequisite resources used inwarmup
andcleanup
stages.
3. Development prerequisites
Forks
Before starting any work, we’ll create a fork of Stratus. GitHub’s documentation on forks is very clear and helpful for those new to them. If you’re new to this, I recommend reviewing this guide:
This process can be started from the “Fork” menu in the Stratus repository:
Creating your fork through Github will allow you to easily sync new upstream changes from Stratus into your fork as you’re working.
Once you’ve created your fork, create a local copy:
git clone https://github.com/[your-username]/stratus-red-team
Developer’s notes
You’ll also want to read the project’s own notes on contribution and philosophy:
This is important to ensure any techniques you contribute meet the project’s standards and are likely to be accepted. In particular, Stratus values techniques being as granular as possible. This means PRs that submit one technique at a time.
Issues
Project issues are where suggestions on new techniques and improvements are stored:
Tags within this list can help you find good ideas to start with. For example:
Planning
Choose a technique to try out. The issues above are a great place to start!
Define for the selected technique:
- Warmup/Clean Up: What resources or configurations need to exist as prerequisites for an attack (for an attacker to exploit)? These will be deployed in Terraform.
- Detonate: What specific actions does the attack consist of? These actions will be performed in Go.
- Revert: How can the attack be undone? For example: If an attacker created an external link to share data, then un-sharing the link would be the revert step. These actions will be performed in Go.
You’ll need these notes for development, as well as documentation of the technique.
4. Creating a new attack technique
Configure a new technique
Let’s start by creating a new “placeholder technique” to build on in later steps, and ensuring it builds into Stratus. Perform these steps in your development environment of choice (e.g. Visual Studio Code, command line, whatever suits you).
- Create a new branch off of your fork:
git checkout -b [branch-name]
- Create a new folder for your technique under
/main/v2/internal/attacktechniques/[cloud]/[attack-type]/[technique-name]
. It’s best to pick a name that’s action-oriented, and follows the example of current techniques. - For now, copy an existing technique’s
main.go
andmain.tf
files into this folder to act as placeholders to be modified into your new technique. Your final structure should look something like the below: - Under
init()
in your new technique’smain.go
, modify theID
,FriendlyName
,Platform
andMitreAttackTactics
to match your new technique’s name and MITRE ATT&CK Tactic (category): - In
/main/v2/internal/attacktechniques/main.go
, add the path of your new technique:"github.com/datadog/stratus-red-team/v2/internal/attacktechniques/[your-path]"
. This creates a reference to your new technique, so the main code of Stratus can find it: - In your terminal,
cd
to the root project folder (stratus-red-team
) and runmake
. This will build a new version of Stratus, with your new technique included. - Run
./bin/stratus status
and ensure your new technique shows up in the list. (./bin/stratus
will ensure the locally built version of Stratus is in use, and not another version.)
At this stage, you should have all the files you need in place to begin developing a new attack technique! Now we need to update it to do something new.
There are two major files that require updating: main.tf
, and main.go
. We’ll split this out by stage to make it simpler to effectively create our attack technique.
Create Terraform prerequisites (warmup)
Creating initial infrastructure in Terraform means that we can easily test our main.tf
outside of the Stratus project code. This will focus our efforts on just prerequisites prior to integrating the code back into the attack technique.
- Create a
testing
folder outside of your Stratus project folder, and copymain.tf
into it. - Update the
main.tf
file to include the prerequisites you’ve identified: - Run
terraform init
+terraform apply
to test your infrastructure out. - Ensure naming of techniques, resources, and accounts align with those of other techniques. This is a great opportunity to review similar techniques, and see how they’ve handled this.
- Include an
output
block for any variables that will be needed in yourdetonate
andrevert
stages. Example: Outputs for an Entra ID technique. - Once you’re comfortable with your code, remember to clean up with
terraform destroy
. - Run
terraform fmt -recursive
to ensure formatting is clean. This is a requirement for Stratus contributions.
When you’re confident that your warmup
stage is ready to go, copy it back into the [technique-name]
directory you’ve created (/main/v2/internal/attacktechniques/[cloud]/[attack-type]/[technique-name]
).
Create technique in Go (detonate, revert)
- Modify
main.go
to create (detonate
) andrevert
any attack infrastructure and commands.- If you’re newer to Go, take time to review patterns and methods already in use elsewhere in Stratus. How have similar problems been solved in the codebase? Does your code align with their formatting?
- Update messaging and error handling to ensure the technique will be clear and well-handled.
- Review previous techniques for your target platform to see what SDKs they use, and documentation for those packages. (Example: MS Graph APIs have a tab for each SDK, such as this one on Get Users.)
- Ensure
IsIdempotent
andIsSlow
(if the technique takes a long time) align with your technique.
- From the directory
stratus-red-team/v2
, rungo get [path]@[version]
for any additional dependencies to ensurego.mod
andgo.sum
are up to date.
Update documentation (init, .md)
- Fully update
init()
inmain.go
to match your technique’s category, name, friendly name, description, detection, and other relevant fields. - Run
make docs
to automatically add documentation tostratus-red-team/docs/attack-techniques/[platform]
based on your technique’s documentation inmain.go
.
5. Testing your technique
Build and run
- From the directory
stratus-red-team
, runmake
to debug and compile your version of Stratus. - Run
./bin/stratus detonate [technique-name]
fromstratus-red-team
to ensure your technique runs. - Repeat these steps as needed until it’s working as expected!
- Remember to
cleanup
your test attacks, especially if you plan on making any modifications to yourmain.tf
file.- This is better than manually destroying any state or resources, which can mess with Terraform.
- If you need to manually reset your technique’s Terraform state, it can be found under
$HOME/.stratus-red-team/[technique-name]/
.
Check your work
- Read over everything you’ve changed in
main.tf
,main.go
, and your technique documentation. Some common checks I make are:- Is anything left over from a previous attack technique? Descriptions, environment variables, and other details should all be updated to your new technique.
- Did you include all your reference links?
- Is your warm-up stage just prerequisites?
- Is your detonate stage just attacker activities?
- Does the full attack flow work as expected? (e.g.
warmup
,detonate
,revert
,cleanup
?) - Did you accidentally change any irrelevant files? (Discard changes on them.)
- Are you consistently using the same methods for output and warnings? Do they line up with other Stratus methods?
- Ensure your work is up to date with the main branch:
- Commit and push your work to your fork’s branch.
- In the Github page for your fork, at the top of the page, does your fork show as up to date with
DataDog/stratus-red-team:main
? Use “sync fork” option if it is not up to date, and resolve any conflicts. - Remember to
git pull
your remote sync to your local system before making any more changes!
6. PR process
Make your request
When you’re ready to go, the Github page for your fork will guide you through opening a pull request (PR) against the main project.
You can start this process by using “Contribute,” then “Open pull request”:
Fill out details of your request. Include any background someone would need. For example:
- Background on why you’ve implemented the technique
- Open issues the technique addresses
- Details on why you’ve chosen certain actions for the
warmup
ordetonate
stages
Respond to feedback
You’ll likely receive some comments from the project maintainer to understand your contribution and ensure it’s up to the project’s standards. This is completely normal!
Be open to feedback. Try to keep in mind that while your work is a valued contribution, it’s still a contribution to someone else’s codebase. Their preferences and standards should come first in how your work is structured.
Your PR will automatically update to include any new contributions you make based on feedback.
Merge!
Once approved, you should be ready to merge in your change! At this stage, the process is complete. This is a great time to capture any notes on what you’ve learned for next time.
Conclusion
We’ve now covered the full process of contributing a new attack technique to Stratus Red Team! While this post was specific to Stratus, the overall workflow of understanding first the tool, then the project, and finally looking to mirror its codebase in a new contribution can be applied to nearly any project.
I hope you found this helpful! If you have any questions, feel free to reach out.