IAM & Identity Security

Dangerous IAM Misconfigurations

4 min read

IAM misconfigurations are behind most cloud breaches. Understanding common mistakes helps you avoid them and recognize them during security assessments.

The Most Dangerous Patterns

1. Overly Permissive Policies ("Admin for Everyone")

The most common and dangerous misconfiguration:

{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Action": "*",
    "Resource": "*"
  }]
}

Why it's dangerous:

  • Any compromised credential = full account access
  • Violates least privilege principle
  • Common in development environments that make it to production

How to find:

# AWS CLI - Find policies with * actions
aws iam list-policies --scope Local --query 'Policies[*].Arn' | \
xargs -I {} aws iam get-policy-version --policy-arn {} --version-id v1 | \
grep -l '"Action": "\*"'

2. Public Trust Policies

IAM roles that anyone can assume:

{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": "*",
    "Action": "sts:AssumeRole"
  }]
}

Impact: Any AWS account in the world can assume this role.

Correct approach:

{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": {
      "AWS": "arn:aws:iam::123456789012:root"
    },
    "Action": "sts:AssumeRole",
    "Condition": {
      "StringEquals": {
        "sts:ExternalId": "unique-external-id"
      }
    }
  }]
}

3. Long-lived Access Keys

Static credentials that never rotate:

# Access keys older than 90 days
aws iam list-access-keys --user-name developer
# Output shows creation date from 2023...

Risks:

  • Keys leaked in code repositories
  • Keys stored on compromised laptops
  • No expiration = unlimited attack window

Solution: Use IAM roles and temporary credentials:

# Instead of hardcoded credentials
import boto3

# Use instance profile (no credentials in code)
session = boto3.Session()
s3 = session.client('s3')

# Or assume a role
sts = boto3.client('sts')
credentials = sts.assume_role(
    RoleArn='arn:aws:iam::123456789012:role/MyRole',
    RoleSessionName='MySession'
)

4. Missing MFA Requirements

Allowing sensitive operations without MFA:

{
  "Effect": "Allow",
  "Action": ["iam:*", "s3:*"],
  "Resource": "*"
}

Should be:

{
  "Effect": "Allow",
  "Action": ["iam:*", "s3:*"],
  "Resource": "*",
  "Condition": {
    "Bool": {
      "aws:MultiFactorAuthPresent": "true"
    }
  }
}

5. Confused Deputy Problem

Cross-account access without External ID:

Vulnerable trust policy:

{
  "Principal": {
    "AWS": "arn:aws:iam::111111111111:root"
  },
  "Action": "sts:AssumeRole"
}

Attack scenario:

  1. You grant access to a third-party service (Account A)
  2. Attacker also uses that service
  3. Attacker tricks service into assuming your role
  4. Attacker gains access to your account

Prevention:

{
  "Principal": {
    "AWS": "arn:aws:iam::111111111111:root"
  },
  "Action": "sts:AssumeRole",
  "Condition": {
    "StringEquals": {
      "sts:ExternalId": "your-unique-id-here"
    }
  }
}

Azure-Specific Misconfigurations

Excessive Custom Role Permissions

{
  "Name": "CustomAdmin",
  "Actions": [
    "*"
  ],
  "AssignableScopes": [
    "/subscriptions/subscription-id"
  ]
}

Missing Conditional Access

No MFA requirement for privileged roles:

  • Global Administrator accessing from any location
  • No impossible travel detection
  • No device compliance requirement

Service Principal Secrets

Long-lived secrets instead of certificate authentication:

# Service principal with password credential (risky)
az ad sp create-for-rbac --name "MyApp" --password "WeakPassword123"

# Better: Use certificate authentication
az ad sp create-for-rbac --name "MyApp" --cert @cert.pem

GCP-Specific Misconfigurations

Primitive Roles on Production

Using Owner/Editor instead of predefined roles:

# BAD: Primitive role with excessive permissions
gcloud projects add-iam-policy-binding my-project \
    --member="user:developer@example.com" \
    --role="roles/editor"

# GOOD: Specific predefined role
gcloud projects add-iam-policy-binding my-project \
    --member="user:developer@example.com" \
    --role="roles/cloudsql.viewer"

Service Account Key Export

Downloading service account keys creates long-lived credentials:

# Creates downloadable key (avoid this)
gcloud iam service-accounts keys create key.json \
    --iam-account=sa@project.iam.gserviceaccount.com

Better approach: Workload Identity for GKE, attached service accounts for Compute.

Detection Checklist

Misconfiguration Detection Method
Wildcard policies Policy analysis tools (Prowler, ScoutSuite)
Public principals Trust policy review
Old access keys IAM credential report
No MFA Credential report, Console audit
Unused permissions IAM Access Analyzer (AWS)
Overprivileged roles Permission boundary analysis

Next, we'll explore credential management best practices to prevent these issues. :::

Quiz

Module 2: IAM & Identity Security

Take Quiz