Authorization bypass due to full administrative IAM permissions in AWS policy

Critical Risk infrastructure-security
awsiamauthorization-bypassprivilege-escalationadmin-permissionsleast-privilegeaccount-takeover

What it is

AWS IAM policies that grant broad administrative permissions (such as iam:*, *, or AdministratorAccess) enable complete account takeover by allowing principals to assume any role, escalate privileges, access any resource, and disable security controls. This creates an extreme security risk where compromised credentials can lead to total AWS account compromise.

# VULNERABLE: Policy with full admin access
data "aws_iam_policy_document" "vulnerable_admin" {
  statement {
    effect = "Allow"
    
    # VULNERABLE: Complete access to everything
    actions = ["*"]
    resources = ["*"]
  }
}

# VULNERABLE: IAM-specific admin permissions
data "aws_iam_policy_document" "vulnerable_iam" {
  statement {
    effect = "Allow"
    
    # VULNERABLE: All IAM actions
    actions = ["iam:*"]
    resources = ["*"]
  }
}

resource "aws_iam_role_policy" "vulnerable" {
  name   = "admin-policy"
  role   = aws_iam_role.app.name
  policy = data.aws_iam_policy_document.vulnerable_admin.json
}

# VULNERABLE: Using managed admin policy
resource "aws_iam_role_policy_attachment" "vulnerable_managed" {
  role       = aws_iam_role.app.name
  policy_arn = "arn:aws:iam::aws:policy/AdministratorAccess"
}
# SECURE: Policy with least-privilege permissions
data "aws_iam_policy_document" "secure_policy" {
  statement {
    sid    = "S3ReadAccess"
    effect = "Allow"
    
    # SECURE: Specific S3 actions only
    actions = [
      "s3:GetObject",
      "s3:ListBucket"
    ]
    
    resources = [
      "arn:aws:s3:::app-bucket",
      "arn:aws:s3:::app-bucket/*"
    ]
  }
  
  statement {
    sid    = "DynamoDBAccess"
    effect = "Allow"
    
    # SECURE: Specific DynamoDB actions
    actions = [
      "dynamodb:GetItem",
      "dynamodb:PutItem",
      "dynamodb:Query"
    ]
    
    resources = [
      "arn:aws:dynamodb:us-east-1:123456789012:table/AppData"
    ]
  }
  
  statement {
    sid    = "LogsAccess"
    effect = "Allow"
    
    # SECURE: CloudWatch Logs write only
    actions = [
      "logs:CreateLogGroup",
      "logs:CreateLogStream",
      "logs:PutLogEvents"
    ]
    
    resources = [
      "arn:aws:logs:us-east-1:123456789012:log-group:/aws/lambda/app-*"
    ]
  }
}

resource "aws_iam_role_policy" "secure" {
  name   = "app-policy"
  role   = aws_iam_role.app.name
  policy = data.aws_iam_policy_document.secure_policy.json
}

💡 Why This Fix Works

The vulnerable configurations use Action: '*' or 'iam:*' wildcards, granting complete administrative access to all AWS services and resources. The secure version replaces wildcards with specific, enumerated actions for each service needed (S3, DynamoDB, CloudWatch Logs), applies resource-level restrictions with specific ARNs, and follows the principle of least privilege by granting only the minimum permissions required for the application to function.

Why it happens

IAM policies use Action: '*' wildcard granting unrestricted access to all AWS services and operations. This overly broad permission enables complete account takeover if credentials are compromised, violating least-privilege principles.

Root causes

Wildcard Action Permissions

IAM policies use Action: '*' wildcard granting unrestricted access to all AWS services and operations. This overly broad permission enables complete account takeover if credentials are compromised, violating least-privilege principles.

IAM Administrative Wildcards

Policies grant iam:* permissions allowing complete IAM control including creating users, modifying policies, assuming any role, and escalating privileges. IAM wildcards enable attackers to grant themselves additional permissions and persist access.

AdministratorAccess Managed Policy

Roles or users attached to the AWS-managed AdministratorAccess policy (arn:aws:iam::aws:policy/AdministratorAccess) which grants * actions on * resources. This convenience policy creates extreme security risks.

Unrestricted Resource Access

IAM policy statements combine broad Allow effects with Action wildcards and Resource: '*', providing unlimited access without resource-level restrictions. Compromised credentials can access any resource in the account.

Convenience Over Security

Organizations prioritize rapid development and operational convenience by granting admin permissions instead of implementing granular, least-privilege IAM policies. Security is sacrificed to avoid determining specific required permissions.

Fixes

1

Replace Wildcards with Specific Actions

Replace Action: '*' and 'iam:*' wildcards with explicit lists of required permissions. Enumerate specific actions needed for each use case (e.g., 's3:GetObject', 'dynamodb:PutItem') rather than granting blanket access.

2

Enumerate Required Permissions Only

Audit application and infrastructure requirements to determine the minimum necessary permissions. Create IAM policies containing only the specific actions required for legitimate operations, eliminating unnecessary access.

3

Apply Least-Privilege Principles

Design all IAM policies following least-privilege principles where principals receive the minimum permissions needed to perform their functions. Regularly review and tighten policies to remove unused permissions.

4

Implement Resource-Level Restrictions

Combine specific actions with resource-level ARN restrictions. Use Resource fields to limit access to specific S3 buckets, DynamoDB tables, or other resources, preventing lateral movement even with compromised credentials.

5

Use Permission Boundaries

Implement IAM permission boundaries to set maximum permissions for delegated IAM role or user creation. Boundaries prevent privilege escalation by ensuring created principals cannot exceed defined permission limits, even with iam:Create* access.

Detect This Vulnerability in Your Code

Sourcery automatically identifies authorization bypass due to full administrative iam permissions in aws policy and many other security issues in your codebase.