Discovery
T1580 — Cloud Infrastructure Discovery
An adversary may attempt to discover infrastructure and resources that are available within an infrastructure-as-a-service (IaaS) environment. This includes compute service resources such as instances, virtual machines, and snapshots as well as resources of other services including the storage and database services. Cloud providers offer methods such as APIs and commands issued through CLIs to serve information about infrastructure...
Investigate Cloud Infrastructure Discovery activity in the context of Discovery: confirm scope, affected host/identity, and whether it matches expected administrative behaviour before deciding this is benign.
Platforms
IaaS
Priority / status
medium / complete
Evidence to collect
- Host or resource affected
- Account or identity involved
- Timestamp of the activity
- Related process, file, or network artifact
- Any preceding or follow-on alerts
D3-NTA · detect
Network Traffic Analysis
Monitor for Network Traffic Analysis indicators relevant to this technique.
Tooling: Sentinel, Defender for Endpoint
| ATT&CK Technique | D3FEND Technique | Practical SOC Action | Tooling |
|---|---|---|---|
| T1580 Cloud Infrastructure Discovery | Network Traffic Analysis | Monitor for Network Traffic Analysis indicators relevant to this technique. | Sentinel, Defender for Endpoint |
T1580 Cloud Infrastructure Discovery → D3FEND → SOC action
Investigation steps — Microsoft
- Review Defender for Endpoint / Defender XDR alerts and timeline for the affected host or identity.
- Check Sentinel analytics rules and incidents correlated with this technique.
- Review Entra ID sign-in and audit logs if the technique involves an identity or cloud resource.
Investigation steps — generic
- Confirm whether the observed cloud infrastructure discovery activity matches expected administrative or application behaviour.
- Identify the host, account, or resource where the activity occurred and its business criticality.
- Check for related alerts before and after this activity to reconstruct the broader intrusion timeline.
- Real detection reference: "Cloud Resource and Tenant Enumeration" -- Flags bulk enumeration of Azure resources or Entra ID directory objects by a single caller, consistent with post-compromise cloud environment mapping (Azure CLI/PowerShell, Stormspotter, ROADtools, AzureHound).
Response actions
| Action | Risk | Automation safe | Approval required |
|---|---|---|---|
| Identify the tool making the requests (Azure CLI, SDK, custo | Low | No | Yes |
| Revoke the credentials used if compromise confirmed | Medium | No | Yes |
| Enable Azure Defender for Key Vault and Storage | Low | No | Yes |
KQL
GEN-DI-004 — Cloud Resource and Tenant Enumeration
AzureActivity
| where TimeGenerated >= ago(1h)
| where OperationNameValue has_any ("list", "List", "get", "Get", "read", "Read")
| where ResourceProviderValue has_any (
"Microsoft.KeyVault", "Microsoft.Storage", "Microsoft.Compute",
"Microsoft.Sql", "Microsoft.Authorization", "Microsoft.Network"
)
| summarize
StartTime = min(TimeGenerated),
EndTime = max(TimeGenerated),
ReadCount = count(),
ResourceTypes = dcount(ResourceProviderValue),
Operations = make_set(OperationNameValue, 10)
by Caller, CallerIpAddress, SubscriptionId
| where ReadCount > 50 and ResourceTypes > 3
| extend timestamp = StartTime, AccountCustomEntity = Caller, IPCustomEntity = CallerIpAddress
| order by ReadCount desc 72891de4-da70-44e4-9984-35fcea98d000 — Privileged Machines Exposed to the Internet
Authomize_v2_CL
| where ingestion_time() >= ago(30m)
| extend EventID = id_s, Policy = policy_name_s, Severity = severity_s,Description = description_s,Recommendation = recommendation_s,URL = url_s,Tactics = tactics_s
| where Policy has "Privileged Machines Exposed to the Internet"
| project EventID, Policy, Severity, Description, Recommendation, URL, Category, Tactics 421b38ec-4295-4aed-8299-c92e268ad663 — API - Kiterunner detection
let discoveryRecords = FortyTwoCrunchAPIProtection
| where TimeGenerated >= ago(5m)
| project-away NonBlockingMode, SourcePort, DestinationPort, Query, ApiId, RequestHeader, ResponseHeader, Errors, EventType, Uuid
| where Status == 404 and ErrorMessage startswith "path not defined in OAS";
let discoveryCnt = (toscalar(discoveryRecords | count));
let recCount = iff((discoveryCnt > 500), 1, 0);
discoveryRecords | top recCount by Timestamp desc Escalation criteria
- Cloud Infrastructure Discovery activity observed on a privileged account or critical system.
- Activity follows or precedes other suspicious behaviour in the same investigation.
- Automated triage cannot confidently rule out malicious intent.
False positive considerations
- Legitimate administrative or maintenance activity matching this pattern.
- Approved security testing or red team exercise.
- Known benign software producing similar telemetry.
# T1580 - Cloud Infrastructure Discovery
## SOC Recommendation
Investigate Cloud Infrastructure Discovery activity in the context of Discovery: confirm scope, affected host/identity, and whether it matches expected administrative behaviour before deciding this is benign.
## D3FEND Mappings
| D3FEND Technique | Relationship | Practical SOC Action |
|---|---|---|
| Network Traffic Analysis | Detect | Monitor for Network Traffic Analysis indicators relevant to this technique. |
## Investigation Steps
1. Review Defender for Endpoint / Defender XDR alerts and timeline for the affected host or identity.
2. Check Sentinel analytics rules and incidents correlated with this technique.
3. Review Entra ID sign-in and audit logs if the technique involves an identity or cloud resource.
## Evidence to Collect
- Host or resource affected
- Account or identity involved
- Timestamp of the activity
- Related process, file, or network artifact
- Any preceding or follow-on alerts
## Response Actions
| Action | Risk | Automation Safe | Approval Required |
|---|---|---|---|
| Identify the tool making the requests (Azure CLI, SDK, custo | Low | No | Yes |
| Revoke the credentials used if compromise confirmed | Medium | No | Yes |
| Enable Azure Defender for Key Vault and Storage | Low | No | Yes |
## KQL
```kql
AzureActivity
| where TimeGenerated >= ago(1h)
| where OperationNameValue has_any ("list", "List", "get", "Get", "read", "Read")
| where ResourceProviderValue has_any (
"Microsoft.KeyVault", "Microsoft.Storage", "Microsoft.Compute",
"Microsoft.Sql", "Microsoft.Authorization", "Microsoft.Network"
)
| summarize
StartTime = min(TimeGenerated),
EndTime = max(TimeGenerated),
ReadCount = count(),
ResourceTypes = dcount(ResourceProviderValue),
Operations = make_set(OperationNameValue, 10)
by Caller, CallerIpAddress, SubscriptionId
| where ReadCount > 50 and ResourceTypes > 3
| extend timestamp = StartTime, AccountCustomEntity = Caller, IPCustomEntity = CallerIpAddress
| order by ReadCount desc
```
```kql
Authomize_v2_CL
| where ingestion_time() >= ago(30m)
| extend EventID = id_s, Policy = policy_name_s, Severity = severity_s,Description = description_s,Recommendation = recommendation_s,URL = url_s,Tactics = tactics_s
| where Policy has "Privileged Machines Exposed to the Internet"
| project EventID, Policy, Severity, Description, Recommendation, URL, Category, Tactics
```
```kql
let discoveryRecords = FortyTwoCrunchAPIProtection
| where TimeGenerated >= ago(5m)
| project-away NonBlockingMode, SourcePort, DestinationPort, Query, ApiId, RequestHeader, ResponseHeader, Errors, EventType, Uuid
| where Status == 404 and ErrorMessage startswith "path not defined in OAS";
let discoveryCnt = (toscalar(discoveryRecords | count));
let recCount = iff((discoveryCnt > 500), 1, 0);
discoveryRecords | top recCount by Timestamp desc
```
## Escalation Criteria
- Cloud Infrastructure Discovery activity observed on a privileged account or critical system.
- Activity follows or precedes other suspicious behaviour in the same investigation.
- Automated triage cannot confidently rule out malicious intent.
## False Positive Considerations
- Legitimate administrative or maintenance activity matching this pattern.
- Approved security testing or red team exercise.
- Known benign software producing similar telemetry.
Generated by SOC Response Atlas by Basyrix.
Want to push this directly to Confluence? Upgrade to Basyrix Pro.
- /api/techniques/T1580.json
- /api/recommendations/T1580.json
- /api/d3fend/T1580.json
- /api/mappings/T1580.json
- /api/confluence/T1580.md
Example curl:
curl https://atlas.basyrix.com/api/recommendations/T1580.json Response:
{
"technique_id": "T1580",
"name": "Cloud Infrastructure Discovery",
"priority": "medium",
"status": "complete",
"version": "0.1.0",
"last_reviewed": "2026-07-23",
"generated_by": "SOC Response Atlas by Basyrix",
"tactics": [
"Discovery"
],
"platforms": [
"IaaS"
],
"summary": "An adversary may attempt to discover infrastructure and resources that are available within an infrastructure-as-a-service (IaaS) environment. This includes compute service resources such as instances, virtual machines, and snapshots as well as resources of other services including the storage and database services. Cloud providers offer methods such as APIs and commands issued through CLIs to serve information about infrastructure...",
"soc_recommendation": "Investigate Cloud Infrastructure Discovery activity in the context of Discovery: confirm scope, affected host/identity, and whether it matches expected administrative behaviour before deciding this is benign.",
"d3fend_mappings": [
{
"id": "D3-NTA",
"name": "Network Traffic Analysis",
"relationship": "detect",
"practical_action": "Monitor for Network Traffic Analysis indicators relevant to this technique.",
"tooling": [
"Sentinel",
"Defender for Endpoint"
]
}
],
"investigation_steps": {
"microsoft": [
"Review Defender for Endpoint / Defender XDR alerts and timeline for the affected host or identity.",
"Check Sentinel analytics rules and incidents correlated with this technique.",
"Review Entra ID sign-in and audit logs if the technique involves an identity or cloud resource."
],
"generic": [
"Confirm whether the observed cloud infrastructure discovery activity matches expected administrative or application behaviour.",
"Identify the host, account, or resource where the activity occurred and its business criticality.",
"Check for related alerts before and after this activity to reconstruct the broader intrusion timeline.",
"Real detection reference: \"Cloud Resource and Tenant Enumeration\" -- Flags bulk enumeration of Azure resources or Entra ID directory objects by a single caller, consistent with post-compromise cloud environment mapping (Azure CLI/PowerShell, Stormspotter, ROADtools, AzureHound)."
]
},
"evidence_to_collect": [
"Host or resource affected",
"Account or identity involved",
"Timestamp of the activity",
"Related process, file, or network artifact",
"Any preceding or follow-on alerts"
],
"response_actions": [
{
"name": "Identify the tool making the requests (Azure CLI, SDK, custo",
"category": "Response",
"risk": "Low",
"automation_safe": false,
"approval_required": true,
"tool": "See investigation guide",
"notes": "Identify the tool making the requests (Azure CLI, SDK, custom script)"
},
{
"name": "Revoke the credentials used if compromise confirmed",
"category": "Response",
"risk": "Medium",
"automation_safe": false,
"approval_required": true,
"tool": "See investigation guide"
},
{
"name": "Enable Azure Defender for Key Vault and Storage",
"category": "Response",
"risk": "Low",
"automation_safe": false,
"approval_required": true,
"tool": "See investigation guide"
}
],
"queries": {
"kql": [
{
"name": "GEN-DI-004 — Cloud Resource and Tenant Enumeration",
"description": "Flags bulk enumeration of Azure resources or Entra ID directory objects by a single caller, consistent with post-compromise cloud environment mapping (Azure CLI/PowerShell, Stormspotter, ROADtools, AzureHound). (Source: Bell Integration baseline detection library.)",
"query": "AzureActivity\n| where TimeGenerated >= ago(1h)\n| where OperationNameValue has_any (\"list\", \"List\", \"get\", \"Get\", \"read\", \"Read\")\n| where ResourceProviderValue has_any (\n \"Microsoft.KeyVault\", \"Microsoft.Storage\", \"Microsoft.Compute\",\n \"Microsoft.Sql\", \"Microsoft.Authorization\", \"Microsoft.Network\"\n)\n| summarize\n StartTime = min(TimeGenerated),\n EndTime = max(TimeGenerated),\n ReadCount = count(),\n ResourceTypes = dcount(ResourceProviderValue),\n Operations = make_set(OperationNameValue, 10)\n by Caller, CallerIpAddress, SubscriptionId\n| where ReadCount > 50 and ResourceTypes > 3\n| extend timestamp = StartTime, AccountCustomEntity = Caller, IPCustomEntity = CallerIpAddress\n| order by ReadCount desc"
},
{
"name": "72891de4-da70-44e4-9984-35fcea98d000 — Privileged Machines Exposed to the Internet",
"description": "These are AWS Ec2 machines that are exposed to the internet. You can further filter by tags so that you can, for example, find exposed machines that are also \"privileged\". (Source: Microsoft's official Azure-Sentinel Detections (MIT licensed).)",
"query": "Authomize_v2_CL\n| where ingestion_time() >= ago(30m)\n| extend EventID = id_s, Policy = policy_name_s, Severity = severity_s,Description = description_s,Recommendation = recommendation_s,URL = url_s,Tactics = tactics_s\n| where Policy has \"Privileged Machines Exposed to the Internet\"\n| project EventID, Policy, Severity, Description, Recommendation, URL, Category, Tactics"
},
{
"name": "421b38ec-4295-4aed-8299-c92e268ad663 — API - Kiterunner detection",
"description": "42Crunch API protection against Kiterunner enumeration' (Source: Microsoft's official Azure-Sentinel Detections (MIT licensed).)",
"query": "let discoveryRecords = FortyTwoCrunchAPIProtection\n| where TimeGenerated >= ago(5m) \n| project-away NonBlockingMode, SourcePort, DestinationPort, Query, ApiId, RequestHeader, ResponseHeader, Errors, EventType, Uuid \n| where Status == 404 and ErrorMessage startswith \"path not defined in OAS\";\nlet discoveryCnt = (toscalar(discoveryRecords | count));\nlet recCount = iff((discoveryCnt > 500), 1, 0);\ndiscoveryRecords | top recCount by Timestamp desc"
}
],
"spl": [],
"esql": [
{
"name": "74f45152-9aee-11ef-b0a5-f661ea17fbcd — AWS Discovery API Calls via CLI from a Single Resource",
"description": "(ESQL) Detects when a single AWS resource is running multiple read-only, discovery API calls in a 10-second window. This behavior could indicate an actor attempting to discover the AWS infrastructure using compromised credentials or a compromised instance... (Source: Elastic's official detection-rules repository (Elastic License v2).)",
"query": "from logs-aws.cloudtrail-* metadata _id, _version, _index\n// create time window buckets of 10 seconds\n| eval Esql.time_window_date_trunc = date_trunc(10 seconds, @timestamp)\n\n| where\n data_stream.dataset == \"aws.cloudtrail\"\n \n // exclude service account and console behavior\n and source.ip IS NOT NULL\n and aws.cloudtrail.session_credential_from_console IS NULL\n and event.provider in (\n \"iam.amazonaws.com\",\n \"ec2.amazonaws.com\",\n \"s3.amazonaws.com\",\n \"rds.amazonaws.com\",\n \"lambda.amazonaws.com\",\n \"dynamodb.amazonaws.com\",\n \"kms.amazonaws.com\",\n \"cloudfront.amazonaws.com\",\n \"elasticloadbalancing.amazonaws.com\", \n \"cloudtrail.amazonaws.com\",\n \"sts.amazonaws.com\",\n \"ses.amazonaws.com\",\n \"organizations.amazonaws.com\"\n )\n // ignore AWS service actions\n and aws.cloudtrail.user_identity.type != \"AWSService\"\n // filter for aws-cli specifically\n and user_agent.name == \"aws-cli\"\n // exclude DescribeCapacityReservations events related to AWS Config\n and event.action != \"DescribeCapacityReservations\"\n and user.name != \"AWSServiceRoleForConfig\"\n\n// filter for Describe, Get, List, and Generate API calls\n| where true in (\n starts_with(event.action, \"Describe\"),\n starts_with(event.action, \"Get\"),\n starts_with(event.action, \"List\"),\n starts_with(event.action, \"Generate\")\n)\n\n// keep relevant fields (preserving ECS fields and computed time window)\n| keep \n @timestamp, \n Esql.time_window_date_trunc, \n event.action, \n aws.cloudtrail.user_identity.arn, \n aws.cloudtrail.user_identity.type, \n aws.cloudtrail.user_identity.access_key_id, \n source.ip, \n cloud.account.id, \n event.provider, \n user_agent.name, \n source.as.organization.name, \n cloud.region,\n data_stream.namespace\n\n// count the number of unique API calls per time window and actor\n| stats\n Esql.event_action_count_distinct = count_distinct(event.action),\n Esql.event_action_values = VALUES(event.action),\n Esql.event_timestamp_values = VALUES(@timestamp),\n Esql.aws_cloudtrail_user_identity_type_values = VALUES(aws.cloudtrail.user_identity.type),\n Esql.aws_cloudtrail_user_identity_access_key_id_values = VALUES(aws.cloudtrail.user_identity.access_key_id),\n Esql.source_ip_values = VALUES(source.ip),\n Esql.cloud_account_id_values = VALUES(cloud.account.id),\n Esql.event_provider_values = VALUES(event.provider),\n Esql.user_agent_name_values = VALUES(user_agent.name),\n Esql.source_as_organization_name_values = VALUES(source.as.organization.name),\n Esql.cloud_region_values = VALUES(cloud.region),\n Esql.data_stream_namespace_values = VALUES(data_stream.namespace)\n by Esql.time_window_date_trunc, aws.cloudtrail.user_identity.arn\n\n// filter for more than 5 unique API calls per 10s window\n| where Esql.event_action_count_distinct > 5\n\n| keep\n aws.cloudtrail.user_identity.arn,\n Esql.time_window_date_trunc,\n Esql.event_action_count_distinct,\n Esql.event_action_values,\n Esql.event_timestamp_values,\n Esql.aws_cloudtrail_user_identity_type_values,\n Esql.aws_cloudtrail_user_identity_access_key_id_values,\n Esql.source_ip_values,\n Esql.cloud_account_id_values,\n Esql.event_provider_values,\n Esql.user_agent_name_values,\n Esql.source_as_organization_name_values,\n Esql.cloud_region_values,\n Esql.data_stream_namespace_values"
},
{
"name": "a7577205-88a1-4a08-85d4-7b72a9a2e969 — AWS S3 Rapid Bucket Posture API Calls from a Single Principal",
"description": "(ESQL) Identifies when the same AWS principal, from the same source IP, successfully invokes read-only S3 control-plane APIs that reveal bucket posture across many buckets in a short period. This pattern can indicate automated reconnaissance or security scanning, similar to CSPM tools and post-compromise enumeration... (Source: Elastic's official detection-rules repository (Elastic License v2).)",
"query": "from logs-aws.cloudtrail-* metadata _id, _version, _index\n| eval Esql.time_window_date_trunc = date_trunc(10 seconds, @timestamp)\n\n| where\n data_stream.dataset == \"aws.cloudtrail\"\n and event.provider == \"s3.amazonaws.com\"\n and event.outcome == \"success\"\n and event.action in (\n \"GetBucketAcl\",\n \"GetBucketPublicAccessBlock\",\n \"GetBucketPolicy\",\n \"GetBucketPolicyStatus\",\n \"GetBucketVersioning\"\n )\n and aws.cloudtrail.user_identity.type != \"AWSService\"\n and source.ip IS NOT NULL\n and aws.cloudtrail.resources.arn IS NOT NULL\n and aws.cloudtrail.user_identity.arn IS NOT NULL\n and aws.cloudtrail.session_credential_from_console IS NULL\n\n| keep\n @timestamp,\n Esql.time_window_date_trunc,\n event.action,\n aws.cloudtrail.user_identity.arn,\n aws.cloudtrail.user_identity.type,\n aws.cloudtrail.user_identity.access_key_id,\n source.ip,\n aws.cloudtrail.resources.arn,\n cloud.account.id,\n cloud.region,\n user_agent.original,\n source.as.organization.name,\n data_stream.namespace\n\n| stats\n Esql.aws_cloudtrail_resources_arn_count_distinct = count_distinct(aws.cloudtrail.resources.arn),\n Esql.aws_cloudtrail_resources_arn_values = VALUES(aws.cloudtrail.resources.arn),\n Esql.event_action_values = VALUES(event.action),\n Esql.timestamp_values = VALUES(@timestamp),\n Esql.aws_cloudtrail_user_identity_type_values = VALUES(aws.cloudtrail.user_identity.type),\n Esql.aws_cloudtrail_user_identity_access_key_id_values = VALUES(aws.cloudtrail.user_identity.access_key_id),\n Esql.cloud_account_id_values = VALUES(cloud.account.id),\n Esql.cloud_region_values = VALUES(cloud.region),\n Esql.user_agent_original_values = VALUES(user_agent.original),\n Esql.source_as_organization_name_values = VALUES(source.as.organization.name),\n Esql.data_stream_namespace_values = VALUES(data_stream.namespace)\n by Esql.time_window_date_trunc, aws.cloudtrail.user_identity.arn, source.ip\n\n| where Esql.aws_cloudtrail_resources_arn_count_distinct > 15\n\n| keep\n aws.cloudtrail.user_identity.arn,\n source.ip,\n Esql.time_window_date_trunc,\n Esql.aws_cloudtrail_resources_arn_count_distinct,\n Esql.aws_cloudtrail_resources_arn_values,\n Esql.event_action_values,\n Esql.timestamp_values,\n Esql.aws_cloudtrail_user_identity_type_values,\n Esql.aws_cloudtrail_user_identity_access_key_id_values,\n Esql.cloud_account_id_values,\n Esql.cloud_region_values,\n Esql.user_agent_original_values,\n Esql.source_as_organization_name_values,\n Esql.data_stream_namespace_values"
}
]
},
"automation": {
"safe": [
"Add recommendation as Sentinel incident comment.",
"Run enrichment queries.",
"Create ServiceNow SecOps task."
],
"approval_required": [
"Contain or disable the affected host/account.",
"Any change to production configuration."
]
},
"escalation_criteria": [
"Cloud Infrastructure Discovery activity observed on a privileged account or critical system.",
"Activity follows or precedes other suspicious behaviour in the same investigation.",
"Automated triage cannot confidently rule out malicious intent."
],
"false_positive_considerations": [
"Legitimate administrative or maintenance activity matching this pattern.",
"Approved security testing or red team exercise.",
"Known benign software producing similar telemetry."
],
"confluence": {
"title": "T1580 - Cloud Infrastructure Discovery Response Guidance",
"labels": [
"mitre",
"attack",
"d3fend",
"secops",
"basyrix"
],
"sections": [
"summary",
"d3fend_mappings",
"investigation_steps",
"response_actions",
"queries",
"automation",
"escalation_criteria",
"false_positive_considerations"
]
}
}