An attacker or compromised principal has escalated their IAM permissions beyond what was intended. This can happen through overly permissive IAM policies, wildcard permissions, the ability to create or modify policies, or by assuming roles with broader access. Privilege escalation is often the second step after initial access.
GuardDuty detects anomalous IAM behavior that may indicate privilege escalation.
Look for IAM policy creation, attachment, or modification events by the suspected principal.
for event in CreatePolicy PutUserPolicy PutRolePolicy AttachUserPolicy AttachRolePolicy CreateRole; do
echo "=== $event ==="
aws cloudtrail lookup-events \
--lookup-attributes AttributeKey=EventName,AttributeValue=$event \
--start-time <incident-start> \
--max-items 10
doneAn attacker with sts:AssumeRole permission can pivot to more powerful roles.
aws cloudtrail lookup-events \ --lookup-attributes AttributeKey=EventName,AttributeValue=AssumeRole \ --start-time <incident-start> --max-items 20
Immediately block all actions by the principal that performed the escalation.
aws iam put-user-policy \
--user-name <username> \
--policy-name DenyAll-IncidentResponse \
--policy-document '{"Version":"2012-10-17","Statement":[{"Effect":"Deny","Action":"*","Resource":"*"}]}'If the attacker created or modified IAM policies, revert those changes immediately.
# List policy versions (attacker may have created new versions) aws iam list-policy-versions --policy-arn <policy-arn>
# Delete the attacker-created version aws iam delete-policy-version \ --policy-arn <policy-arn> \ --version-id v2
Add time-based deny conditions to invalidate any temporary credentials obtained through the escalated roles.
Compare current IAM policies against known-good baseline and revert any modifications.
# Get the current policy version aws iam get-policy-version \ --policy-arn <policy-arn> \ --version-id <version>
Delete any IAM users, roles, or policies created by the attacker for persistence.
# Find policies created during incident
aws iam list-policies --scope Local \
--query 'Policies[?CreateDate>=`<incident-start>`].{Name:PolicyName,Arn:Arn}' \
--output tableThe attacker may have modified role trust policies to allow cross-account access from attacker-controlled accounts.
for role in $(aws iam list-roles --query 'Roles[].RoleName' --output text); do
echo "=== $role ==="
aws iam get-role --role-name $role \
--query 'Role.AssumeRolePolicyDocument' 2>/dev/null
doneReplace overly permissive policies with least-privilege versions based on actual usage.
# Use IAM Access Analyzer to generate least-privilege policies
aws accessanalyzer start-policy-generation \
--policy-generation-details '{"principalArn":"<role-arn>"}'Continuously analyze IAM policies for overly permissive access.
aws accessanalyzer create-analyzer \ --analyzer-name "org-analyzer" \ --type ORGANIZATION
Audit which principals have iam:CreatePolicy, iam:AttachRolePolicy, and other dangerous IAM permissions.
Use IAM permission boundaries to cap the maximum permissions that any role or user can have, even if someone attaches additional policies.
Use SCPs to deny iam:CreatePolicy, iam:AttachRolePolicy, and other dangerous actions except for designated admin roles.
Schedule periodic reviews of IAM Access Analyzer findings to detect permission drift.
When an incident strikes, every minute counts. We help AWS teams prepare, detect, and respond to security incidents with proven expertise.