Tabbed sections cover AWS, Azure, and GCP — switch tabs per provider. Detection queries use SPL (Splunk) and KQL (Sentinel). All IPs are RFC 5737/1918. All org names are synthetic.
Privilege Escalation — IAM Policy Attach Sequence¶
index=cloudtrail (eventName=CreatePolicy OR eventName=AttachUserPolicy
OR eventName=AttachRolePolicy OR eventName=PutUserPolicy)
| eval actor=mvindex(split('userIdentity.arn',"/"),1)
| stats earliest(_time) as first latest(_time) as last
values(eventName) as actions dc(eventName) as action_count
by actor, sourceIPAddress
| where action_count >= 2 AND match(actions,"CreatePolicy")
AND match(actions,"Attach")
| eval window_min=round((last-first)/60,1)
| where window_min <= 10
// --- Unauthorized API calls ---
index=cloudtrail errorCode IN ("AccessDenied","UnauthorizedAccess")
| stats count as denied dc(eventName) as unique_apis
values(eventName) as apis by userIdentity.arn, sourceIPAddress
| where denied > 10
// --- Security group opened to 0.0.0.0/0 ---
index=cloudtrail eventName IN ("AuthorizeSecurityGroupIngress",
"AuthorizeSecurityGroupEgress")
| eval rule='requestParameters.ipPermissions.items{}.ipRanges.items{}.cidrIp'
| where match(rule,"0\\.0\\.0\\.0/0") OR match(rule,"::/0")
| table _time, userIdentity.arn, eventName, requestParameters.groupId
// Unauthorized API callsAWSCloudTrail|whereErrorCodein("AccessDenied","UnauthorizedAccess")|summarizeDenied=count(),APIs=make_set(EventName,20)byUserIdentityArn,SourceIpAddress|whereDenied>10// Security group opened to the internetAWSCloudTrail|whereEventNamein("AuthorizeSecurityGroupIngress","AuthorizeSecurityGroupEgress")|whereRequestParametershas"0.0.0.0/0"orRequestParametershas"::/0"|projectTimeGenerated,UserIdentityArn,EventName,RequestParameters
// Privileged role assignmentsAuditLogs|whereOperationNamehas"Add member to role"|extendTarget=tostring(TargetResources[0].userPrincipalName)|extendRole=tostring(parse_json(tostring(TargetResources[0].modifiedProperties))[1].newValue)|whereRolehas_any("Global Administrator","Privileged Role Administrator","Security Administrator","User Access Administrator")|extendActor=tostring(InitiatedBy.user.userPrincipalName)|projectTimeGenerated,Actor,Target,Role// Anomalous mass resource deletionAzureActivity|whereOperationNameValuehas"DELETE"andActivityStatusValue=="Success"|summarizeDeletes=count(),Resources=make_set(Resource,25)byCaller,CallerIpAddress,bin(TimeGenerated,1h)|whereDeletes>5
Regardless of IaaS/PaaS/SaaS, the customer is always responsible for: data classification, user access management, regulatory compliance, and business continuity planning.
Launching instance in unused region (cryptomining)
RunInstances in atypical region
T1562.008
Disable Cloud Logs
Defense Evasion
Stopping CloudTrail or deleting log sinks
StopLogging, DeleteTrail
T1530
Data from Cloud Storage
Collection
Downloading sensitive S3/Blob/GCS data
High-volume GetObject, unusual principal
T1537
Transfer to Cloud Account
Exfiltration
Copying bucket to attacker-controlled account
Cross-account CopyObject
T1496
Resource Hijacking
Impact
Cryptomining on compromised compute
Unusual instance types, high CPU spike
T1580
Cloud Infrastructure Discovery
Discovery
Enumerating resources after initial access
Spike in Describe* / List* API calls
T1525
Implant Internal Image
Persistence
Backdooring AMI/VM image in auto-scaling
Image creation by unusual principal
T1610
Deploy Container
Execution
Deploying malicious container in EKS/AKS/GKE
Unexpected image, public registry pull
Cloud ATT&CK Matrix
MITRE maintains a dedicated Cloud Matrix covering IaaS, SaaS, and identity provider techniques. Map detection rules to these IDs for coverage tracking.
# List IAM users with console access but no MFAawsiamgenerate-credential-report&&sleep5awsiamget-credential-report--query'Content'--outputtext|\base64-d|awk-F',''$4=="true" && $8=="false" {print $1}'# Check CloudTrail status across all regionsforregionin$(awsec2describe-regions--query'Regions[].RegionName'\--outputtext);doawscloudtraildescribe-trails--region"$region"\--query'trailList[].{Name:Name,Multi:IsMultiRegionTrail}'done# Revoke all sessions for IAM user (emergency)awsiamput-user-policy--user-namecompromised-user\--policy-nameDenyAll--policy-document\'{"Version":"2012-10-17","Statement":[{"Effect":"Deny","Action":"*","Resource":"*"}]}'
# Storage accounts with public blob accessazstorageaccountlist--query\"[?allowBlobPublicAccess==true].{Name:name,RG:resourceGroup}"-otable
# Defender for Cloud secure scoreazsecuritysecure-scoreslist--query\"[].{Name:displayName,Score:currentScore,Max:maxScore}"-otable
# Revoke user sessions (emergency)azadusershow--idcompromised@acme-corp.example.com--queryid-otsv|\xargs-I{}azrest--methodPOST\--url"https://graph.microsoft.com/v1.0/users/{}/revokeSignInSessions"
# List public GCS bucketsforbucketin$(gsutills);dogsutiliamget"$bucket"2>/dev/null|\grep-q"allUsers\|allAuthenticatedUsers"&&echo"PUBLIC: $bucket"done# Firewall rules allowing 0.0.0.0/0gcloudcomputefirewall-ruleslist\--filter="sourceRanges=('0.0.0.0/0') AND direction=INGRESS"\--format='table(name,network,allowed,sourceRanges)'# Disable compromised service account (emergency)gcloudiamservice-accountsdisable\compromised-sa@acme-secops-prod.iam.gserviceaccount.com