AWS Cognito Security Misconfigurations

Published on January 15, 2024

If you are the pentester dealing with the modern web applications you might have faced the use of cognito in your assessments or you might have watched the awesome video of the Yassine Aboukir. A big shoutout to yassine for the awesome talk.

This blog post is all about the text version of the video by yassine that I have been keeping in my unstructured notes from quite some time. This can be useful during the pentesting while hunting for the cognito misconfigurations.

Introduction to AWS Cognito

  • With Amazon cognito, you can add user-signup and sign-in features and control access to your web and mobile applications.
  • Amazon Cognito provides an identity store that scales to millions of users, supports social and enterprise identity federation (OIDC or SAML 2.0) and offers advanced security features to protect your consumers and business.
  • Amazon Cognito makes it easier for you to manage user identifies, authentication and permissions. It consists of two main components:
  • User pools: allows sign-in and sign-up functionality.
  • Identity Pools: allow authenticated and unauthenticated users to access AWS resources using temporary AWS credentials.

Cognito URLs Enumeration

  • API call user pool endpoint: cognito-idp.us-west2.amazonaws.com
  • API calls to identity pool endpoint: cognito-identity.us-west-2.amazonaws.com

Below are the list of AWS cognito misconfiguration that can be seen in the targets during the pentesting/bugbounty:

Unauthorized Access to AWS services due to Liberal AWS credentials

  • Guest Account is Enabled (Anyone can request credentials).
Guest Account Enabled

Try to fetch temporary AWS credentials as unauthenticated guest:

To generate the AWS credentials, we need to identify Pool ID which is usually hardcoded in the source code, in a bundled JS file or HTTP response. Other Useful information that you can find:

  • Client ID.
  • User Pool ID.
  • Region.
Pool Information

After getting the required information, next step is to use the Pool Identity ID to generate an Identity ID.

Use AWS Client as shown below:

aws cognito-identity get-id --identity-pool-id <identity-pool-id> --region <region>

Successful output:

Identity ID Generation

Next step is to use the previous Identity ID to generate AWS credentials. Use AWS cli as follows:

aws cognito-identity get-credentials-for-identity --identity-id <identity-id> --region <region>

Successful Output:

AWS Credentials

Now, we can enumerate permissions associated with the obtained credentials using a tool such as:

  • Enumerate-iam.
  • Scout suite.

Evidence:

Permissions Enumeration

We can enumerate all sort of permissions that allow unauthenticated user to access AWS Services:

  • dynamodb.list_backups().
  • dynamodb.list_tables().
  • lambda.list_functions().
  • s3.list_buckets().
  • etc.

If the unauthenticated role is explicitly disabled, the following error is shown:

Disabled Unauthenticated Role

Also, try to fetch temporary AWS credentials as authenticated user as shown below:

Authenticated User Credentials

Authentication Bypass Due to Enabled Signup API action

  • Applications not offering user signup and only supporting administrative provision of accounts could be vulnerable as a result of not disabling signup API action.
  • This includes admin login portals which implements AWS cognito allowing authentication bypass as a result.
Signup API Enabled

For the exploitation we need client ID which can be retrieved via JS files or HTTP request. After obtaining the client ID we can register an account with the following command via AWS cli:

aws cognito-idp sign-up --client-id <client-id> --username <email_address> --password <password> --region <region>

Both successful and error in below evidence:

Signup Results

In case of a successful self-registration, a 6 digits confirmation code will be delivered to the attacker's email address as shown below:

Confirmation Code

Now we will need to confirm the account next using the following code:

aws cognito-idp confirm-sign-up --client-id <client-id> --username <email-address> --confirmation-code <confirmation-code> --region <region>

Privilege Escalation Through writable User attributes

Attributes are pieces of information that help you identify individual users. such as name, email address, and phone number. A new user pool has a set of default standard attributes.

User Attributes

We can also add custom attributes to your user pool definition in the AWS Management Console as shown below:

Custom Attributes

Unless set as readable only, the new custom attribute permission is writable by default which allows the user to update its values.

Writable Attributes

In order to test against this misconfiguration, we need to be authenticated then we'll fetch the available user attributes using the generated access token as shown as example below: (Check Authorization header).

Access Token Usage

After obtaining the access token, we can use the command given below to fetch the user attributes:

aws cognito-idp get-user --region <region> --access-token <access-token>

Fetched user attributes will look like this:

Fetched User Attributes

From the list we need to look for the custom attributes such as:

  • custom:isAdmin
  • custom:userRole
  • custom:isActive
  • custom:isApproved
  • custom:accessLevel

Now we will try to update the user attributes to check if they are writable using aws cli:

aws cognito-idp update-user-attributes --access-token <access-token> --region <region> --user-attributes Name="<attribute-name>", Value="<new-value>"

Updating email attribute before verification

There are scenarios where the user isn't allowed to update their email address due to both client and server-side security controls. However, by leveraging cognito API, it might also be possible to bypass this restriction.

This can be achieved by using the following command:

aws cognito-idp update-user-attributes --access-token <access-token> --region <region> --user-attributes Name="email", Value="<new-email-address>"

This is especially bad when verification isn't required. If the email is relied upon for authorization and access control, this will result in horizontal and vertical privilege escalation.

Email Update

Even with email verification enabled, most applications will update the email attribute value to the new unverified email address. This is bad because the user will still be able to login and obtain an authenticated access token using the unverified email address.

Many applications do not necessarily check if email_verified is set to True or False. Therefore, this would bypass any security controls that relies on email domain for authorization, hence privilege escalation.

Mitigation:

  • AWS has introduced a new security configuration to mitigate this issue, so if you have Keep original attribute value active when an update is pending explicitly enabled the email attribute will not be updated to the new email address until is verified.
  • This new security configuration was introduced on June 2022 which means no chance. (but still can be found maybe)
Mitigation Configuration

User Account Enumeration via Signup API

User Enumeration 1User Enumeration 2

AWS has fixed the user account enumeration in login, but it is still possible using cognito Signup API using the following command:

aws cognito-idp sign-up --client-id <Client_ID> --username admin --password adminpass

Successful output will look something like this:

Enumeration Result

Recommendation

  • Remove sensitive details from server responses, including cognito identity pool id.
  • Disable signup on AWS cognito if not required.
  • Disable unauthenticated role if not required.
  • Review IAM policy attached to the authenticated and unauthenticated role to ensure least privilege access.
  • Evaluate all user attributes and disable writing permission if not necessary.
  • Remember that the email attribute value may hold an unverified email address.

Hunting for cognito in pentest and bugbounty often leads to high or critical severity issues. Make sure to understand the application nature and try to bypass the business logic of the target application abusing the cognito misconfiguration can be a great win. If you are reading up to here, I would like to thank you for your patience and hope this will help you.