# IAM Unauthenticated Enumeration

> Techniques for enumerating AWS IAM resources without valid credentials, identifying exposed roles, policies, and principals through unauthenticated API calls.

- **URL:** https://hackindex.io/platforms/aws/enumeration/iam/iam-unauthenticated-enumeration
- **Path:** AWS > Enumeration > IAM
- **Up:** [IAM](https://hackindex.io/platforms/aws/enumeration/iam.md)
- **Published:** 2026-05-24
- **Updated:** 2026-05-24

AWS error messages differ between non-existent principals and valid ones that simply lack permissions. This allows confirming whether a username or role exists without any credentials. You only need a valid AWS account to make API calls against the target. The target account logs nothing useful during this phase because the operations happen on resources you control. Use this technique early in an engagement. It works when you have no foothold in the target environment. Map IAM principals before attempting credential attacks.

- Your own AWS account (any tier) to perform policy-based principal validation
- Target account ID (obtainable from public S3 buckets, error messages, or OSINT)
- Wordlist tuned to the target's naming conventions (check their GitHub, job posts)
- Confirmed user ARNs for credential spray and public key exposure hunting

## Error-Based User Enumeration

**quiet-riot** brute-forces IAM principal names using resource-based policy insertion errors. It runs from your attacker machine and requires its own AWS account to perform the checks. The tool constructs principal ARNs and attaches them to a resource-based policy on a resource in your account. AWS validates principal ARNs at write time. A non-existent principal causes an error. A valid principal causes no error or returns `AccessDenied` based on your account permissions.

```bash
git clone https://github.com/righteousgambit/quiet-riot
cd quiet-riot
python3 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
```

**Enumerate users**

```bash
quiet_riot --scan_type 4.2 --wordlist /usr/share/seclists/Usernames/Names/names.txt --threads 30 --profile $PROFILE
```

**Enumerate roles**

```bash
quiet_riot --scan_type 4.1 --wordlist wordlist.txt --threads 30 --profile $PROFILE
```

The tool attempts to insert a test principal ARN into a resource-based policy. A `MalformedPolicyDocumentException` means the principal does **not** exist (AWS rejects non-existent principal ARNs in policies). No exception (or `AccessDenied`) means the principal exists. When you confirm a hit, record the full ARN including the account ID. Users and roles have different attack surfaces. Users can carry long-lived access keys that may be exposed in code repositories or environment variables. Roles require a trust relationship to assume and are targeted via cross-account access or SSRF chains. Prioritize confirmed user ARNs for credential hunting. Check GitHub, GitLab, and public S3 buckets for access keys tied to those usernames.

> [!WARNING]
> This generates CloudTrail `AssumeRole` events in the target account for every tested principal name. Use a wordlist matched to the target's naming conventions to reduce noise.

## Note on sts:AssumeRole Error Discrimination

The sts:AssumeRole AccessDenied-vs-NoSuchEntity oracle is no longer reliable. AWS now returns `AccessDenied` regardless of whether the target role exists. Use the resource-based policy technique via quiet-riot instead. This change affects all tooling that relied on the STS error difference. If a tool or write-up references the STS oracle approach, treat its output as unreliable. The resource-based policy technique is the confirmed working method for unauthenticated principal enumeration.

## Wordlists for IAM Enumeration

Common IAM role name patterns to try. Most AWS environments use predictable names tied to their service stack. Prioritize names that match technology you have already identified for the target. If the target uses Terraform, try `terraform` and `terraform-backend`. CI/CD pipelines almost always have a dedicated IAM role. GitHub Actions deployments commonly use a role named `github-actions` or a close variant. Check the target's public GitHub repos, job postings, and LinkedIn to infer naming patterns before running a full wordlist. Service-specific roles follow patterns like `ec2-role` or `lambda-execution-role`. Cross-account roles often include words like `cross-account`, `audit`, or the partner organization's name.

```
admin
Administrator
AdminRole
OrganizationAccountAccessRole
ReadOnlyAccess
PowerUserAccess
ec2-role
lambda-role
ecs-task-role
github-actions
deploy
ci-cd
terraform
s3-access
rds-access
cross-account
audit
security
devops
```

See [IAM Authenticated Enumeration](https://hackindex.io/platforms/aws/enumeration/iam/iam-authenticated-enumeration) for full enumeration once you have credentials. Principal names confirmed here feed directly into that workflow. A confirmed user ARN also reveals the target account ID, which is useful for scoping further attacks. Combine confirmed principals with credential spray, public key exposure checks, or assume-role attempts from other accounts.
