IAM AWS-Managed Policies Should Not Grant Administrative Privileges
Overview
This check identifies AWS-managed IAM policies that grant full administrative access (*:* permissions) and are attached to users, groups, or roles. Policies like AdministratorAccess allow unrestricted access to all AWS services and resources, which violates the principle of least privilege.
Risk
Full administrative access (*:*) creates critical security exposure:
- Data theft: Attackers can read and exfiltrate sensitive data from any service
- Data tampering: Unauthorized modifications to databases, files, and configurations
- Service disruption: Ability to delete or shut down critical resources
- Audit evasion: Disabling CloudTrail, logs, and security monitoring
- Persistence: Creating backdoor IAM users or roles for continued access
- Lateral movement: Compromised credentials can access any resource in the account
Severity: Critical
Remediation Steps
Prerequisites
- AWS Console access with IAM permissions (or an administrator who can help)
- Knowledge of which users/roles need access and what they actually need to do
AWS Console Method
-
Open the IAM Console
- Go to https://console.aws.amazon.com/iam/
- Click Policies in the left navigation
-
Find the Flagged Policy
- Search for
AdministratorAccess(or the specific policy from Prowler) - Click the policy name to open its details
- Search for
-
View Attached Entities
- Click the Entities attached tab
- Note all users, groups, and roles using this policy
-
Detach the Policy
- For each entity listed:
- Select the checkbox next to the entity name
- Click Detach
- Confirm the detachment
- For each entity listed:
-
Assign Appropriate Permissions
- For each entity, determine what access they actually need
- Attach more specific AWS-managed policies (e.g.,
ReadOnlyAccess,PowerUserAccess) or create custom policies - See the "Creating Least-Privilege Policies" section below for guidance
AWS CLI Method
Step 1: Identify Attached Entities
List all users, groups, and roles attached to the AdministratorAccess policy:
aws iam list-entities-for-policy \
--policy-arn arn:aws:iam::aws:policy/AdministratorAccess \
--region us-east-1
Example output:
{
"PolicyGroups": [
{"GroupName": "Admins", "GroupId": "AGPACKCEVSQ6C2EXAMPLE"}
],
"PolicyUsers": [
{"UserName": "alice", "UserId": "AIDACKCEVSQ6C2EXAMPLE"}
],
"PolicyRoles": [
{"RoleName": "AdminRole", "RoleId": "AROADBQP57FF2AEXAMPLE"}
]
}
Step 2: Detach from Users
aws iam detach-user-policy \
--user-name <username> \
--policy-arn arn:aws:iam::aws:policy/AdministratorAccess \
--region us-east-1
Step 3: Detach from Groups
aws iam detach-group-policy \
--group-name <group-name> \
--policy-arn arn:aws:iam::aws:policy/AdministratorAccess \
--region us-east-1
Step 4: Detach from Roles
aws iam detach-role-policy \
--role-name <role-name> \
--policy-arn arn:aws:iam::aws:policy/AdministratorAccess \
--region us-east-1
Step 5: Attach Replacement Policies
Attach more specific policies based on actual needs:
# Example: Attach PowerUserAccess instead (no IAM management)
aws iam attach-user-policy \
--user-name <username> \
--policy-arn arn:aws:iam::aws:policy/PowerUserAccess \
--region us-east-1
CloudFormation Example
When defining IAM roles in CloudFormation, avoid AdministratorAccess and use specific policies instead.
Avoid this (overly permissive):
Resources:
AdminRole:
Type: AWS::IAM::Role
Properties:
RoleName: MyRole
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service: ec2.amazonaws.com
Action: sts:AssumeRole
ManagedPolicyArns:
# DO NOT USE - grants full admin access
- arn:aws:iam::aws:policy/AdministratorAccess
Use this instead (scoped permissions):
AWSTemplateFormatVersion: '2012-10-17'
Description: IAM role with least-privilege permissions
Resources:
ScopedRole:
Type: AWS::IAM::Role
Properties:
RoleName: MyAppRole
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service: ec2.amazonaws.com
Action: sts:AssumeRole
ManagedPolicyArns:
# Use specific AWS-managed policies
- arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess
- arn:aws:iam::aws:policy/AmazonDynamoDBReadOnlyAccess
CustomPolicy:
Type: AWS::IAM::Policy
Properties:
PolicyName: MyAppCustomPolicy
Roles:
- !Ref ScopedRole
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- s3:PutObject
- s3:DeleteObject
Resource: arn:aws:s3:::my-specific-bucket/*
- Effect: Allow
Action:
- dynamodb:PutItem
- dynamodb:UpdateItem
Resource: arn:aws:dynamodb:us-east-1:*:table/MyTable
Terraform Example
When defining IAM roles in Terraform, use specific policies rather than AdministratorAccess.
Avoid this (overly permissive):
# DO NOT USE - grants full admin access
resource "aws_iam_role_policy_attachment" "admin" {
role = aws_iam_role.example.name
policy_arn = "arn:aws:iam::aws:policy/AdministratorAccess"
}
Use this instead (scoped permissions):
# Define the role
resource "aws_iam_role" "app_role" {
name = "my-app-role"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = "sts:AssumeRole"
Effect = "Allow"
Principal = {
Service = "ec2.amazonaws.com"
}
}
]
})
}
# Attach specific AWS-managed policies
resource "aws_iam_role_policy_attachment" "s3_read" {
role = aws_iam_role.app_role.name
policy_arn = "arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess"
}
resource "aws_iam_role_policy_attachment" "dynamodb_read" {
role = aws_iam_role.app_role.name
policy_arn = "arn:aws:iam::aws:policy/AmazonDynamoDBReadOnlyAccess"
}
# Create a custom policy for specific write permissions
resource "aws_iam_policy" "app_write_policy" {
name = "my-app-write-policy"
description = "Limited write access for my application"
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Action = [
"s3:PutObject",
"s3:DeleteObject"
]
Resource = "arn:aws:s3:::my-specific-bucket/*"
},
{
Effect = "Allow"
Action = [
"dynamodb:PutItem",
"dynamodb:UpdateItem"
]
Resource = "arn:aws:dynamodb:us-east-1:*:table/MyTable"
}
]
})
}
resource "aws_iam_role_policy_attachment" "app_write" {
role = aws_iam_role.app_role.name
policy_arn = aws_iam_policy.app_write_policy.arn
}
Creating Least-Privilege Policies
Strategy for Replacing Administrative Access
-
Audit current usage: Use IAM Access Analyzer or CloudTrail to see what actions are actually being performed
-
Start with AWS-managed policies: AWS provides many job-function policies:
ViewOnlyAccess- Read-only access to most servicesReadOnlyAccess- Read-only access to all servicesPowerUserAccess- Full access except IAM management- Service-specific policies (e.g.,
AmazonEC2FullAccess,AmazonS3FullAccess)
-
Create custom policies: For fine-grained control, create customer-managed policies with only the required permissions
-
Use conditions: Add conditions to further restrict access:
{
"Effect": "Allow",
"Action": "s3:*",
"Resource": "*",
"Condition": {
"StringEquals": {
"aws:RequestedRegion": "us-east-1"
}
}
} -
Implement permissions boundaries: Set maximum permissions that can be granted to principals
Emergency Access Pattern
For emergency/break-glass scenarios where admin access may be needed:
- Create a separate "break-glass" role with
AdministratorAccess - Require MFA to assume the role
- Set a short session duration (1 hour)
- Enable detailed CloudTrail logging for the role
- Set up alerts when the role is assumed
Verification
After remediation, verify the fix:
-
In the AWS Console:
- Go to IAM > Policies > AdministratorAccess
- Click "Entities attached" tab
- Confirm no users, groups, or roles are listed
-
Re-run Prowler:
prowler aws -c iam_aws_attached_policy_no_administrative_privileges --region us-east-1
CLI Verification Commands
# Verify no entities are attached to AdministratorAccess
aws iam list-entities-for-policy \
--policy-arn arn:aws:iam::aws:policy/AdministratorAccess \
--region us-east-1
# Expected output (no attachments):
# {
# "PolicyGroups": [],
# "PolicyUsers": [],
# "PolicyRoles": []
# }
Additional Resources
- AWS IAM Best Practices
- AdministratorAccess Policy Reference
- IAM Access Analyzer
- AWS Job Function Managed Policies
- Using Permissions Boundaries
Notes
-
Do not remove admin access without a plan: Ensure you have alternative access methods in place before detaching administrative policies. Locking yourself out of an account is difficult to recover from.
-
Service-linked roles: Some AWS services create roles that may have broad permissions. These are managed by AWS and may not be modifiable.
-
Root account: This check applies to IAM identities, not the root account. Root account access should be secured separately with MFA and rarely used.
-
Break-glass procedures: Consider maintaining a documented emergency access procedure for situations requiring temporary administrative access, with proper controls and auditing.
-
Gradual rollout: For large organizations, consider a phased approach - start with non-critical environments, monitor for access issues, then apply to production.