Skip to main contentSkip to main content
Room Banner
Back to all walkthroughs
Room Icon

AWS IAM Enumeration

Learn enumerating IAM Principals and implemented services.

medium

60 min

253

User profile photo.
User profile photo.

To access material, start machines and answer questions login.

Prerequisites

Before starting this room, it is beneficial to have an introductory knowledge of Identity and Access Management () in and should understand how an AssumeRoleTrust policy works. If you are unfamiliar with this topic, please visit the room for more information.

Learning Objectives

Knowing how to get information about resources without authenticating is an important skill for vulnerability assessments and penetration testing. In this room, you will learn how to perform Principal enumeration and partial service enumeration for environments. You will learn:

  • How resource policies can be abused to identify valid principals
  • How to use open source tools to efficiently enumerate valid principals in a given account
  • How to footprint potential services, including security services, enabled for an account

Remember, these Principals form the backbone of access in - without them, there is almost nothing you can do. By being able to identify what valid principals exist in another account - you form a basis of information to perform more well-informed attacks that are more likely to succeed.

It is possible to get information about principals from a target account and other insider information about an account while remaining unauthenticated to that account - this is referred to as unauthenticated enumeration. enumeration is a reconnaissance exercise that can be leveraged to attack an cloud environment, and by using this technique, an attacker can gain a better understanding of the landscape within an account without having access to it. pen testers and red teamers commonly use this gathered “insider knowledge” to gain information about resources residing within an environment in order to perform attacks against the target account.

Answer the questions below
Can you get information about an AWS account, including its IAM principals - without authenticating?

Select the Cloud details button at the top of the room:

Where needed generate the environment required for the room. The "Generate Environment" button will appear if the room contains an environment that needs to be generated. 

For any issues with the environment, select the "Reset Environment" button. Review this article for more information.

To view the credentials required for the environment, select the credentials tab. You can use these credentials to access the environment in various ways. More information can be found here:

Answer the questions below
Generate environment or set up your credentials

Scavenging For Credentials

You may find yourself on a machine and think - "Hey! I wonder if there is any loot on here?" Let's take a look at how you might enumerate principals and credentials in use on a machine you have compromised.  Boto3 (Python) SDK is one of the most mature tools out there for working with APIs. Therefore, we look to Boto3 documentation to see how Boto3 looks for credentials (opens in new tab) when running commands to learn where credentials might be stored. Reading through the docs, a few places stand out:

  • Environment Variables - users can set credentials using AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY as environment variables.
  • Shared Credentials File (~/./credentials) - this is the most common place when storing user access keys or configurations for assuming roles.
  • Config file (~/./config) - credential sources that reference helper scripts and other external credential providers are commonly referenced here.
  • Assume Role Provider - the trick here is to know that when someone uses or another mechanism to assume a role via the , the tool caches credentials for each role session at ~/.//cache/{role_session_id}.
  • Boto2 config file - Boto2 is the predecessor version to Boto3 and might be used in legacy clients.
  • Instance Metadata Service (IMDS) - on an Amazon instance that has an role configured.

While Boto3 checks for credentials stored at the "metadata endpoint" (learn more here (opens in new tab)), Elastic Service () tasks also have a metadata endpoint (://169.254.170.2/v2/metadata), store credentials as environment variables, and CloudShell stores credentials via a local host metadata endpoint. If you find yourself on a compromised system, any of these are potential sources of temporary credentials with varying levels of privilege. Let's get started by logging in to the CloudShell or our Attack Box with our credentials.

Get-Access-Key-Info

If you have found an access key during your local system discovery process - you probably have a few questions. Starting with, what account does this belong to? The   can help with this exact need, without being authenticated to the target account:

STS Get Access Key Info
           root@ip-10-10-89-159:~#  aws sts get-access-key-info --access-key-id {access_key_id}
        
Running this command should return the account to which the access key belongs. Interestingly enough, you can perform this command unauthenticated, meaning that you have implicit permissions to access this API by default in . This can help provide important context regarding the account you have compromised in conjunction with the account alias, along with IAM and other resource naming/tagging conventions. Go ahead and try it with your access key ID.

Resource-Based Policies

As we discussed back in the Basics room, resource-based policies are IAM policies applied directly to certain types of resources. Interestingly enough, these resource-based policies have a little quirk (opens in new tab) that allows attackers to identify any valid IAM Principal in a given account, and even the validity of any particular Account ID. Resource-based policies are comprised of the following format:

Example Resource-Based Policy
           root@ip-10-10-89-159:~# 
{       
"Statement": 
[{         
"Sid": "grant-1234-publish", 
        "Effect": "Allow", 
        "Principal": {           
               "AWS": {IAM_PRINCIPAL_TO_TEST} 
        }, 
        "Action": ["sns:Publish"], 
        "Resource": {EXAMPLE_SNS_TOPIC} 
      }] 
    }
        

When attempting to enumerate an Principal via resource policy, you simply create the resource that supports a resource-based policy, and then update it to allow access for the Principal you want to test whether it exists. If the Principal does not exist, the update command will return an error message. If the Principal does exist, then you will not receive an error message, and the updated resource-policy will be implemented. For most types of resource-based policies, this consists of the Account , Roles, and Users. Other types of Principals aren't enumerable using this method.

Answer the questions below
If an IAM Principal does not exist, what does an attempt to update the resource-based policy to include the "Principal" return?

In order to perform enumeration, we will be using a tool called Quiet Riot. Quiet Riot can be used for "unauthenticated" enumeration of /Azure Active Directory/Google Workspace users/principals. The reason I use quotes around "unauthenticated" is because even though you don't have to be authenticated against the target you intend on scanning, for Quiet Riot to work, you do need to be authenticated to an account with permissions to deploy resources that Quiet Riot will use in its scanning. You can view the source code for Quiet Riot on GitHub (opens in new tab).

If you are using the AttackBox to work the rooms, then you are already familiar with using the tool and using aws configure to configure your credentials. If you have been using CloudShell, this may be your first time loading credentials. Because CloudShell relies on the metadata service (opens in new tab) to retrieve and use credentials - you won't find any credentials configured in CloudShell if you try to navigate to ~/./credentials when you start up. This may be a problem when using tools that default to using the 'default' credential profile commonly implemented with  CLI

Once you have credentials configured, if using CloudShell, you will want to install Quiet Riot. You can do so by running the following command:

Install Quiet Riot
           root@ip-10-10-89-159:~# pip3 install quiet-riot
        

You can test that Quiet Riot is properly installed by running the following command:

Install Quiet Riot
           root@ip-10-10-89-159:~# quiet_riot --help

usage:  quiet_riot [--help,--h help] [--scan,--s SCAN] [--threads,--t THREADS] [--wordlist,--w WORDLIST] [--profile,--p PROFILE]

        

Now, you will want to use Quiet Riot to scan your target account for potential users and roles. During S3 and API Gateway rooms, you will note that Best Cloud Company appears to employ two individuals by the names of Adam and John. Assuming Adam and John are technology employees with access to AWS, we could attempt to look for their users by creating a wordlist of potential usernames using common patterns (opens in new tab) employed by companies and common family names (opens in new tab) in the USA, where Best Cloud Company appears to be based. Assuming you have the family names file stored in your local directory as familynames-usa-top1000.txt in your local directory, you could use something like the following script to generate a list of common "Adam" and "John" usernames:

script.py
           root@ip-10-10-89-159:~#  
#!/usr/bin/env python
malenames = ['adam', 'john']
with open('familynames-usa-top1000.txt', 'r') as f:
    lastnames = f.read().splitlines()
with open('test.txt', 'w') as f:
    for i in malenames:
        for j in lastnames:
            first = i.lower()
            last = j.lower()
            f.write(f"{first}.{last}\n")
            f.write(f"{first[0]}{last}\n")
            f.write(f"{first}\n")
            f.write(f"{first}_{last}\n")
            f.write(f"{first}{last}\n")
            f.write(f"{first}{j[0].lower()}\n")

        

You can try the script for yourself, but I've also included the pre-generated list (opens in new tab) of common usernames using the names adam and john, so that you might use them for yourself with Quiet Riot. Once you have the usernames, save them as usernames.txt in your machine of choice (AttackBox/CloudShell), then we can use Quiet Riot to test them out.

Quiet Riot Scan
           root@ip-10-10-89-159:~#  quiet_riot --scan 5
        

Then you will select option 1 or option 2, depending on whether you want to scan for roles or users. Roles are the more common pattern recently, but a lot of organizations are still deploying IAM users. Let's start with the roles. 

Quiet Riot IAM Roles Scan
           root@ip-10-10-89-159:~# quiet_riot --scan 5 
Input arguments : Namespace(scan=5, threads=100, wordlist='', profile='default')

    ________        .__        __    __________.__        __   
    \_____  \  __ __|__| _____/  |_  \______   \__| _____/  |_ 
     /  / \  \|  |  \  |/ __ \   __\  |       _/  |/  _ \   __/
    /   \_/.  \  |  /  \  ___/|  |    |    |   \  (  <_> )  |  
    \_____\ \_/____/|__|\___  >__|    |____|_  /__|\____/|__|  
           \__>             \/               \/                
    

1. IAM Roles

2. IAM Users

Kindly select one of the above scan types:1
        


Quiet Riot Provide Account ID
           root@ip-10-10-89-159:~#  quiet_riot --scan 5 
Input arguments : Namespace(scan=5, threads=100, wordlist='', profile='default')

    ________        .__        __    __________.__        __   
    \_____  \  __ __|__| _____/  |_  \______   \__| _____/  |_ 
     /  / \  \|  |  \  |/ __ \   __\  |       _/  |/  _ \   __/
    /   \_/.  \  |  /  \  ___/|  |    |    |   \  (  <_> )  |  
    \_____\ \_/____/|__|\___  >__|    |____|_  /__|\____/|__|  
           \__>             \/               \/                
    

1. IAM Roles

2. IAM Users

Kindly select one of the above scan types:1
Provide an an Account ID to scan against: {Your_Current_Account_ID}
        

You'll provide your current AWS Account ID - but this approach woudl work even if you were scanning a different account.

Quiet Riot Provide Wordlist
           root@ip-10-10-89-159:~#  quiet_riot --scan 5 
Input arguments : Namespace(scan=5, threads=100, wordlist='', profile='default')

    ________        .__        __    __________.__        __   
    \_____  \  __ __|__| _____/  |_  \______   \__| _____/  |_ 
     /  / \  \|  |  \  |/ __ \   __\  |       _/  |/  _ \   __/
    /   \_/.  \  |  /  \  ___/|  |    |    |   \  (  <_> )  |  
    \_____\ \_/____/|__|\___  >__|    |____|_  /__|\____/|__|  
           \__>             \/               \/                
    

1. IAM Roles

2. IAM Users

Kindly select one of the above scan types:1
Provide an an Account ID to scan against: {Your_Current_Account_ID}

Provide the path to wordlist file : test.txt

        

Now that you've provided your wordlist - we press enter and wait for the scan to conclude. You can expect a scan with this many options to take between 3-10 minutes depending on a variety of factors, including network latency and potential API throttling by .

Quiet Riot Role Scan Results
           root@ip-10-10-89-159:~#  quiet_riot --scan 5 
Input arguments : Namespace(scan=5, threads=100, wordlist='', profile='default')

    ________        .__        __    __________.__        __   
    \_____  \  __ __|__| _____/  |_  \______   \__| _____/  |_ 
     /  / \  \|  |  \  |/ __ \   __\  |       _/  |/  _ \   __/
    /   \_/.  \  |  /  \  ___/|  |    |    |   \  (  <_> )  |  
    \_____\ \_/____/|__|\___  >__|    |____|_  /__|\____/|__|  
           \__>             \/               \/                
    

1. IAM Roles

2. IAM Users

Kindly select one of the above scan types:1
Provide an an Account ID to scan against: {Your_Current_Account_ID}

Provide the path to wordlist file : test.txt


Estimated Scan Duration: 0 minutes to 0 minutes

Scanning Started with Quiet Riot

Identified Valid Principals:

Scan Summary: 
# of Identified Valid Principals: 0
# of Scanned Principals: 12001
% Valid Principals: 0.0%
# of Minutes Elapsed: 2.6666666666666665
# of Threads Utilized: 101

Creating S3 bucket for uploading results: quiet-riot-499164911814

Download your scan results:

https://quiet-riot-499164911814.s3.amazonaws.com/valid_scan_results-20230218-163609.txt?AWSAccessKeyId=AKIAVMIEFIECE74C4IDX&Signature=3E4ighgRbtEN1D4EI%2BT2EyCwFKg%3D&Expires=1678142367

        

As you can see, we weren't successful in identifying any roles with the scan (# of Identified Valid Principals: 0). Maybe Best Cloud Company implements Users instead. Try it for yourself. After running the Quiet Riot scan a second time with the scan type 2 selected, did it identify any Users?

Answer the questions below
What is John's username? 

What is Adam's last name?

We mentioned earlier in this room that resource-based policies could only return users, Roles, and Account . Well, that isn't completely true. There is one exception. When using legacy ACLs (Access Control Lists) (now deprecated by default), you can use the policy to place email addresses that correspond to potential root user email addresses. These root users are particularly interesting as an attacker, because they have full permissions against the account, unless otherwise restricted by Service Control Policy (SCP). As an attacker, if you take over a root user account, you have the proverbial keys to the kingdom. 

Quiet Riot supports scanning for root user email addresses, though this technique is inherently slower because it is only supported by the service and is prone to rate limiting. Let's try Adam and John's usernames as potential root users - we found them as regular users in the last task after all. We'll create a new file called rootuser.txt and add each potential email username to a new line. Then run Quiet Riot:

Quiet Riot Root User Scan
           root@ip-10-10-89-159:~# quiet_riot --s 4

        

Quiet Riot has a feature where it will help you generate the e-mail addresses based on a provided domain. While our scenario of checking two addresses doesn't require such a capability, it is useful if you have a large list of valid usernames. In fact, Quiet Riot also supports options for generating a list of almost 2 million potential usernames with common patterns (using common US names). But this time, we'll submit our custom wordlist:

Quiet Riot Root User Scan Part II
           root@ip-10-10-89-159:~# quiet_riot --s 4                                    
Input arguments : Namespace(scan=4, threads=100, wordlist='', profile='default')

    ________        .__        __    __________.__        __   
    \_____  \  __ __|__| _____/  |_  \______   \__| _____/  |_ 
     /  / \  \|  |  \  |/ __ \   __\  |       _/  |/  _ \   __/
    /   \_/.  \  |  /  \  ___/|  |    |    |   \  (  <_> )  |  
    \_____\ \_/____/|__|\___  >__|    |____|_  /__|\____/|__|  
           \__>             \/               \/                
    
E-mail Format (First and Last Names):
a. [first]@[domain]
b. [first][last]@[domain]
c. [first].[last]@[domain]
d. [last]@[domain]
e. [first]_[last]@[domain]
f. [first_initial][last]@[domain]
g. custom username list
h. input single e-mail address

Enter an alphabet between a-h : g

Location to emails list file: rootuser.txt

Domain Name:  bestcloudcompany.org

Total Number of e-mail addresses generated: 2

        

Well, it looks like neither Adam or John are Administrators. Unfortunately, due to the sensitivity of root user email addresses, we aren't going to be providing a valid address for this room. However, Quiet Riot supports validating e-mail users in Office 365 and G-Suite, the two most common enterprise email providers. That means you can create potential user lists, validate the emails against Microsoft or Google tenants, and then run large lists of valid emails against for root user email validation. You might be surprised by what you can find.

Answer the questions below
What type of S3 policy allows you to enumerate root user email addresses?

The last concept we are going to cover for Enumeration is a little different than identifying potential principals to attack or take over. That is because it isn't just humans that utilize roles. No, services also take advantage of the role concept in order to perform automation on your organization's behalf. In fact, if you have a service configured to do anything automatically on your behalf in , odds are someone (or automation ran by someone) enabled an "-service-role" that is being used to perform the actions on the services' behalf. You see, even services need permissions to perform actions in your account. It isn't uncommon to see an assume role trust policy with a similar structure to the following:

Assume Role Policy
           root@ip-10-10-89-159:~#   "Principal": {
                            "Service": "lambda.amazonaws.com"

                        }


        

This demonstrates that a particular AWS service has the ability to assume the role defined. In this case, the AWS service can assume the role with whatever permissions are applied.

It turns out this can be really useful when trying to do reconnaissance against an organization. You see, AWS uses pre-defined "aws-service-role" names that can be used to identify common services and, notably, security services such as GuardDuty. If you know a particular account you want to check enabled services against, you can run the following Quiet Riot command:

Quiet Right Scan Service Roles
           root@ip-10-10-89-159:~# quiet_riot --s 3                                          
Input arguments : Namespace(scan=3, threads=100, wordlist='', profile='default')

    ________        .__        __    __________.__        __   
    \_____  \  __ __|__| _____/  |_  \______   \__| _____/  |_ 
     /  / \  \|  |  \  |/ __ \   __\  |       _/  |/  _ \   __/
    /   \_/.  \  |  /  \  ___/|  |    |    |   \  (  <_> )  |  
    \_____\ \_/____/|__|\___  >__|    |____|_  /__|\____/|__|  
           \__>             \/               \/                
    
Provide an Account ID to scan against: 499164911814                                                        



Estimated Scan Duration: 0 minutes to 0 minutes

Scanning Started with Quiet Riot

Identified Valid Principals:
{Scan_Results_Redacted}

Scan Summary: 
# of Identified Valid Principals: {Scan_Results_Redacted}
# of Scanned Principals: 208
% Valid Principals: 2.403846153846154%
# of Minutes Elapsed: 0.03333333333333333
# of Threads Utilized: 104

S3 bucket is already there with this name: quiet-riot-499164911814

Download your scan results:

https://quiet-riot-499164911814.s3.amazonaws.com/valid_scan_results-20230227-203110.txt?AWSAccessKeyId=AKIAXIOEMDDDFS6B6643&Signature=CyTCdQRTUwaXECeECFVzjNPlMmc%3D&Expires=1678156332

        

What services do you see enabled in the account? How might it change your actions regarding an access key you might find? With , in particular, you know that there are specific security alerts that may be triggered by actions in the account. One special note is that these accounts may continue to be registered in an account, even if an organization discontinues its use. Therefore, it's important to understand that a role's existence isn't 100% accurate regarding the current service use.

Answer the questions below
How many roles does Quiet Riot identify in your account when you run the Service Footprinting option?

What services appear enabled based on the results?