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 on a local host, after identifying available storage services (i.e. Cloud Infrastructure Discovery) 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 [1] and List Blobs in Azure[2].
45th pctamong all ATT&CK techniques for number of groups
1 group has been recorded using this technique. Newest first; each entry carries MITRE’s procedure text and a link to the group’s full record. Click a name to filter the rules below.
Has used Amazon Simple Storage Service (S3) Browser and WinSCP to access S3 objects.1
created 2026-07-291 referenceaka UNC6240
All 1 groups for this technique
3 software entries are documented implementing this technique. MITRE files each as a tool or as malware; newest first, then by how many groups carry them.
MITRE names one behaviour worth catching for this technique and breaks it into 1 analytic, one per platform. Each carries the log sources it needs and the fields you tune per environment.
Detection Strategy for Cloud Storage Object Discovery
Enterprise
1 platform
AN1594 · IaaS
Detection of suspicious enumeration of cloud storage objects via API calls such as AWS S3 ListObjectsV2, Azure List Blobs, or GCP ListObjects. Correlate access with account role, user context, and prior authentication activity to identify anomalous usage patterns (e.g., unusual account, unexpected regions, or large-scale enumeration in short time windows).
Log sources
The data this analytic draws on. You do not need every component — each one you already collect covers part of it. Each links to its ATT&CK record.
Restrict granting of permissions related to listing objects in cloud storage to necessary accounts.
Tests4Executorspowershell 3 · sh 1Need elevation0 of 4Have prerequisites3Have cleanup3Platformsiaas:aws, iaas:azure
#
Test
Platform
Executor
Elevation
Prereqs
Cleanup
Ref
01
AWS S3 Enumeration
iaas:aws
sh
—
1
—
This test will enumerate all the S3 buckets in the user account and lists all the files in each bucket.
Attack Commandsrun with sh
for bucket in "$(aws s3 ls | cut -d " " -f3)"; do aws s3api list-objects-v2 --bucket $bucket --output text; done
Dependencies
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
GUID3c7094f8-71ec-4917-aeb8-a633d7ec4ef5
02
Azure - Enumerate Storage Account Objects via Shared Key authorization using Azure CLI
iaas:azure
powershell
—
1
Yes
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.
Inputs
Name
Description
Type
Default Value
output_file
Csv file path for results
path
$env:temp\T1619_storage_account_objects.csv
Attack Commandsrun 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
Azure - Scan for Anonymous Access to Azure Storage (Powershell)
iaas:azure
powershell
—
—
Yes
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
Inputs
Name
Description
Type
Default Value
base_name
Azure storage account name to test
string
T1619Test2
blob_name
Blob name to search for (optional)
string
—
output_file
File to output results to
string
$env:temp\T1619Test2.txt
container_name
Container name to search for (optional)
string
—
Attack Commandsrun with powershell
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
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/ .
Inputs
Name
Description
Type
Default Value
base
Azure blob keyword to enumerate (Example, storage account name)