feat: T1526 discovery (AWS and Azure) (#3023)

Co-authored-by: Bhavin Patel <bhavin.j.patel91@gmail.com>
This commit is contained in:
ryananicholson
2025-01-03 17:27:52 -05:00
committed by GitHub
parent b7a6dd6c14
commit 8bf0d8dd69
3 changed files with 336 additions and 0 deletions
+95
View File
@@ -51,3 +51,98 @@ atomic_tests:
cleanup_command: | cleanup_command: |
remove-item #{output_directory} -recurse -force -erroraction silentlycontinue remove-item #{output_directory} -recurse -force -erroraction silentlycontinue
name: powershell name: powershell
- name: AWS - Enumerate common cloud services
description: |
Upon successful execution, this test will enumerate common resources that are contained within a valid AWS account.
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: ""
regions:
description: AWS regions
type: string
default: us-east-1,us-east-2,us-west-1,us-west-2
output_directory:
description: Directory to output results to
type: string
default: $env:TMPDIR/aws_discovery
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
executor:
command: |
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}"
name: powershell
- name: Azure - Enumerate common cloud services
description: |
Upon successful execution, this test will enumerate common resources that are contained within a valid Azure subscription.
supported_platforms:
- iaas:azure
input_arguments:
client_id:
description: Azure AD client ID
type: string
default:
client_secret:
description: Azure AD client secret
type: string
default:
tenant_id:
description: Azure AD tenant ID
type: string
default:
cloud:
description: Azure cloud environment
type: string
default: AzureCloud
output_directory:
description: Directory to output results to
type: string
default: $env:TMPDIR/azure_discovery
dependency_executor_name: powershell
dependencies:
- description: |
The Az module must be installed.
prereq_command: |
try {if (Get-InstalledModule -Name Az -ErrorAction SilentlyContinue) {exit 0} else {exit 1}} catch {exit 1}
get_prereq_command: |
Install-Module -Name Az -Force
executor:
command: |
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}"
name: powershell
+114
View File
@@ -0,0 +1,114 @@
Import-Module AWSPowerShell
function Set-AWSAuthentication {
param (
[string]$AccessKey,
[string]$SecretKey,
[string]$SessionToken,
[string]$Regions,
[string]$AWSProfile
)
if ($SessionToken -eq "" -and $AWSProfile -eq "") {
Set-AWSCredential -AccessKey $AccessKey -SecretKey $SecretKey -StoreAs "atomic"
}
elseif ($SessionToken -ne "" -and $AWSProfile -ne "") {
Set-AWSCredential -AccessKey $AccessKey -SecretKey $SecretKey -SessionToken $SessionToken -StoreAs "atomic"
}
elseif ($AWSProfile -ne "") {
Set-AWSCredential -ProfileName $AWSProfile -StoreAs "atomic"
}
}
function Get-AWSDiscoveryData {
param(
[string]$OutputDirectory,
[string]$Regions
)
if (-not (Test-Path $OutputDirectory)) {
$null = New-Item -ItemType Directory -Path $OutputDirectory
}
# Account Discovery
"AccountID" | Out-File -FilePath $OutputDirectory/account.csv
Get-AWSAccountInfo | Out-File $OutputDirectory/account.csv -Append
# EC2 Discovery
"Name,Id,PublicIP,Size" | Out-File -FilePath $OutputDirectory/instances.csv
foreach ($region in $Regions.Split(",")) {
Get-EC2Discovery -Region $region | Out-File $OutputDirectory/instances.csv -Append
}
# S3 Bucket Discovery
"BucketName,CreationDate" | Out-File -FilePath $OutputDirectory/buckets.csv
Get-S3BucketDiscovery | Out-File $OutputDirectory/buckets.csv -Append
# IAM User Discovery
"UserName,CreateDate,PasswordLastUsed" | Out-File -FilePath $OutputDirectory/users.csv
Get-IAMUserDiscovery | Out-File $OutputDirectory/users.csv -Append
Write-Host "Discovery data saved to $OutputDirectory"
}
function Get-AWSAccountInfo {
$account = Get-STSCallerIdentity
$accountID = $account.Account
return $accountID
}
function Get-EC2Discovery {
param(
[string]$Region
)
Set-DefaultAWSRegion -Region $region
$instances = Get-EC2Instance | Select-Object -ExpandProperty Instances
$output = $null
foreach($instance in $instances) {
$instanceName = $instance.Tags | Where-Object { $_.Key -eq "Name" } | Select-Object -ExpandProperty Value
$instanceId = $instance.InstanceId
$instancePublicIp = $instance.PublicIpAddress
$instanceSize = $instance.InstanceType
$output += "$instanceName,$instanceId,$instancePublicIp,$instanceSize,$Region`n"
}
if ($null -ne $output) {
$output = $output.Substring(0, $output.Length - 1)
}
return $output
}
function Get-S3BucketDiscovery {
$buckets = Get-S3Bucket
foreach($bucket in $buckets) {
$bucketName = $bucket.BucketName
$creationDate = $bucket.CreationDate
$output += "$bucketName,$creationDate`n"
}
if ($null -ne $output) {
$output = $output.Substring(0, $output.Length - 1)
}
return $output
}
function Get-IAMUserDiscovery {
$users = Get-IAMUser
foreach($user in $users) {
$userName = $user.UserName
$createDate = $user.CreateDate
$passwordLastUsed = $user.PasswordLastUsed
$output += "$userName,$createDate,$passwordLastUsed`n"
}
if ($null -ne $output) {
$output = $output.Substring(0, $output.Length - 1)
}
return $output
}
function Remove-BlankFiles {
param (
[string]$OutputDirectory
)
$files = Get-ChildItem -Path $OutputDirectory
foreach ($file in $files) {
$lineCount = (Get-Content -Path $file.FullName).Count
if ($lineCount -eq 1) {
$null = Remove-Item -Path $file.FullName
}
}
}
+127
View File
@@ -0,0 +1,127 @@
function Set-AzureAuthentication {
param (
[string]$TenantID,
[string]$ClientID,
[string]$ClientSecret,
[string]$Environment
)
$SecurePassword = ConvertTo-SecureString -String $ClientSecret -AsPlainText -Force
$Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $ClientID, $SecurePassword
$null = Connect-AzAccount -ServicePrincipal -TenantId $TenantID -Credential $Credential -Environment $Environment -WarningAction:SilentlyContinue
}
function Get-AzureDiscoveryData {
param(
[string]$Environment,
[string]$OutputDirectory
)
if (-not (Test-Path $OutputDirectory)) {
$null = New-Item -ItemType Directory -Path $OutputDirectory
}
# Subscription Discovery
"SubscriptionID" | Out-File -FilePath $OutputDirectory/subscriptions.csv
$subscriptions = Get-AzureSubscriptions
$subscriptions | Out-File $OutputDirectory/subscriptions.csv -Append
$subscriptions = $subscriptions -split "`n"
# VM Discovery
"Name,Id,PublicIP,Size" | Out-File -FilePath $OutputDirectory/vms.csv
Get-AzureVMDiscovery -Subscriptions $subscriptions | Out-File $OutputDirectory/vms.csv -Append
# Storage Account Discovery
"Name,ResourceGroup,Location" | Out-File -FilePath $OutputDirectory/storage.csv
Get-AzureStorageDiscovery -Subscriptions $subscriptions | Out-File $OutputDirectory/storage.csv -Append
# Key Vault Discovery
"Name,ResourceGroup,Location" | Out-File -FilePath $OutputDirectory/keyvaults.csv
Get-AzureKeyVaultDiscovery -Subscriptions $subscriptions | Out-File $OutputDirectory/keyvaults.csv -Append
Write-Host "Discovery data saved to $OutputDirectory"
}
function Get-AzureSubscriptions {
$subscriptions = Get-AzSubscription | Select-Object -ExpandProperty Id
foreach ($subscription in $subscriptions) {
$output += "$subscription`n"
}
if ($null -ne $output) {
$output = $output.Substring(0, $output.Length - 1)
}
return $output
}
function Get-AzureVMDiscovery {
param (
[string[]]$Subscriptions
)
foreach ($subscription in $subscriptions) {
$null = Set-AzContext -Subscription $subscription
$vms = Get-AzVM
foreach ($vm in $vms) {
$vmName = $vm.Name
$vmId = $vm.Id
$nicId = ($vm | Select-Object -ExpandProperty NetworkProfile).NetworkInterfaces[0].Id
$pipId = (Get-AzNetworkInterface -ResourceId $nicId | Select-Object -ExpandProperty IpConfigurations | Select-Object -ExpandProperty PublicIpAddress).Id
$pipName = ($pipId -split "/")[-1]
$vmPublicIP = (Get-AzPublicIpAddress -Name $pipName).IpAddress
$vmSize = $vm.HardwareProfile.VmSize
$output += "$vmName,$vmId,$vmPublicIP,$vmSize`n"
}
if ($null -ne $output) {
$output = $output.Substring(0, $output.Length - 1)
}
}
return $output
}
function Get-AzureStorageDiscovery {
param (
[string[]]$Subscriptions
)
foreach ($subscription in $subscriptions) {
$null = Set-AzContext -Subscription $subscription
$storageAccounts = Get-AzStorageAccount
foreach ($storageAccount in $storageAccounts) {
$storageAccountName = $storageAccount.StorageAccountName
$resourceGroup = $storageAccount.ResourceGroupName
$location = $storageAccount.Location
$output += "$storageAccountName,$resourceGroup,$location`n"
}
if ($null -ne $output) {
$output = $output.Substring(0, $output.Length - 1)
}
}
return $output
}
function Get-AzureKeyVaultDiscovery {
param (
[string[]]$Subscriptions
)
foreach ($subscription in $subscriptions) {
$null = Set-AzContext -Subscription $subscription
$keyVaults = Get-AzKeyVault
foreach ($keyVault in $keyVaults) {
$keyVaultName = $keyVault.VaultName
$resourceGroup = $keyVault.ResourceGroupName
$location = $keyVault.Location
$output += "$keyVaultName,$resourceGroup,$location`n"
}
if ($null -ne $output) {
$output = $output.Substring(0, $output.Length - 1)
}
}
return $output
}
function Remove-BlankFiles {
param (
[string]$OutputDirectory
)
$files = Get-ChildItem -Path $OutputDirectory
foreach ($file in $files) {
$lineCount = (Get-Content -Path $file.FullName).Count
if ($lineCount -eq 1) {
$null = Remove-Item -Path $file.FullName
}
}
}