AWS Detection Engineering with Grimoire

Grimoire for AWS Detection Engineering

In a prior article, I showed you how to get started with a tool called Stratus Red Team to simulate adversaries by executing attacks against your cloud environments.

Grimoire is another open source tool created by the same person — Christophe Tafani-Dereeper — and you can use it to generate datasets of cloud audit logs for common attacks.

What this means is we can use it with a tool like Stratus Red Team to execute attacks, and Grimoire will inject a unique user agent containing a UUID so that it can then poll CloudTrail logs to retrieve the logs caused by the detonation, and it will stream those results into your terminal or into a file.

You can also use it with the AWS CLI interactive shell if you’d prefer to manually execute attacks — you don’t have to use it with Stratus Red Team. I’ll show you both ways in this article.

Installing and configuring Grimoire

You can install Grimoire either directly with Go since it’s made in Go:

go install -v github.com/datadog/grimoire/cmd/grimoire@latest

Or you can use pre-built binaries from the releases page.

Or you can use Homebrew, which is what I did for this video on my Mac.

brew tap datadog/grimoire https://github.com/DataDog/grimoire
brew install datadog/grimoire/grimoireCode language: JavaScript (javascript)

After that, all you have to do is authenticate your AWS CLI and set a default region.

❯ aws configure --profile demo

❯ export AWS_PROFILE=demo

❯ export AWS_REGION=us-east-1
Code language: JavaScript (javascript)

You can use it with the default profile (skip the --profile demo and AWS_PROFILE export), or you can set a custom profile and then export the profile name.

After that make sure you export the region or it will complain and not work.

Of course if you want to use it with Stratus Red Team, you’ll need to make sure that’s installed and fully functional (stratus —help)— but I won’t show how here since I already did in the prior post. Refer to that if you need help.

Using Grimoire with Stratus Red Team

Alright so once you’ve installed it, using it is actually really easy:

❯ grimoire help
   ____          _                       _
  / ___|  _ __  (_)  _ __ ___     ___   (_)  _ __    ___
 | |  _  | '__| | | | '_ ` _ \\   / _ \\  | | | '__|  / _ \\
 | |_| | | |    | | | | | | | | | (_) | | | | |    |  __/
  \\____| |_|    |_| |_| |_| |_|  \\___/  |_| |_|     \\___|

Usage:
  grimoire [command]

Available Commands:
  help             Help about any command
  shell            
  stratus-red-team 

Flags:
  -v, --debug            Enable debug logging
      --disable-banner   Disable Grimoire ASCII-art banner
  -h, --help             help for grimoire

Use "grimoire [command] --help" for more information about a command.
Code language: JavaScript (javascript)

I’m going to first use it with Stratus Red Team, and I’ll do that by typing in:

❯ grimoire help stratus-red-team
   ____          _                       _
  / ___|  _ __  (_)  _ __ ___     ___   (_)  _ __    ___
 | |  _  | '__| | | | '_ ` _ \\   / _ \\  | | | '__|  / _ \\
 | |_| | | |    | | | | | | | | | (_) | | | | |    |  __/
  \\____| |_|    |_| |_| |_| |_|  \\___/  |_| |_|     \\___|

Usage:
  grimoire stratus-red-team [flags]

Examples:
Detonate a Stratus Red Team attack technique

Flags:
      --attack-technique string         Stratus Red Team attack technique to detonate. Use 'stratus list' to list available attack techniques or browse <https://stratus-red-team.cloud/attack-techniques/list/>.
      --exclude-events strings          Exclude specific CloudTrail events. Comma-separated and using the format 'service:Operation' (e.g. 's3:PutObject')
      --extend-search-window duration   Extend the end of the search window by this amount of time
  -h, --help                            help for stratus-red-team
      --include-events strings          Only consider specific CloudTrail events. Comma-separated and using the format 'service:Operation' (e.g. 's3:PutObject')
      --interval duration               Interval to check for new events. You might need to increase this if you're hitting AWS API rate limits (default 5s)
      --max-events int                  Maximum number of events to retrieve before exiting
      --only-write-events               Only consider write events and ignore read-only ones
  -o, --output string                   Output file to write CloudTrail events to. Grimoire will overwrite the file if it exists, and create otherwise.
      --timeout duration                Maximum time to wait for events to appear in CloudTrail logs (default 15m0s)

Global Flags:
  -v, --debug            Enable debug logging
      --disable-banner   Disable Grimoire ASCII-art banner
Code language: PHP (php)

Using that information, we can write a command like this:

❯ grimoire stratus-red-team -o /tmp/logs --attack-technique aws.persistence.iam-create-backdoor-role

We can specify -o /tmp/logs which is where Grimoire will output the log files from CloudTrail.

Then we specify the --attack-technique that we want to execute. There are a bunch we could use, but I’ll use aws.persistence.iam-create-backdoor-role – -what we use here doesn’t really matter since we’re not focusing on that part of the attack.

Before I execute the attack, I want to tail the log file to view the logs as they stream in. To do that, I’ll first need to create the file if it doesn’t already exist, which is fine because Grimoire will overwrite it anyway:

❯ touch /tmp/logs

❯ tail -f /tmp/logs

Let’s execute now and see what happens:

❯ grimoire stratus-red-team -o /tmp/logs --attack-technique aws.persistence.iam-create-backdoor-role
   ____          _                       _
  / ___|  _ __  (_)  _ __ ___     ___   (_)  _ __    ___
 | |  _  | '__| | | | '_ ` _ \\   / _ \\  | | | '__|  / _ \\
 | |_| | | |    | | | | | | | | | (_) | | | | |    |  __/
  \\____| |_|    |_| |_| |_| |_|  \\___/  |_| |_|     \\___|

INFO[2024-10-29 20:34:27] Warming up Stratus Red Team attack technique aws.persistence.iam-create-backdoor-role 
INFO[2024-10-29 20:34:27] Detonating Stratus Red Team attack technique aws.persistence.iam-create-backdoor-role 
INFO[2024-10-29 20:34:29] Stratus Red Team attack technique successfully detonated 
INFO[2024-10-29 20:34:29] Searching for CloudTrail events...           
INFO[2024-10-29 20:34:29] Cleaning up Stratus Red Team detonation in the background 
Code language: JavaScript (javascript)

Meanwhile, in the other tab, so far it looks like this:

❯ tail -f /tmp/logs
[]

Keep in mind that CloudTrail is not a real-time logging service, and so there are delays. That’s why by default Grimoire has a timeout duration of 15 minutes where it will wait for up to 15 minutes for events to appear. You can change that though with the flag --timeout duration but that should be more than enough.

So I’ll wait a few minutes and be right back.

Viewing results

After about 2 minutes, I was able to start to see some logs:

❯ tail -n 30 -f /tmp/logs
[][
   {
      "awsRegion": "us-east-1",
      "eventCategory": "Management",
      "eventID": "5d585f44-d178-40ca-831c-7fbe8557c395",
      "eventName": "AttachRolePolicy",
      "eventSource": "iam.amazonaws.com",
      "eventTime": "2024-10-30T02:34:29Z",
      "eventType": "AwsApiCall",
      "eventVersion": "1.10",
      "managementEvent": true,
      "readOnly": false,
      ...SNIP...
Code language: JavaScript (javascript)

This tells us quite a bit, but primarily that 2 actions took place related to this attack:

  • CreateRole
  • AttachRolePolicy

CreateRole will, of course, create the IAM role. It also provides it with a trust policy that allows assuming it from an attacker-controlled account. Though this is a simulation so it’s a fake external account ID and there’s also a DenyAll permission boundary for good measure.

The AttackRolePolicy attaches the arn:aws:iam::aws:policy/AdministratorAccess managed policy.

Of course we get a lot more information about these actions, including the eventTime, account ID, requestParameters, sourceIPAddress, userAgent, userIdentity, etc.., etc…

This is all valuable information for detecting threats, and for responding to incidents. In fact if you’re interested in learning more about incident response with CloudTrail, check out our course on Cybr called “Incident Response with CloudTrail Lake and Athena.”

Using Grimoire with the AWS CLI / Interactive Shell

Like I said earlier, we can use Grimoire with the AWS CLI instead if we want to execute a manual attack.

Let’s exit interactive mode in our other terminal window with Ctrl + C.

Then we can start by using the command:

❯ grimoire shell -o -
   ____          _                       _
  / ___|  _ __  (_)  _ __ ___     ___   (_)  _ __    ___
 | |  _  | '__| | | | '_ ` _ \\   / _ \\  | | | '__|  / _ \\
 | |_| | | |    | | | | | | | | | (_) | | | | |    |  __/
  \\____| |_|    |_| |_| |_| |_|  \\___/  |_| |_|     \\___|

INFO[2024-10-29 20:44:27] Grimoire will now run your shell and automatically inject a unique identifier to your HTTP user agent when using the AWS CLI 
INFO[2024-10-29 20:44:27] You can use the AWS CLI as usual. Press Ctrl+D or type 'exit' to return to Grimoire. 
INFO[2024-10-29 20:44:27] When you exit the shell, Grimoire will look for the CloudTrail events that your commands have generated. 
INFO[2024-10-29 20:44:27] Press ENTER to continue                      Code language: PHP (php)

This time I’m using -o - to print logs in the terminal as they come in.

Go ahead and press ENTER, which will take you back to what looks like your normal shell, except your commands are going to be monitored by Grimoire. So let’s enter a few:

❯ aws sts get-caller-identity   
{
    "UserId": "AROAVYQBCJKC6NYYCWUC7:christophe",
    "Account": "396212980357",
    "Arn": "arn:aws:sts::396212980357:assumed-role/AWSReservedSSO_AdministratorAccess_f5e2808a1e330887/christophe"
}

❯ aws s3 ls
2023-11-15 09:44:22 cloudtrail-events-history-demo-cybr

❯ aws ec2 describe-instances
{
    "Reservations": []
}

Code language: JavaScript (javascript)

And then we can type and submit exit

exit
INFO[2024-10-29 20:44:52] Welcome back to Grimoire!                    
INFO[2024-10-29 20:44:52] Searching for CloudTrail events...   

Code language: CSS (css)

Once you exit, Grimoire will start searching for CloudTrail events, and then stream them in our terminal:

INFO[2024-10-29 20:50:31] Found event: sts:GetCallerIdentity           
{
   "awsRegion": "us-east-1",
   "eventCategory": "Management",
   "eventID": "becc363b-441a-4610-80a7-e7190e692156",
   "eventName": "GetCallerIdentity",
   "eventSource": "sts.amazonaws.com",
   "eventTime": "2024-10-30T02:48:40Z",
   "eventType": "AwsApiCall",
   "eventVersion": "1.08",
   "managementEvent": true,
   "readOnly": true,
   ...SNIP...
   "userAgent": "aws-cli/2.18.13 md/awscrt#0.22.0 ua/2.0 os/macos#23.6.0 md/arch#arm64 lang/python#3.12.7 md/pyimpl#CPython exec-env/grimoire_4437fe7b-0cde-407e-84d4-e7bbb4cdc489 cfg/retry-mode#standard md/installer#source md/prompt#off md/command#sts.get-caller-identity",
   ...SNIP...
}

Code language: JavaScript (javascript)

Pretty cool, right?

We can exit with Ctrl + C.

Using Grimoire with scripts

Instead of an interactive shell, you can even write scripts and pass in that script, and Grimoire will execute the script.

So let’s write one really quickly:

❯ vim /tmp/script.sh
aws sts get-caller-identity

❯ grimoire shell --script /tmp/script.sh
   ____          _                       _
  / ___|  _ __  (_)  _ __ ___     ___   (_)  _ __    ___
 | |  _  | '__| | | | '_ ` _ \\   / _ \\  | | | '__|  / _ \\
 | |_| | | |    | | | | | | | | | (_) | | | | |    |  __/
  \\____| |_|    |_| |_| |_| |_|  \\___/  |_| |_|     \\___|

INFO[2024-10-29 20:55:36] Running detonation script: /tmp/script.sh    
+/tmp/script.sh:1> aws sts get-caller-identity
{
    "UserId": "AROAVYQBCJKC6NYYCWUC7:christophe",
    "Account": "396212980357",
    "Arn": "arn:aws:sts::396212980357:assumed-role/AWSReservedSSO_AdministratorAccess_f5e2808a1e330887/christophe"
}
INFO[2024-10-29 20:55:37] Searching for CloudTrail events... 

Code language: JavaScript (javascript)

Conclusion & Workshop

All of this is mentioned in the GitHub documentation for the tool, so you can reference it for more information and for more advanced usage, but this tutorial should get you started and should help you see the benefit!

If you have any questions let me know in the comments below, but otherwise, play around with it some more and have fun!

Also wanted to mention that I’m hosting a workshop with the author of this tool so if you’d like to join you can RSVP here, but even if you’re reading this after we’ve already hosted it, we will make it available for replay at that same URL, so check it out!

Adversary Emulation for the Cloud with Christophe Tafani-Dereeper webinar

Thanks for reading and see you in the next article!

Related Articles

Responses

Your email address will not be published. Required fields are marked *