feat: T1526 discovery (AWS and Azure) (#3023)
Co-authored-by: Bhavin Patel <bhavin.j.patel91@gmail.com>
This commit is contained in:
@@ -51,3 +51,98 @@ atomic_tests:
|
||||
cleanup_command: |
|
||||
remove-item #{output_directory} -recurse -force -erroraction silentlycontinue
|
||||
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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user