Skip to main content

No Potential Privilege Escalation Activity Detected in CloudTrail

Overview

This check analyzes CloudTrail logs to detect identities (IAM users or roles) performing high-risk actions associated with privilege escalation. Actions like AttachPolicy, PassRole, AssumeRole, and CreateAccessKey are monitored. If an identity exceeds a threshold of such events within a recent time window, it is flagged for investigation.

Privilege escalation is one of the most dangerous attack patterns because it allows an attacker with limited access to gain elevated permissions, potentially taking full control of your AWS environment.

Risk

When this check fails, an identity in your account may be attempting privilege escalation. The security impacts include:

  • Confidentiality loss: Unauthorized access to sensitive data and secrets
  • Integrity compromise: Modification of IAM policies and role configurations
  • Availability impact: Tampering with logging, alerting, or critical resources
  • Lateral movement: Attackers can move across accounts and services
  • Persistence: Establishment of long-term backdoor access

This finding requires immediate investigation to determine if the activity is legitimate or malicious.

Remediation Steps

Prerequisites

You need:

  • AWS Console access with IAM and CloudTrail read/write permissions
  • For preventive controls: AWS Organizations management account access
Setting up AWS CLI access (optional)

If you prefer using the command line, ensure you have:

  1. AWS CLI installed: Installation guide
  2. Credentials configured with appropriate permissions:
    aws configure
  3. Verify access:
    aws sts get-caller-identity

Step 1: Investigate the Finding

Before taking action, understand what triggered the alert.

  1. Go to AWS Console > CloudTrail > Event history
  2. Filter by the IAM identity (user or role ARN) from the Prowler finding
  3. Look for these high-risk API calls:
    • AttachUserPolicy, AttachRolePolicy, AttachGroupPolicy
    • PutUserPolicy, PutRolePolicy, PutGroupPolicy
    • CreateAccessKey
    • UpdateAssumeRolePolicy
    • PassRole
    • AssumeRole
  4. Review the timing, source IP addresses, and context of these calls
  5. Determine if the activity was legitimate (e.g., planned deployment) or suspicious
AWS CLI investigation commands

Look up recent privilege escalation events for a specific user:

aws cloudtrail lookup-events \
--region us-east-1 \
--lookup-attributes AttributeKey=Username,AttributeValue=<username> \
--start-time $(date -u -d '24 hours ago' +%Y-%m-%dT%H:%M:%SZ) \
--query 'Events[?contains(EventName, `Attach`) || contains(EventName, `PassRole`) || contains(EventName, `CreateAccessKey`)]'

For macOS, use this date format instead:

aws cloudtrail lookup-events \
--region us-east-1 \
--lookup-attributes AttributeKey=Username,AttributeValue=<username> \
--start-time $(date -u -v-24H +%Y-%m-%dT%H:%M:%SZ) \
--query 'Events[?contains(EventName, `Attach`) || contains(EventName, `PassRole`) || contains(EventName, `CreateAccessKey`)]'

Step 2: Contain the Compromised Identity (If Malicious)

If you determine the activity is malicious, immediately contain the identity.

For IAM Users:

  1. Go to IAM > Users > select the flagged user
  2. Click the Security credentials tab
  3. Under Access keys, click Make inactive for all active keys
  4. Under Console sign-in, click Manage > Disable console access
  5. Go to the Permissions tab and remove all attached policies
  6. Go to the Groups tab and remove the user from all groups

For IAM Roles:

  1. Go to IAM > Roles > select the flagged role
  2. Go to the Permissions tab and detach all policies
  3. Go to the Trust relationships tab and review/restrict who can assume the role
  4. Consider adding a deny-all inline policy as an emergency block
AWS CLI containment commands

Deactivate all access keys for a user:

# List access keys
aws iam list-access-keys --user-name <username> --region us-east-1

# Deactivate each key
aws iam update-access-key \
--user-name <username> \
--access-key-id <access-key-id> \
--status Inactive \
--region us-east-1

Remove all attached managed policies from a user:

# List attached policies
aws iam list-attached-user-policies --user-name <username> --region us-east-1

# Detach each policy
aws iam detach-user-policy \
--user-name <username> \
--policy-arn <policy-arn> \
--region us-east-1

Remove all inline policies from a user:

# List inline policies
aws iam list-user-policies --user-name <username> --region us-east-1

# Delete each inline policy
aws iam delete-user-policy \
--user-name <username> \
--policy-name <policy-name> \
--region us-east-1

Add emergency deny-all policy to a role:

aws iam put-role-policy \
--role-name <role-name> \
--policy-name EmergencyDenyAll \
--policy-document '{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Deny",
"Action": "*",
"Resource": "*"
}]
}' \
--region us-east-1

Step 3: Implement Preventive Controls

After containment, implement controls to prevent future privilege escalation attempts.

Apply least privilege:

  1. Review and minimize permissions for all IAM users and roles
  2. Remove unused permissions, especially:
    • iam:PassRole
    • iam:Attach*Policy
    • iam:Put*Policy
    • iam:UpdateAssumeRolePolicy
    • iam:CreateAccessKey

Set up permission boundaries:

  1. Go to IAM > Policies > Create policy
  2. Create a policy that defines the maximum permissions any user/role can have
  3. Attach as a permission boundary to all users and roles

Require MFA for sensitive operations:

  1. Add MFA conditions to IAM policies for high-risk actions
Service Control Policy (SCP) to block privilege escalation

If you use AWS Organizations, deploy an SCP to block privilege escalation actions organization-wide.

SCP Policy Document:

{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyPrivilegeEscalationActions",
"Effect": "Deny",
"Action": [
"iam:CreateAccessKey",
"iam:AttachUserPolicy",
"iam:AttachRolePolicy",
"iam:AttachGroupPolicy",
"iam:PutUserPolicy",
"iam:PutRolePolicy",
"iam:PutGroupPolicy",
"iam:UpdateAssumeRolePolicy",
"iam:PassRole"
],
"Resource": "*",
"Condition": {
"StringNotEquals": {
"aws:PrincipalTag/AllowedPrivilegeEscalation": "true"
}
}
}
]
}

This SCP allows exceptions for principals tagged with AllowedPrivilegeEscalation=true, enabling your CI/CD pipelines and authorized administrators to function.

Deploy via AWS Console:

  1. Go to AWS Organizations > Policies > Service control policies
  2. Click Create policy
  3. Enter a name like PreventPrivilegeEscalation
  4. Paste the policy document above
  5. Attach to target OUs or accounts
CloudFormation template
AWSTemplateFormatVersion: '2010-09-09'
Description: SCP to prevent privilege escalation actions

Parameters:
TargetOUId:
Type: String
Description: The ID of the organizational unit to attach this SCP to

Resources:
PreventPrivilegeEscalationSCP:
Type: AWS::Organizations::Policy
Properties:
Name: PreventPrivilegeEscalation
Description: Blocks high-risk privilege escalation actions
Type: SERVICE_CONTROL_POLICY
TargetIds:
- !Ref TargetOUId
Content:
Version: '2012-10-17'
Statement:
- Sid: DenyPrivilegeEscalationActions
Effect: Deny
Action:
- iam:CreateAccessKey
- iam:AttachUserPolicy
- iam:AttachRolePolicy
- iam:AttachGroupPolicy
- iam:PutUserPolicy
- iam:PutRolePolicy
- iam:PutGroupPolicy
- iam:UpdateAssumeRolePolicy
- iam:PassRole
- sts:AssumeRole
Resource: '*'
Condition:
StringNotEquals:
aws:PrincipalTag/AllowedPrivilegeEscalation: 'true'

Deploy with:

aws cloudformation create-stack \
--stack-name prevent-privilege-escalation-scp \
--template-body file://scp-template.yaml \
--parameters ParameterKey=TargetOUId,ParameterValue=<ou-xxxx-xxxxxxxx> \
--region us-east-1
Terraform module
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}

variable "target_ou_id" {
description = "The ID of the organizational unit to attach the SCP to"
type = string
}

resource "aws_organizations_policy" "prevent_privilege_escalation" {
name = "PreventPrivilegeEscalation"
description = "Blocks high-risk privilege escalation actions"
type = "SERVICE_CONTROL_POLICY"

content = jsonencode({
Version = "2012-10-17"
Statement = [
{
Sid = "DenyPrivilegeEscalationActions"
Effect = "Deny"
Action = [
"iam:CreateAccessKey",
"iam:AttachUserPolicy",
"iam:AttachRolePolicy",
"iam:AttachGroupPolicy",
"iam:PutUserPolicy",
"iam:PutRolePolicy",
"iam:PutGroupPolicy",
"iam:UpdateAssumeRolePolicy",
"iam:PassRole",
"sts:AssumeRole"
]
Resource = "*"
Condition = {
StringNotEquals = {
"aws:PrincipalTag/AllowedPrivilegeEscalation" = "true"
}
}
}
]
})
}

resource "aws_organizations_policy_attachment" "prevent_privilege_escalation" {
policy_id = aws_organizations_policy.prevent_privilege_escalation.id
target_id = var.target_ou_id
}

output "scp_id" {
description = "The ID of the created SCP"
value = aws_organizations_policy.prevent_privilege_escalation.id
}

Deploy with:

terraform init
terraform apply -var="target_ou_id=ou-xxxx-xxxxxxxx"

Step 4: Enhance Monitoring and Alerting

Set up alerts to detect future privilege escalation attempts.

  1. Go to CloudWatch > Alarms > Create alarm
  2. Create a metric filter for CloudTrail events matching privilege escalation actions
  3. Set up SNS notifications to alert your security team

Alternatively, enable AWS GuardDuty which automatically detects many privilege escalation patterns.

Verification

After remediation, verify the issue is resolved:

  1. Re-run the Prowler check:
    prowler aws --checks cloudtrail_threat_detection_privilege_escalation
  2. Confirm the previously flagged identity no longer appears in findings
  3. Test that your preventive controls work by attempting a blocked action from a non-exempt identity (in a test environment)
Advanced verification steps

Verify user containment:

# Check user has no active access keys
aws iam list-access-keys --user-name <username> --region us-east-1 \
--query 'AccessKeyMetadata[?Status==`Active`]'

# Check user has no attached policies
aws iam list-attached-user-policies --user-name <username> --region us-east-1

# Check user has no inline policies
aws iam list-user-policies --user-name <username> --region us-east-1

Verify SCP is attached:

aws organizations list-policies-for-target \
--target-id <ou-id-or-account-id> \
--filter SERVICE_CONTROL_POLICY \
--region us-east-1

Additional Resources

Notes

  • Time sensitivity: Privilege escalation findings are critical and should be investigated immediately. Delayed response increases the risk of data breach or account compromise.
  • False positives: Legitimate administrative activities (deployments, automation) can trigger this check. Correlate with change management records before assuming malicious intent.
  • Incident response: If you confirm a compromise, follow your organization's incident response plan. Consider engaging AWS Support or a security incident response team.
  • SCP exceptions: The SCP examples include a tag-based exception mechanism. Ensure only trusted CI/CD roles and break-glass accounts have the AllowedPrivilegeEscalation=true tag.
  • Multi-region considerations: Privilege escalation can occur in any region. Ensure CloudTrail is enabled in all regions and consider using AWS Organizations trail for comprehensive coverage.