Identity is the new perimeter — and attackers know it. Unit 42's latest research, Unmasking Cloud Identities: From Behavioral Clustering to Automated Detection, tackles one of the hardest problems in cloud defense: how do you baseline what "normal" looks like for thousands of machine and human identities in a cloud environment, and how do you turn that baseline into something a SOC can actually operationalize?
Their answer is elegant in its practicality: use behavioral clustering to group cloud identities by what they actually do in audit logs (AWS CloudTrail, Azure Activity Logs, GCP Audit Logs), assign each identity a behavioral role, and then express deviations from those roles as standard SQL queries that run continuously. No exotic ML pipeline required in production — the clustering does the heavy lifting upfront, and the detection layer is plain SQL that any detection engineer can read, tune, and deploy.
For defenders, this matters because cloud identity abuse is the common denominator in nearly every major cloud breach we respond to — credential theft, token replay, privilege escalation via over-permissioned roles, and living-off-the-cloud techniques where attackers use legitimate API calls for malicious ends. Static allowlists and hand-written rules do not scale to thousands of service accounts. Behavioral baselining does. This post breaks down the technique and gives you deployable detection content for your SIEM today.
Technical Analysis
What the Research Proposes
The Unit 42 approach works in three stages:
-
Feature extraction from audit logs. Every cloud API call recorded in the audit trail (e.g., CloudTrail events like
iam:CreateAccessKey,sts:AssumeRole,ec2:DescribeInstances,s3:GetObject) becomes a behavioral signal. For each identity (IAM user, assumed role, service principal), you build a feature vector: which API actions are called, at what frequency, from which source IPs, against which resource types, at what times. -
Clustering into behavioral roles. Identities are clustered (e.g., with density-based or embedding-based clustering) so that identities with similar API-call profiles group together. A CI/CD deployer role, a read-only monitoring service account, and a human administrator land in distinct clusters. The practical output: each identity gets a behavioral role label and a known-good envelope of expected actions.
-
Continuous detection via SQL. Once roles are established, deviations become queryable: an identity calling an API action it has never used before, an identity behaving outside its cluster, or an identity suddenly resembling a different (more privileged) cluster. Because the detection layer is SQL, it ports directly to Athena, BigQuery, Snowflake, Sentinel, or any SIEM that ingests cloud audit logs.
Why This Matters From an Incident Response Chair
In our ransomware and BEC-adjacent cloud intrusions, the post-compromise pattern is remarkably consistent: the attacker lands with a stolen credential or token, then performs reconnaissance (Describe*, List*, Get* calls across services the identity has never touched), privilege escalation attempts (iam:AttachRolePolicy, iam:PassRole, lambda:CreateFunction with an existing role), persistence (iam:CreateAccessKey, iam:CreateLoginProfile, new federated identities), and data staging/exfiltration (s3:GetObject at anomalous volume, rds:CreateDBSnapshot, s3:PutBucketPolicy to public). None of these APIs are inherently malicious — which is exactly why signature-based detections fail and behavioral deviation detection succeeds.
Exploitation / Abuse Status
This is a defensive research item, not a vulnerability disclosure — there is no associated CVE. The techniques it counters (cloud credential abuse, identity misuse, anomalous API behavior) are observed in active intrusions across all three major clouds and map directly to MITRE ATT&CK Cloud Matrix tactics. The defensive lesson is current and actionable: if your cloud detection strategy is still a flat list of "alert on CreateAccessKey" rules, you are blind to everything an attacker does within an identity's nominal permissions.
Detection & Response
The detections below operationalize the behavioral-deviation concept in Sigma, Sentinel KQL, and Velociraptor VQL, tuned to fire on high-fidelity identity anomalies rather than ambient noise.
Sigma Rules
---
title: Cloud IAM Persistence via New Access Key Creation Outside Change Window
id: 3c7a2e91-4f58-4b1d-9a6c-8d2e5f7b0a31
status: experimental
description: Detects creation of new IAM access keys, a common persistence mechanism after cloud credential compromise. Correlate with the identity's behavioral baseline — first-time use of iam:CreateAccessKey by an identity is a strong deviation signal.
references:
- https://unit42.paloaltonetworks.com/behavioral-clustering-map-to-cloud-identities/
- https://attack.mitre.org/techniques/T1098/001/
author: Security Arsenal
date: 2026/04/06
tags:
- attack.persistence
- attack.t1098.001
logsource:
product: aws
service: cloudtrail
detection:
selection:
eventSource: 'iam.amazonaws.com'
eventName:
- 'CreateAccessKey'
- 'CreateLoginProfile'
- 'UpdateLoginProfile'
filter_console_login_user:
userIdentity.type: 'Root'
condition: selection and not filter_console_login_user
falsepositives:
- Legitimate onboarding of new IAM users by identity administrators
- Automated IAM provisioning pipelines (suppress known automation principals)
level: high
---
title: Cloud Reconnaissance Burst Across Multiple AWS Services
id: 9f1d4b62-7c3e-4a28-b5f1-2e6d8a0c4f97
status: experimental
description: Detects discovery-style API calls (Describe/List/Get) spanning services an identity does not normally touch. Attackers performing post-compromise recon fan out across EC2, S3, RDS, Lambda, and IAM in short windows — behavior that deviates sharply from clustered baselines.
references:
- https://unit42.paloaltonetworks.com/behavioral-clustering-map-to-cloud-identities/
- https://attack.mitre.org/techniques/T1580/
author: Security Arsenal
date: 2026/04/06
tags:
- attack.discovery
- attack.t1580
logsource:
product: aws
service: cloudtrail
detection:
selection:
eventName|startswith:
- 'Describe'
- 'List'
- 'Get'
filter_known_readers:
userIdentity.arn|contains:
- 'assumed-role/MonitoringRole'
- 'assumed-role/SecurityAuditRole'
condition: selection and not filter_known_readers
falsepositives:
- Inventory and CSPM tooling (exclude their role ARNs explicitly)
- Administrators during incident response or audits
level: medium
---
title: Cloud Privilege Escalation via IAM Policy or PassRole Abuse
id: 5b8e3c14-2a97-4d6f-8e3b-1c9a7d5e2f48
status: experimental
description: Detects API calls commonly used for privilege escalation in cloud environments — attaching privileged policies, passing roles to compute services, or creating roles with broad trust. First-time use of these actions by an identity is a critical behavioral deviation.
references:
- https://unit42.paloaltonetworks.com/behavioral-clustering-map-to-cloud-identities/
- https://attack.mitre.org/techniques/T1548/
author: Security Arsenal
date: 2026/04/06
tags:
- attack.privilege_escalation
- attack.t1548
logsource:
product: aws
service: cloudtrail
detection:
selection:
eventSource:
- 'iam.amazonaws.com'
eventName:
- 'AttachRolePolicy'
- 'AttachUserPolicy'
- 'PutRolePolicy'
- 'PutUserPolicy'
- 'PassRole'
- 'CreateRole'
- 'UpdateAssumeRolePolicy'
condition: selection
falsepositives:
- Terraform/CloudFormation deployments from known pipeline roles (baseline and suppress)
- IAM administration during sanctioned change windows
level: high
KQL (Microsoft Sentinel / Defender)
The following hunt assumes AWS CloudTrail is ingested into the AWSCloudTrail table (or Azure AD sign-in/audit equivalents). It operationalizes the clustering concept directly: it builds a 30-day behavioral baseline per identity, then flags identities whose today's API-action set contains actions never seen in the baseline — the SQL-style deviation detection from the Unit 42 model, expressed in KQL.
// Behavioral deviation hunt: identity using API actions never seen in its 30-day baseline
// Baseline window: days 30..2 | Detection window: last 48 hours
let baseline_start = ago(30d);
let baseline_end = ago(2d);
let detection_start = ago(48h);
let baseline =
AWSCloudTrail
| where TimeGenerated between (baseline_start .. baseline_end)
| summarize BaselineActions = make_set(EventName), BaselineSources = make_set(SourceIpAddress)
by Identity = tostring(UserIdentityArn);
AWSCloudTrail
| where TimeGenerated >= detection_start
| summarize NewActions = make_set(EventName), SourceIPs = make_set(SourceIpAddress),
CallCount = count(), FirstSeen = min(TimeGenerated), LastSeen = max(TimeGenerated)
by Identity = tostring(UserIdentityArn)
| join kind=inner baseline on Identity
| extend NovelActions = set_difference(NewActions, BaselineActions)
| extend NovelActionCount = array_length(NovelActions)
| where NovelActionCount >= 3
| extend SuspiciousNew = set_intersect(NovelActions,
dynamic(["CreateAccessKey","AttachRolePolicy","PutRolePolicy","PassRole",
"CreateRole","UpdateAssumeRolePolicy","CreateLoginProfile",
"PutBucketPolicy","CreateDBSnapshot","StopLogging","DeleteTrail"]))
| extend RiskScore = NovelActionCount + (array_length(SuspiciousNew) * 5)
| project Identity, NovelActionCount, SuspiciousNew, SourceIPs, CallCount,
FirstSeen, LastSeen, RiskScore
| order by RiskScore desc
A companion query for high-severity destructive/evasive actions regardless of baseline:
// Defense-evasion: CloudTrail tampering or GuardDuty disabling
AWSCloudTrail
| where TimeGenerated >= ago(24h)
| where EventName in ("StopLogging", "DeleteTrail", "PutEventSelectors",
"DeleteDetector", "DisableSecurityHub", "UpdateTrail")
| project TimeGenerated, UserIdentityArn, SourceIpAddress, EventName,
AwsRegion, UserAgent
| order by TimeGenerated desc
Velociraptor VQL
Cloud identity attacks frequently begin or end on endpoints: attackers harvest cloud credentials from ~/.aws/credentials, Azure CLI token caches, or browser session data. This Velociraptor artifact hunts for processes accessing cloud credential stores — a strong endpoint-side corroboration signal when a cloud identity anomaly fires.
-- Hunt: processes accessing cloud credential stores on endpoints
-- Corroborates cloud identity anomalies with endpoint-side credential access
LET cred_paths = {
SELECT FullPath FROM glob(globs=[
'C:/Users/*/.aws/credentials',
'C:/Users/*/.azure/accessTokens.json',
'C:/Users/*/.azure/msal_token_cache*',
'C:/Users/*/AppData/Local/Google/Chrome/User Data/Default/Network/Cookies'
])
};
SELECT Pid, Name, Exe, CommandLine, Username, CreateTime
FROM pslist()
WHERE CommandLine =~ '(?i)(\.aws.credentials|accessTokens\.json|msal_token_cache|gcloud.*credentials|aws sso|az login|sts assume-role)'
OR Name =~ '(?i)(aws|az|gcloud)\.(exe)?$'
Remediation / Verification Script
This Bash script builds a lightweight behavioral baseline and deviation report from CloudTrail events stored in S3 via Athena-style export, or directly against local JSON logs — a practical first step toward the continuous SQL detection model. It also audits for the highest-risk IAM conditions.
#!/usr/bin/env bash
# Cloud Identity Behavioral Baseline + High-Risk IAM Audit
# Usage: ./cloud_identity_audit.sh /path/to/cloudtrail/json/logs
set -euo pipefail
LOG_DIR="${1:-/var/log/cloudtrail}"
OUT="identity_audit_$(date +%Y%m%d_%H%M%S)"
mkdir -p "$OUT"
echo "[+] Building per-identity API action baseline from $LOG_DIR"
# Extract identity -> action pairs; requires jq
cat "$LOG_DIR"/*.json 2>/dev/null | \
jq -r '.Records[]? // . | "\(.userIdentity.arn // "unknown")\t\(.eventName // "unknown")"' | \
sort -u > "$OUT/identity_action_pairs.tsv"
awk -F'\t' '{actions[$1] = actions[$1] "," $2; count[$1]++}
END {for (id in actions) printf "%s\t%d unique actions\n", id, count[id]}' \
"$OUT/identity_action_pairs.tsv" | sort -k2 -nr > "$OUT/identity_baseline_summary.tsv"
echo "[+] Flagging high-risk API actions (persistence / priv-esc / evasion)"
grep -Ei 'CreateAccessKey|CreateLoginProfile|AttachRolePolicy|PutRolePolicy|PassRole|UpdateAssumeRolePolicy|StopLogging|DeleteTrail|PutBucketPolicy' \
"$OUT/identity_action_pairs.tsv" > "$OUT/high_risk_events.tsv" || true
echo "[+] Auditing IAM for users with unused-but-active access keys (90d+)"
if command -v aws >/dev/null 2>&1; then
aws iam generate-credential-report >/dev/null 2>&1 || true
sleep 5
aws iam get-credential-report --query 'Content' --output text | \
base64 -d | awk -F',' 'NR>1 && $9=="true" && $11!="N/A" {
split($11,d,"T"); cmd="date -d "d[1]" +%s 2>/dev/null || date -j -f %Y-%m-%d "d[1]" +%s;
cmd | getline ts; close(cmd);
if ((systime()-ts)/86400 > 90) print $1" - key1 unused >90 days (last: "$11")"
}' > "$OUT/stale_access_keys.txt" || echo " (credential report requires iam:GenerateCredentialReport permission)"
fi
echo ""
echo "===== RESULTS ====="
echo "Identities profiled: $(wc -l < "$OUT/identity_baseline_summary.tsv")"
echo "High-risk events: $(wc -l < "$OUT/high_risk_events.tsv")"
echo "Output directory: $OUT/"
echo ""
echo "[NEXT STEPS]"
echo " 1. Review high_risk_events.tsv — every persistence/priv-esc action needs a ticket or a suppression reason."
echo " 2. Feed identity_action_pairs.tsv into your SIEM as a lookup table for deviation detection."
echo " 3. Schedule this script weekly; diff consecutive runs to catch role drift (new actions per identity)."
Remediation
Beyond detection, harden the identity layer so deviations become rare and obvious:
- Eliminate long-lived credentials. Migrate human users to IAM Identity Center / federated SSO with short-lived session tokens. For workloads, prefer instance profiles, IRSA (EKS), or managed identities over static access keys. Every
CreateAccessKeyevent should then be anomalous by default. - Enforce least privilege with Access Analyzer. Run AWS IAM Access Analyzer (or Azure Access Reviews / GCP Policy Analyzer) continuously. Unused-permission findings feed directly into tightening the behavioral envelope per identity — the same envelope your clustering model uses.
- Baseline then alert on deviation, not action. Implement the Unit 42 pattern in your stack: export audit logs to a queryable store (Athena, BigQuery, Sentinel), build per-identity action baselines over 30 days, and alert when an identity uses actions outside its historical set. Start with the high-risk action list in the script above as priority deviation signals.
- Protect the audit plane itself. Alert on
StopLogging,DeleteTrail,PutEventSelectors, and GuardDuty/Security Hub tampering immediately. An attacker who blinds your audit logs defeats behavioral detection entirely. Enable organization-level CloudTrail trails with S3 object lock / log file validation. - Correlate cloud and endpoint. As the VQL hunt shows, cloud identity compromise usually touches an endpoint (stolen
~/.aws/credentials, token cache theft). Join cloud anomalies with EDR telemetry on credential-store access for high-confidence incidents. - Rehearse the IR playbook. For any confirmed identity deviation: revoke sessions/keys immediately (
aws iam update-access-key --status Inactive, revoke refresh tokens), rotate affected credentials, diff the identity's activity window against its baseline for blast-radius scoping, and check for persistence artifacts created during the window.
Related Resources
Security Arsenal Managed SOC Services AlertMonitor Platform Book a SOC Assessment soc-mdr Intel Hub
Is your security operations ready?
Get a free SOC assessment or see how AlertMonitor cuts through alert noise with automated triage.