T1619 - Cloud Storage Object Discovery
Description from ATT&CK (opens in a new tab)
Adversaries may enumerate objects in cloud storage infrastructure. Adversaries may use this information during automated discovery to shape follow-on behaviors, including requesting all or specific objects from cloud storage. Similar to File and Directory Discovery (opens in a new tab) on a local host, after identifying available storage services (i.e. Cloud Infrastructure Discovery (opens in a new tab)) adversaries may access the contents/objects stored in cloud infrastructure.
Cloud service providers offer APIs allowing users to enumerate objects stored within cloud storage. Examples include ListObjectsV2 in AWS (Citation: ListObjectsV2) and List Blobs in Azure(Citation: List Blobs) .
Atomic Tests
Atomic Test #1 - AWS S3 Enumeration
This test will enumerate all the S3 buckets in the user account and lists all the files in each bucket.
Supported Platforms: Iaas:aws
auto_generated_guid: 3c7094f8-71ec-4917-aeb8-a633d7ec4ef5
Attack Commands: Run with sh
!
for bucket in "$(aws s3 ls | cut -d " " -f3)"; do aws s3api list-objects-v2 --bucket $bucket --output text; done
Dependencies: Run with sh
!
Description: Check if ~/.aws/credentials file has a default stanza is configured
Check Prereq Commands:
cat ~/.aws/credentials | grep "default"
Get Prereq Commands:
echo Please install the aws-cli and configure your AWS default profile using: aws configure
Atomic Test #2 - Azure - Enumerate Storage Account Objects via Shared Key authorization using Azure CLI
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.
Supported Platforms: Iaas:azure
auto_generated_guid: 070322a4-2c60-4c50-8ffb-c450a34fe7bf
Inputs:
Name | Description | Type | Default Value |
---|---|---|---|
output_file | Csv file path for results | path | $env:temp\T1619_storage_account_objects.csv |
Attack Commands: Run with powershell
!
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
Cleanup Commands:
Remove-Item -Path "#{output_file}" -Force -erroraction silentlycontinue
Write-Output "Removed #{output_file}"
Dependencies: Run with powershell
!
Description: Azure CLI must be installed
Check Prereq Commands:
try {if (Get-InstalledModule -Name Az -ErrorAction SilentlyContinue) {exit 0} else {exit 1}} catch {exit 1}
Get Prereq Commands:
Install-Module -Name Az -Force