Recon

CSP Enumeration

Domain-based

Domain reconnaissance is a passive technique used early in attacks to gather public data without alerting the target. Starting with a domain name (e.g., example.com), the goal is to identify DNS infrastructure, hosting details, and subdomains. A recursive approach is essential—each discovery can lead to more.

Every domain has authoritative name servers that store its DNS records. Identifying them reveals who manages the domain’s DNS, often pointing to the cloud provider or registrar. For example, name server queries might show the CSP, which can be verified via WHOIS.

# Query the domain's authoritative name servers
$ host -t ns example.com
example.com name server ns-1456.awsdns-00.co.uk.
example.com name server ns-533.awsdns-00.net.

# Verify the organization managing the name server
$ whois ns-1456.awsdns-00.co.uk | grep "Registrant Organization"
Registrant Organization: Amazon Technologies, Inc.

To identify where a site is hosted, we can resolve the domain and then perform a reverse IP lookup. In this case, the result shows the service is hosted on an AWS EC2 instance.

# Resolve the domain
$ host www.example.com
www.example.com has address 54.73.167.99

# Reverse-lookup the IP address
$ host 54.73.167.99
80.127.74.52.in-addr.arpa domain name pointer ec2-54.73.167.99.compute-1.amazonaws.com

# Confirm ownership
$ whois 54.73.167.99 | grep "OrgName"
OrgName: Amazon Technologies Inc.

To discover more subdomains, automated tools like dnsenum can be used.

S3 Buckets

Public cloud infrastructure often uses predictable hostnames that reveal the service in use. For example, a reverse DNS lookup might return ec2-18-102-34-210.compute-1.amazonaws.com, indicating an AWS EC2 instance. Browser developer tools can aid in recon. In the Network tab, each row lists the file name and the domain it originated, such as:

The above URL:

  • suggests the use of Amazon S3 bucket

  • the bucket name: example-assets-public-mnzpytrl

  • the object key: sites/www/images/randomphoto.jpg.

Visiting the bucket URL without the object path may reveal misconfigured permissions, such as directory listing, indicating that the bucket is publicly readable.

S3 permissions allow public access at the object level even if the bucket is private.

Bucket naming conventions often follow patterns such as [org]-[type]-[env]-[random]. Predictable naming lets attackers guess related buckets (e.g., example-assets-private-mnzpytrl). Errors like AccessDenied or NoSuchBucket help confirm existence and access levels. Because bucket names are globally unique, teams often add a random or hashed suffix to avoid collisions. But if this suffix is reused, attackers can guess other related buckets more easily. To automate this process, tools like cloud_enum can search for cloud assets across AWS, Azure, and GCP:

Or generate bucket naming variations with:

API Enumeration

Cloud Application Programming Interfaces (APIs) are essential for automation and integration but also create a distinct attack surface. Even with authentication, misconfigured or overly permissive APIs can expose valuable information to attackers. CSPs typically offer two main access methods:

  • Web Portals: Browser-based interfaces for managing cloud services. Users authenticate with credentials like usernames, passwords, and often MFA. This method is user-friendly and commonly used by individuals and administrators.

  • APIs: Designed for programmatic access, APIs enable developers and automation tools to manage services without using a browser. Though protected by API keys, tokens, or cloud credentials, they are publicly exposed.

Despite requiring authentication, APIs can aid attackers during reconnaissance. An attacker might register a legitimate account and use valid credentials to explore API responses, discovering details about misconfigurations, exposed resources, or other tenants. This doesn’t involve bypassing controls but rather abusing intended, documented functionality — known as API abuse.

IAM is the gatekeeper of AWS accounts. It controls users, roles, permissions, and access policies within an AWS account. Each user created under an IMA is called an IAM user. IAM defines what a user can do—such as accessing storage, launching servers, or using APIs.

Using named profiles in the AWS CLI is a best practice for managing credentials across different IAM users. It allows easy switching between identities for testing access and behavior. Once configured, every command we run must include the profile to use, e.g. --profile attacker, so AWS CLI knows which credentials to use. After configuration, we can verify the setup by asking AWS to tell us who we are using the STS.

The Amazon Resource Name (ARN) uniquely identifies the profile in AWS.

AccountID Discovery

Cloud platforms like AWS let users share resources internally or publicly. While this enables collaboration, misconfigurations can expose sensitive data. Some resources are meant to be shared, but others may become publicly accessible by mistake. Under the AWS Shared Responsibility Model, securing shared data is the customer’s job—a common source of risk. Unlike web apps with visible URLs, these resources typically lack public endpoints. They’re discoverable only by querying the AWS API, often using the AWS CLI.

Via Public AMIs

An AMI is a blueprint for launching EC2 instances. It includes an OS and may also contain apps, configs, or user data. AMIs can be shared publicly—intentionally (e.g., open-source) or unintentionally due to misconfigurations.

We can enumerate the target's AccountID via filtering the AMI's metadata.

Using the same principles, we can search for publicly available EBS and RDS snapshots.

Via IAM Policies

An attacker using their own AWS account can try to access misconfigured S3 buckets owned by another organization. If access is granted based on loose or overly broad policies, it may reveal sensitive data or even the account ID of the target. The attacker’s approach involves:

  1. Creating a new IAM user to simulate a low-privilege attacker

  2. Crafting a permissive IAM policy which includes a condition that matches certain account IDs

  3. Using that policy to test access against external S3 buckets

  4. Iterating on the policy to discover the correct account ID range

The enum user simulates a clean slate attacker with no permissions.

The attacker writes a policy allowing access only if the resource's AWS account ID starts with a specific prefix, in this case 0.

The attacker now changes the wildcard condition to match different account ID prefixes until access is granted.

Update the policy to try a different prefix:

This time the command succeeds (e.g., returns a directory listing like PRE sites/), thus, the attacker has confirmed that the resource is owned by an account beginning with 7. By incrementally modifying the account ID prefix, the attacker can continue the process:

Tools like s3-account-search automate this by using roles instead of users, but the principle is the same: use IAM policy conditions to infer the account ID that owns the target bucket.

Cross-Account Access

Previously, we extracted an AWS account ID. Now, we’ll explore how to enumerate internal IAM identities (users or roles) in a known account by analyzing policy-based API responses. In AWS, cross-account access allows resources to be shared with just some specific external accounts, rather than the public. IAM policies use a Principal field to specify the target identity (e.g., user or role). If that identity doesn’t exist, AWS returns an error—this can be used to verify if an identity is valid.

Define a bucket policy targeting a specific user in the victim account.

If no errors occur, the policy is applied successfully, meaning the enum user exists in the target account. If we apply the policy for a non-existent user, we receive an error message.

In a similar manner, IAM roles can also be discovered by setting up trust policies and observing the responses. We can use pacu to achieve that.

This approach allows attackers to enumerate and even assume roles within a target AWS account—often serving as a pivot for deeper access.

Initial IAM Recon

Identity Details

After compromising AWS credentials, attackers begin by exploring what the account can access—all while staying within valid permissions to avoid detection. Though AWS logs actions via CloudTrail, alerts only trigger if properly configured. As a result, legitimate-but-curious activity often goes unnoticed.

Assuming we’ve obtained a set of AWS access keys (target), our first goal is to determine whether they are still valid, what account they belong to, and ideally do so without triggering logs in the target's CloudTrail. The most common way to verify credentials is via the get-caller-identity subcommand. However, this action is always allowed (even if explicitly denied) and always logged in the target’s CloudTrail.

For stealthier reconnaissance, we can use the get-access-key-info subcommand. This only reveals the account ID tied to the access key, and it logs only to the caller's account, not the account associated with the key. Therefore, we run it from a separate AWS account (e.g., an attacker-controlled one). Below is an example using an “attacker” profile configured with separate credentials:

Another stealthy approach for revealing identity details is via failed API calls; these aren't logged by default in Cloudtrail.

CloudTrail logging behavior varies by region. For example, the below command may show up in us-east-2 logs—but remain invisible in the default region (us-east-1) if not explicitly configured. Attackers exploit this gap to probe quieter regions.

IAM Permissions

IAM policies determine what a user can do. Permissions may be:

  • Inline (directly attached to the user)

  • Managed (reusable, attached to multiple identities)

  • Inherited via group membership

AWS Managed Policies are pre-defined and often too permissive, allowing broad access to many resources.

To see the policy conten, we must first find its exact version.

If the compromised account lack the privileges to query for IAM-related infomation, permissions can be inferred via brute-force API probing with tools such as pacuiam__bruteforce_permissions, awsenum, and enumerate-iam .

The above tools can generate a lot of noise; a manual, service-aware approach is stealthier in sensitive environments.

IAM Resources Recon

With access to the compromised clouddesk-plove IAM user, we begin enumeration. The user belongs to the support group and inherits the AWS-managed SupportUser policy, designed for support roles. According to AWS, this policy grants broad read-only access—enough to reveal sensitive information about the environment’s security posture.

Resource Type
Name
ARN

IAM::User

clouddesk-plove

arn:aws:iam::123456789012:user/support/clouddesk-plove

IAM:Group

support

arn:aws:iam::123456789012:group/support/support

IAM::Policy

SupportUser

arn:aws:iam::aws:policy/job-function/SupportUser

We can start by retrieving and inspecting the policy to confirm IAM read permissions.

This allows nearly all get and list operations on IAM. We identify these using:

We can learn about any of the commands by running aws iam <command> help.

We can then run get-account-summary:

The output includes useful information:

  • 18 users, 20 roles, 8 groups

  • No MFA enabled (MFADevices: 0, MFADevicesInUse: 0)

  • No MFA enable for the root account (AccountMFAEnabled: 0)

This is a serious weakness—any compromised credentials are immediately usable without second-factor authentication. We continue by enumerating users, groups, and roles:

These commands reveal identity paths and naming conventions (e.g., admin-alice, admin) that may indicate elevated privileges and warrant deeper analysis.

To investigate permissions at a more granular level, we can list the IAM policies created within this account, limiting the scope to locally-managed, i.e., customer-managed and not AWS-managed policies, and currently-attached policies, i.e., policies attached to an IAM identity.

One notable policy: manage-credentials—its name implies potential for key rotation or MFA manipulation, both possible paths to escalation. We can fetch all attached identity definitions using:

To run get-account-authorization-details, the account needs GetAccountAuthorizationDetails, which is rarely granted directly but often included via broader wildcards like iam:Get*.

Explicing Deny Bypass

During this phase, we enumerated the deny_challenges_access policy which is attached to our compromised user.

Explicit denies always override allows, signaling the admin intentionally blocked access to this policy. However, IAM restrictions must account for both what’s explicitly denied and what’s still implicitly allowed. Thus, when we run a broader command that retrieves all locally managed policies in the account, hoping that the forbidden policy might be included in the output.

This applies a global Deny to all tagged resources (challenge=true). Despite the explicit block, we accessed it through broader permissions—a classic example of indirect access.

Processing API Responses

The AWS CLI returns JSON by default, which can be filtered using JMESPath—a query language tailored for JSON. This helps extract and transform key data during enumeration, especially from verbose commands like iam get-account-authorization-details.

The output includes a UserDetailList array of user objects with fields like UserName, UserId, Arn, and GroupList. To isolate usernames:

JMESPath queries (--query) run client-side, while filters (--filter) run server-side. To retrieve multiple fields we can use the [key1, key2, key3] or the labeled keys format {Identifier1: key1, Identifier2: key2, IdentifierN: keyN} format:

To filter users with names containing admin:

For nested filtering—e.g., users and groups under /admin/ paths:

Or combine conditions:

Automated Enumeration

Pacu is an AWS post-exploitation tool for AWS that automates the enumeration using compromised credentials.

This data is stored in Pacu’s internal SQLite database.

Extracting Insights

Once AWS IAM enumeration is complete, the next step is analysis—turning raw data into actionable findings. This is key for identifying privilege escalation paths or misconfigurations. We must first determine what we're looking for: elevated privileges, policy gaps, or tagging misuse.

Output shows admin-alice is in admin and amethyst_admin groups, tagged with Project: amethyst. While the user has no direct policies, group memberships imply privilege inheritance.

Attribute-Based Access Control (ABAC) uses attributes (like tags) to control access, making tag analysis crucial.

The admin group is attached to the AWS-managed AdministratorAccess policy, and the amethyst_admin group uses the amethyst_admin custom policy.

The AdministratorAccess policy is an AWS-managed policy that grants full access to all AWS services; its document is available in the official AWS documentation.

The policy grants broad IAM permissions (e.g., iam:*) but scopes them to resources tagged with Project:amethyst or located under specific paths. While this appears restrictive, it can be dangerously permissive—especially when those tags overlap with high-privilege resources. The wildcard use (iam:*) itself raises concerns about over-permissiveness. Two privilege escalation paths emerge:

  1. Direct Access Abuse

    • Compromise admin-alice via phishing or exposed credentials

    • Exploit absence of MFA

  2. Group-Based Escalation

    • Users in the amethyst_admin group can use iam:CreateAccessKey on admin-alice

    • Add themselves to the admin group using iam:AddUserToGroup

The critical issue is that admin-alice is both tagged with Project:amethyst and a member of amethyst_admin. This allows other group members to perform privileged IAM actions on her—including creating access keys—enabling escalation from lower-privileged users to full admin access. This unintended overlap of tagging and group membership results in a serious security misconfiguration.

Tools like awspx and cloudmapper can map IAM relationships and effective access visually. In this case, it illustrates a clear privilege escalation path from admin-cbarton to admin-alice—a user with full administrative access.

Last updated

Was this helpful?