Playbooks

T1525, T1526, T1078, T1530

Cloud Incident Response

How incident response differs in cloud environments — IAM pivoting, data exfiltration via cloud storage, log sources that replace on-prem artifacts, cloud-native detection queries, and the playbook adjustments analysts need.

View on Graph

How Cloud IR Differs from On-Prem

  • Cloud incident response operates under fundamentally different assumptions than traditional on-prem IR.
  • MITRE ATT&CK maps cloud reconnaissance to T1526 (Cloud Service Discovery) and T1525 (Implant Internal Image), since attackers who compromise the identity plane can also plant backdoored AMIs and container images for persistence.
  • Key differences: (1) No physical access — you cannot unplug a cable. Containment is API-driven (revoke IAM keys, modify security groups, apply SCPs). (2) Shared responsibility: the cloud provider secures the infrastructure; you secure your data, identities, and configurations. (3) Logs are API-driven — every action in the cloud generates an API event, which is both a blessing (complete audit trail) and a challenge (volume).

Cloud-Native Log Sources

AWS

Log SourceWhat It CapturesRetentionCritical Events
CloudTrailEvery API call in the accountConfigurable (default 90 days)ConsoleLogin, CreateAccessKey, AttachRolePolicy, PutBucketPolicy, ModifySnapshotAttribute, AuthorizeSecurityGroupIngress
VPC Flow LogsIP traffic metadata (src/dst IP, port, protocol, packets)ConfigurableAll traffic — baseline for anomaly detection
GuardDutyManaged threat detectionSame as alert retentionCredential compromise, EC2 malware, S3 exfiltration, crypto mining
S3 Access LogsObject-level access requestsConfigurableGetObject from unusual IPs, bulk ListBucket
CloudWatch LogsApplication and system logsConfigurableOS-level events, application errors

Azure

Log SourceWhat It CapturesCritical Events
Azure Activity LogControl plane operations (subscription-level)Create Role Assignment, Update Key Vault, Delete Diagnostic Setting
Azure AD Sign-in LogsUser authentication attemptsImpossible travel, anonymous IP, unfamiliar device, MFA denied
Azure AD Audit LogsDirectory configuration changesPrivileged role assignment, application registration, conditional policy changes
NSG Flow LogsNetwork traffic metadataTraffic to/from Azure resources

GCP

Log SourceWhat It CapturesCritical Events
Cloud Audit LogsAdmin activity, data access, system eventsSetIamPolicy, storage.objects.create, compute.instances.create
VPC Flow LogsNetwork traffic metadataAnomalous outbound connections

Detection Queries by Attack Scenario

Scenario 1: AWS IAM Privilege Escalation

Attackers who compromise an IAM user will attempt to escalate privileges by attaching policies, creating admin users, or modifying trust relationships.

SPL query — detect privilege escalation via IAM changes (run in Splunk):

index=cloudtrail eventSource="iam.amazonaws.com"
| search eventName IN ("AttachRolePolicy", "AttachUserPolicy", "PutUserPolicy", "CreatePolicy", "UpdateAssumeRolePolicy", "CreateUser", "CreateAccessKey")
| stats count, values(sourceIPAddress) as SourceIPs, values(userIdentity.arn) as UserARN by eventName, requestParameters.policyArn
| eval severity = if(eventName="AttachRolePolicy" OR eventName="PutUserPolicy", "HIGH — policy attachment", "MEDIUM — IAM configuration change")
| table _time, eventName, UserARN, SourceIPs, requestParameters.policyArn, severity

KQL query (Azure Sentinel) — detect Azure RBAC escalation (see the KQL guide):

AzureActivity
| where OperationName in ("Create Role Assignment", "Update Role Assignment", "Delete Role Assignment")
| where ActivityStatus == "Succeeded"
| extend Role = tostring(Properties.role)
| extend Principal = tostring(Properties.principalDisplayName)
| where Role contains "Owner" or Role contains "Contributor" or Role contains "Admin"
| project TimeGenerated, Caller, Principal, Role, OperationName

Scenario 2: Data Exfiltration via Cloud Storage

SPL query — detect large S3 object retrievals (compatible with Elastic Security EQL):

index=cloudtrail eventSource="s3.amazonaws.com"
| search eventName="GetObject"
| stats sum(eventParameters.responseElements.bytesTransferred) as totalBytes by sourceIPAddress, userIdentity.arn, requestParameters.bucketName
| where totalBytes > 50000000
| eval alert = "HIGH — user " . userIdentity.arn . " downloaded " . round(totalBytes/1048576, 2) . "MB from " . requestParameters.bucketName
| table _time, sourceIPAddress, userIdentity.arn, requestParameters.bucketName, totalBytes, alert

SPL query — detect public bucket exposure changes:

index=cloudtrail eventSource="s3.amazonaws.com"
| search eventName IN ("PutBucketAcl", "PutBucketPolicy")
| search requestParameters.AccessControlPolicy.AccessControlList.Grant.Grantee.URI="*acs.amazonaws.com/groups/global/AllUsers*" OR requestParameters.Policy="*Principal\":\"*\"*"
| eval alert = "CRITICAL — bucket made public by " . userIdentity.arn . " on " . requestParameters.bucketName
| table _time, userIdentity.arn, sourceIPAddress, requestParameters.bucketName, alert

Scenario 3: Cloud Credential Compromise

SPL query — detect console login from unusual location (impossible travel):

index=cloudtrail eventName="ConsoleLogin"
| search responseElements.ConsoleLogin="Success"
| iplocation sourceIPAddress
| eval login_hour = strftime(_time, "%H")
| stats count, values(sourceIPAddress) as IPs, values(userIdentity.arn) as Users by Country, City
| where Country!="US" AND Country!="" 
| eval alert = "HIGH — cloud console login from " . Country . " — possible credential compromise"
| table _time, Users, IPs, Country, City, alert

KQL query (Azure Sentinel) — detect Azure MFA push denial flood:

SigninLogs
| where ResultType == "500121"  // MFA denied
| summarize DenialCount = count() by UserPrincipalName, IPAddress, AppDisplayName, bin(TimeGenerated, 5m)
| where DenialCount > 10
| project TimeGenerated, UserPrincipalName, IPAddress, AppDisplayName, DenialCount
| sort by DenialCount desc

Scenario 4: Cloud Resource Hijacking (Crypto Mining)

SPL query — detect EC2 instance creation from unusual IAM roles:

index=cloudtrail eventSource="ec2.amazonaws.com"
| search eventName="RunInstances"
| stats count, values(requestParameters.instanceType) as InstanceTypes, values(sourceIPAddress) as SourceIPs by userIdentity.arn
| where count > 5
| eval alert = "HIGH — multiple instances launched by " . userIdentity.arn . " — possible resource hijacking"
| table _time, userIdentity.arn, count, InstanceTypes, alert

Containment in the Cloud — API-Driven Actions

AWS Containment Actions

ActionCommandUse Case
Revoke IAM credentialsaws iam update-access-key --access-key-id AKIA... --status InactiveCompromised user key
Detach IAM policyaws iam detach-user-policy --user-name jdoe --policy-arn arn:aws:iam::...Privilege escalation prevention
Deny all access via SCPCreate SCP with Deny * effect for the compromised account/OUWidespread compromise
Isolate EC2 instanceModify security group to deny all ingress/egressCompromised EC2
Disable access keyaws iam update-access-key --access-key-id AKIA... --status InactiveAPI key compromise

Azure Containment Actions

ActionCommandUse Case
Disable userDisable in Azure ADCompromised user account
Revoke sessionsRevoke-AzureADUserAllRefreshTokenActive session hijack
Detach roleRemove role assignmentPrivilege escalation
Block resourceCreate NSG deny ruleCompromised VM
Remove app consentRevoke OAuth grantOAuth application abuse

GCP Containment Actions

ActionCommandUse Case
Revoke IAMgcloud projects remove-iam-policy-bindingCompromised service account
Disable service accountgcloud iam service-accounts disableAPI key compromise
Remove from organizationMove project to separate folder with restrictive org policyWidespread compromise

Cloud IR Decision Tree

Cloud incident detected

    ├─ What type of cloud resource is compromised?
    │   ├─ IAM user/service account → Revoke credentials, check CloudTrail for API calls
    │   ├─ Compute (EC2/VM/Compute Engine) → Isolate, capture snapshot, check for persistence
    │   ├─ Storage (S3/Blob/GCS) → Lock down access, review access logs for data theft
    │   └─ Container/orchestration (EKS/AKS/GKE) → Capture pod logs, check RBAC configuration

    ├─ Is the management plane compromised?
    │   ├─ Yes → Assume all resources in the account are at risk. Apply organization-level SCPs.
    │   └─ No → Isolate the specific resource. Proceed with single-account investigation.

    ├─ What is the blast radius?
    │   ├─ Single resource → Targeted. Investigate access source. Rotate credentials.
    │   └─ Multiple resources across services → Automated (likely crypto mining or data exfiltration bot). Apply broad containment.

    └─ Post-incident: Review root cause
        ├─ Was it a leaked API key? → Rotate all keys. Enable key rotation policies.
        ├─ Was it a misconfigured bucket? → Apply organization-wide bucket policies. Enable S3 Block Public Access.
        ├─ Was it a compromised admin credential? → Review identity provider. Enable MFA for all users.
        └─ Was it an exploited CVE? → Patch, update, or replace affected service.

Sources