Detect Cloud Service Discovery in Splunk
Adversaries who have gained access to a cloud environment may enumerate cloud services, resources, and configurations to identify valuable targets, understand security controls, and plan follow-on actions. This includes enumerating Azure resources via Azure Resource Manager API, Microsoft Graph API calls to list applications and service principals, AWS service enumeration via Pacu or direct CLI, and discovery of security services such as GuardDuty, Defender for Cloud, CloudTrail, and logging configurations. Tools like Stormspotter, AADInternals, and ROADTools automate this reconnaissance and are commonly observed in pre-ransomware and espionage campaigns.
MITRE ATT&CK
- Tactic
- Discovery
- Technique
- T1526 Cloud Service Discovery
- Canonical reference
- https://attack.mitre.org/techniques/T1526/
SPL Detection Query
index=azure sourcetype="azure:activity" status=Succeeded
| where (lower(operationName) LIKE "%list%" OR lower(operationName) LIKE "%/read" OR lower(operationName) LIKE "%/get%")
| eval resource_type=mvindex(split(resourceId, "/"), 3)
| eval time_bucket=strftime(round(_time/600)*600, "%Y-%m-%dT%H:%M:%SZ")
| stats
count as operation_count,
dc(operationName) as distinct_ops,
dc(resource_type) as distinct_resource_types,
dc(subscriptionId) as distinct_subscriptions,
values(operationName) as operations,
values(resource_type) as resource_types
by caller, callerIpAddress, time_bucket
| where operation_count >= 20 OR distinct_resource_types >= 8
| eval risk_score=case(
distinct_resource_types >= 15, "Critical",
distinct_resource_types >= 8, "High",
operation_count >= 50, "High",
1=1, "Medium"
)
| eval enumeration_breadth=distinct_resource_types . " resource types, " . operation_count . " operations"
| table time_bucket, caller, callerIpAddress, operation_count, distinct_ops, distinct_resource_types, distinct_subscriptions, risk_score, enumeration_breadth, operations, resource_types
| sort - distinct_resource_types, - operation_count
| append [
search index=azure sourcetype="azure:aad:audit" category IN ("Core Directory", "ApplicationManagement", "Policy")
(operationName="Get servicePrincipal" OR operationName="List servicePrincipals"
OR operationName="Get application" OR operationName="List applications"
OR operationName="Get policy" OR operationName="List policies"
OR operationName="Get organization" OR operationName="Get directoryRole"
OR operationName="List directoryRoles" OR operationName="List roleAssignments")
| eval initiator=coalesce('initiatedBy.user.userPrincipalName', 'initiatedBy.app.displayName', "unknown")
| eval src_ip=coalesce('initiatedBy.user.ipAddress', "unknown")
| eval time_bucket=strftime(round(_time/600)*600, "%Y-%m-%dT%H:%M:%SZ")
| stats count as graph_enum_count, dc(operationName) as distinct_graph_ops, values(operationName) as graph_operations
by initiator, src_ip, time_bucket
| where graph_enum_count >= 8 OR distinct_graph_ops >= 5
| eval risk_score=case(distinct_graph_ops >= 8, "High", 1=1, "Medium")
| rename initiator as caller, src_ip as callerIpAddress
| eval operation_count=graph_enum_count, distinct_ops=distinct_graph_ops, distinct_resource_types=null(), distinct_subscriptions=null()
| eval enumeration_breadth=distinct_graph_ops . " Graph API operations"
| table time_bucket, caller, callerIpAddress, operation_count, distinct_ops, risk_score, enumeration_breadth, graph_operations
] Detects cloud service enumeration via Azure Activity Logs and Azure AD Audit Logs. The primary search identifies callers performing many List/Read/Get operations across multiple Azure resource types in 10-minute windows — the breadth of resource types is the key discriminator. An appended sub-search detects Microsoft Graph API enumeration of Entra ID service principals, applications, policies, and directory roles, which tools like AADInternals and ROADTools perform heavily. Both searches feed into a unified result set ranked by risk score.
Data Sources
Required Sourcetypes
False Positives & Tuning
- Terraform or Pulumi IaC pipelines using service principals to enumerate existing resources before applying changes
- Azure Security Center and CSPM tools that continuously scan resource configurations for compliance assessment
- Cloud inventory or asset management tools (ServiceNow CMDB sync, Flexera, CloudHealth) with broad read permissions
- Microsoft Entra ID Connect synchronization accounts that regularly read directory objects and group memberships
- Authorized penetration testing activities using cloud assessment frameworks with Azure read-only service principals
Other platforms for T1526
Testing Methodology
Validate this detection against 4 adversary techniques from Atomic Red Team. Each test below lists the behaviour to exercise and the telemetry you should expect to see. Executable commands and cleanup steps are available with Pro.
- Test 1Azure Resource Enumeration via Azure CLI
Expected signal: AzureActivity log entries for each az CLI command with OperationNameValue containing Microsoft.Compute/virtualMachines/read, Microsoft.Network/virtualNetworks/read, Microsoft.Storage/storageAccounts/read, Microsoft.KeyVault/vaults/read, Microsoft.Web/sites/read, Microsoft.ContainerService/managedClusters/read, Microsoft.Security/autoProvisioningSettings/read. Caller will be the authenticated user or service principal. CallerIpAddress will reflect the source machine's IP.
- Test 2Entra ID Enumeration via AADInternals PowerShell Module
Expected signal: AuditLogs entries with Category='Core Directory' for tenant and domain read operations. User-Agent field in AdditionalDetails will contain 'AADInternals'. SigninLogs will show authentication events for the token acquisition. MicrosoftGraphActivityLogs (if enabled) will show HTTP GET requests to /v1.0/organization, /v1.0/domains, /v1.0/servicePrincipals with User-Agent='AADInternals'.
- Test 3Microsoft Graph API Service Principal Enumeration via PowerShell
Expected signal: AuditLogs entries: OperationName='List servicePrincipals', 'List applications', 'List directoryRoles', 'Get organization', 'Get policy' with Category='Core Directory' and 'ApplicationManagement'. InitiatedBy will reflect the authenticated user. MicrosoftGraphActivityLogs will show GET requests to /v1.0/servicePrincipals, /v1.0/applications, /v1.0/directoryRoles, /v1.0/organization, /v1.0/policies/authorizationPolicy.
- Test 4AWS Cloud Service Discovery via Pacu Framework
Expected signal: AWS CloudTrail logs: DescribeTrails, ListDetectors, DescribeInstances, ListRoles, ListBuckets, ListFunctions, ListClusters, ListSecrets events with eventSource matching cloudtrail.amazonaws.com, guardduty.amazonaws.com, ec2.amazonaws.com, iam.amazonaws.com, s3.amazonaws.com, lambda.amazonaws.com, ecs.amazonaws.com, secretsmanager.amazonaws.com. userAgent will contain 'aws-cli'. sourceIPAddress will reflect the caller's IP.
References (12)
- https://attack.mitre.org/techniques/T1526/
- https://docs.microsoft.com/en-us/rest/api/resources/
- https://docs.microsoft.com/en-us/previous-versions/azure/ad/graph/howto/azure-ad-graph-api-operations-overview
- https://github.com/Azure/Stormspotter
- https://github.com/RhinoSecurityLabs/pacu
- https://o365blog.com/aadinternals/
- https://github.com/dirkjanm/ROADtools
- https://learn.microsoft.com/en-us/azure/azure-monitor/reference/tables/azureactivity
- https://learn.microsoft.com/en-us/azure/azure-monitor/reference/tables/auditlogs
- https://learn.microsoft.com/en-us/graph/microsoft-graph-activity-logs-overview
- https://www.microsoft.com/en-us/security/blog/2024/09/26/midnight-blizzard-conducts-large-scale-spear-phishing-campaign-using-rdp-files/
- https://github.com/redcanaryco/atomic-red-team/blob/master/atomics/T1526/T1526.md
Unlock Pro Content
Get the full detection package for T1526 including response playbook, investigation guide, and atomic red team tests.