Attacking AWS IAM: Common Misconfigurations and How to Find Them
A practical walkthrough of the most frequently abused IAM misconfigurations I encounter during AWS penetration tests, with detection and remediation guidance for each.
Introduction
AWS Identity and Access Management (IAM) is simultaneously one of the most powerful and most dangerous services in the AWS platform. After hundreds of AWS-focused assessments, the same misconfigurations appear repeatedly — and they're often the difference between a contained incident and a full account compromise.
This post walks through the top five IAM issues I encounter in the wild, how to detect them, and what to do about them.
1. Overly Permissive Inline Policies with Wildcards
The pattern "Action": "*" or "Resource": "*" in an inline policy is almost always a mistake. It frequently appears in automation roles, Lambda execution roles, and developer sandbox accounts that somehow made it to production.
{
"Effect": "Allow",
"Action": "*",
"Resource": "*"
}
Detection: Run aws iam get-account-authorization-details and grep for "Action": "*". Tools like Prowler will surface these automatically.
Remediation: Scope policies to the minimum set of actions and resources the principal actually needs. Use IAM Access Analyzer to validate.
2. Long-lived Access Keys on Human Identities
Access keys are convenient but dangerous. A key rotated infrequently (or never) that leaks into a public GitHub repository is the single most common root cause I see in cloud incident response.
Detection:
aws iam generate-credential-report
aws iam get-credential-report --query 'Content' --output text | base64 -d
Look for access keys with access_key_1_last_rotated older than 90 days.
Remediation: Mandate short-lived credentials via AWS SSO (IAM Identity Center) for human access. Reserve long-lived keys for service accounts where SSO is not feasible, and rotate them every 90 days.
3. Trust Policies That Allow Cross-Account AssumeRole Without Conditions
A trust policy like this allows any principal in account 123456789012 to assume the role — including any IAM user or role that can call sts:AssumeRole:
{
"Principal": {
"AWS": "arn:aws:iam::123456789012:root"
},
"Action": "sts:AssumeRole"
}
If account 123456789012 is a partner, a customer, or a vendor — this is a potential confused deputy.
Remediation: Add an aws:PrincipalArn condition to restrict which principals in the trusted account can assume the role.
4. Permission Boundaries That Don't Actually Bound
Permission boundaries are a great control for developer sandbox environments, but I regularly see them defined in a way that doesn't prevent privilege escalation. If a boundary allows iam:PassRole or iam:CreateRole without restriction, an attacker with those permissions can create a new role, bypass the boundary, and escalate.
Remediation: Ensure permission boundaries explicitly deny iam:CreateRole, iam:AttachRolePolicy, iam:PutRolePolicy, and iam:PassRole unless the target role also falls within the boundary.
5. S3 Bucket Policies That Grant s3:GetObject to All Principals
This one sounds obvious, but it still crops up — especially for buckets used to serve static assets. If the bucket contains anything other than truly public content (CloudFront logs, deployment artefacts, application configs), this is a data exposure risk.
Detection:
aws s3api get-bucket-policy --bucket <bucket-name>
Look for "Principal": "*" without a aws:SourceVpce or aws:SourceIp condition.
Conclusion
IAM misconfigurations are endemic across organisations of all sizes. The good news is that most of them are detectable with free tooling — Prowler, ScoutSuite, and AWS's own IAM Access Analyzer will catch the majority of the issues above. The challenge is building the organisational discipline to remediate them before an adversary exploits them.
If you'd like a structured AWS security review, get in touch.