# Cognito User Pool and Identity Pool Enumeration

> Techniques for enumerating AWS Cognito User Pools and Identity Pools, uncovering misconfigured auth flows, exposed pool IDs, and unauthenticated access risks.

- **URL:** https://hackindex.io/platforms/aws/enumeration/cognito/cognito-user-pool-enumeration
- **Path:** AWS > Enumeration > Cognito
- **Up:** [Cognito](https://hackindex.io/platforms/aws/enumeration/cognito.md)
- **Published:** 2026-05-24
- **Updated:** 2026-09-24

Cognito manages user authentication (user pools) and AWS credential federation (identity pools). Misconfigurations in identity pools grant temporary AWS credentials: sometimes without any authentication at all.

There are two distinct attack surfaces. User pools are the account directory: they store credentials, enforce password policies, and issue JWTs on successful login. Identity pools accept those JWTs and exchange them for short-lived IAM credentials. A misconfigured user pool is a spray or enumeration target. A misconfigured identity pool hands out AWS credentials to anyone with no account required. Enumerate both independently.

## User Pools

The output table shows each pool ID, name, and creation date. Multiple pools often indicate separate environments sharing one account. Pool IDs follow the format `us-east-1_XXXXXXXXX`. Record every ID and pass each to `describe-user-pool` to extract the security configuration.

```bash
aws cognito-idp list-user-pools --max-results 60 --profile $PROFILE --region $REGION --query 'UserPools[*].{ID:Id,Name:Name,Created:CreationDate}' --output table
```

**Describe a pool**

```bash
aws cognito-idp describe-user-pool --user-pool-id $USER_POOL_ID --profile $PROFILE --region $REGION
```

Key fields:

- `MfaConfiguration`: `OFF`, `OPTIONAL`, or `ON`
- `Policies.PasswordPolicy`: minimum length and complexity requirements
- `UsernameAttributes`: whether users log in with email or phone number
- `AliasAttributes`: what aliases are allowed

`MfaConfiguration: OFF` means no second factor: password spraying has no MFA barrier. `OPTIONAL` means MFA can be registered but is not enforced for all users. Check `Policies.PasswordPolicy.MinimumLength`: a minimum of six or eight characters combined with no lockout policy is a reliable spray candidate. Also check `AccountRecoverySetting` to understand how account recovery works, which can be abused through email or SMS interception.

## App Clients

App clients define how applications authenticate against the user pool. Each client has its own OAuth flows, callback URLs, and optionally a client secret. Clients without secrets use the public client pattern. The `client_id` is often embedded directly in the frontend JavaScript bundle or compiled into the mobile binary. Finding it is usually trivial: inspect the application source or intercept authentication traffic.

```bash
aws cognito-idp list-user-pool-clients --user-pool-id $USER_POOL_ID --profile $PROFILE --region $REGION
aws cognito-idp describe-user-pool-client --user-pool-id $USER_POOL_ID --client-id $CLIENT_ID --profile $PROFILE --region $REGION
```

A client with `ALLOW_USER_PASSWORD_AUTH` enabled accepts direct username and password login. That flow is a spray target: no OAuth redirect required. Check `ExplicitAuthFlows` for `ALLOW_CUSTOM_AUTH` and `ALLOW_USER_SRP_AUTH` as well. SRP requires a valid password, but custom auth flows often implement weaker or bypassable challenges. App client secrets are returned in plaintext if you hold `cognito-idp:DescribeUserPoolClient`. A client secret means server-side validation only: it is not directly usable in browser or mobile authentication flows.

## List Users

This call requires `cognito-idp:ListUsers` on the pool. If you have it, the response includes every registered account: usernames, email addresses, phone numbers, and `UserStatus`. `CONFIRMED` accounts are active targets. `FORCE_CHANGE_PASSWORD` means an admin created the account and the user has not logged in yet. Collect confirmed usernames and email addresses as the spray list. Use `--filter` to narrow results by attribute on large pools.

```bash
aws cognito-idp list-users --user-pool-id $USER_POOL_ID --profile $PROFILE --region $REGION --query 'Users[*].{Username:Username,Status:UserStatus,Created:UserCreateDate,Enabled:Enabled}' --output table
```

## Identity Pools (Federated Identities)

Identity pools issue temporary IAM credentials by accepting logins from user pools, social providers, SAML, and OIDC. They also support unauthenticated identities: a separate IAM role assigned with no login at all. This is the highest-value Cognito misconfiguration. If `AllowUnauthenticatedIdentities` is enabled, you can request valid AWS credentials from any IP without an account. List all identity pools and describe each one.

```bash
aws cognito-identity list-identity-pools --max-results 60 --profile $PROFILE --region $REGION
aws cognito-identity describe-identity-pool --identity-pool-id $IDENTITY_POOL_ID --profile $PROFILE --region $REGION
```

Key field: `AllowUnauthenticatedIdentities`. If `true`, anyone can get AWS credentials. No user account is needed. The resulting tokens are short-lived STS sessions, valid for one hour by default, but fully functional. Note the identity pool ID and account ID. You need both for the next call.

**Get unauthenticated AWS credentials**

```bash
aws cognito-identity get-id --identity-pool-id $IDENTITY_POOL_ID --account-id $ACCOUNT_ID --region $REGION
aws cognito-identity get-credentials-for-identity --identity-id $IDENTITY_ID --region $REGION
```

The returned credentials are scoped to the unauthenticated IAM role. Enumerate what that role can do: it is often overpermissioned. Common findings include `s3:GetObject` on customer data buckets and read access to DynamoDB tables. Occasionally the role can call `sts:AssumeRole` into a more privileged role. Export the credentials as environment variables and run `aws sts get-caller-identity` first to confirm the assumed role ARN. Then proceed with IAM enumeration to map the full permission set.

## Roles for Identity Pool

Every identity pool maps to at least one IAM role. Pools with rule-based mapping assign different roles based on token claims from the identity provider. Examine `RoleMappings` for claim-based rules. If role assignment depends on a token attribute you can control, that is a privilege escalation path to a higher-privilege role.

```bash
aws cognito-identity get-identity-pool-roles --identity-pool-id $IDENTITY_POOL_ID --profile $PROFILE --region $REGION
```

Returns both `authenticated` and `unauthenticated` role ARNs. Enumerate both roles' policies via [IAM Authenticated Enumeration](https://hackindex.io/platforms/aws/enumeration/iam/iam-authenticated-enumeration). If you cannot call `get-identity-pool-roles`, role ARNs appear in CloudFormation templates or the application source. Look for the `arn:aws:iam::` pattern in decompiled mobile apps or frontend JavaScript bundles.
