AWS Cognito Unauthenticated Identity Pool Credentials Issued

Identifies AWS CloudTrail data events where an unauthenticated identity successfully retrieves temporary AWS credentials from a Cognito Identity Pool via GetCredentialsForIdentity. Cognito Identity Pools can be configured to allow unauthenticated (guest) access, intended for scenarios like anonymous app analytics, but a pool that grants those anonymous identities meaningful IAM permissions becomes a public, unauthenticated path to real AWS credentials. Adversaries who discover an identity pool ID (often embedded in mobile app binaries, web app JavaScript, or public source repositories) can call GetId followed by GetCredentialsForIdentity with no login token at all to obtain temporary credentials, then use them to access whatever the pool's unauthenticated role permits. This is a New Terms rule that limits alerting to identity pools that have not been observed issuing credentials to an unauthenticated caller before, since some applications intentionally and continuously use guest access as part of normal operation.

Elastic rule (View on GitHub)

  1[metadata]
  2creation_date = "2026/07/13"
  3integration = ["aws"]
  4maturity = "production"
  5updated_date = "2026/07/13"
  6
  7[rule]
  8author = ["Elastic"]
  9description = """
 10Identifies AWS CloudTrail data events where an unauthenticated identity successfully retrieves temporary AWS credentials
 11from a Cognito Identity Pool via GetCredentialsForIdentity. Cognito Identity Pools can be configured to allow
 12unauthenticated (guest) access, intended for scenarios like anonymous app analytics, but a pool that grants those
 13anonymous identities meaningful IAM permissions becomes a public, unauthenticated path to real AWS credentials.
 14Adversaries who discover an identity pool ID (often embedded in mobile app binaries, web app JavaScript, or public
 15source repositories) can call GetId followed by GetCredentialsForIdentity with no login token at all to obtain
 16temporary credentials, then use them to access whatever the pool's unauthenticated role permits. This is a New Terms
 17rule that limits alerting to identity pools that have not been observed issuing credentials to an unauthenticated caller
 18before, since some applications intentionally and continuously use guest access as part of normal operation.
 19"""
 20false_positives = [
 21    """
 22    Applications that intentionally allow unauthenticated Identity Pool access for legitimate purposes (for example,
 23    anonymous usage analytics or unauthenticated content delivery) will trigger this rule the first time that pattern is
 24    observed for a given identity pool. Confirm whether the pool's unauthenticated role grants only the minimal
 25    permissions the application actually needs, and treat repeated alerts for the same pool as expected once validated.
 26    """,
 27]
 28from = "now-6m"
 29index = ["logs-aws.cloudtrail-*"]
 30language = "kuery"
 31license = "Elastic License v2"
 32name = "AWS Cognito Unauthenticated Identity Pool Credentials Issued"
 33note = """## Triage and analysis
 34
 35### Investigating AWS Cognito Unauthenticated Identity Pool Credentials Issued
 36
 37Amazon Cognito Identity Pools can be configured with `AllowUnauthenticatedIdentities`, letting a caller obtain a
 38guest identity via `GetId` and then temporary AWS credentials via `GetCredentialsForIdentity`, with no login token or
 39authentication of any kind. This is by design for use cases like anonymous app analytics, but if the pool's
 40unauthenticated IAM role is overpermissioned, anyone who discovers the identity pool ID gets a free, unauthenticated
 41path to real AWS credentials.
 42
 43This rule fires the first time a given identity pool is observed issuing credentials to an unauthenticated caller
 44(`aws.cloudtrail.user_identity.type: "Unknown"`).
 45
 46#### Possible investigation steps
 47
 48- **Identify the pool**: review `aws.cloudtrail.resources.arn` to determine which identity pool issued the
 49  credentials, and `aws.cloudtrail.request_parameters.identityId` for the specific guest identity.
 50- **Confirm this is intentional guest access**: check whether the application this pool belongs to is designed for
 51  anonymous/unauthenticated use (for example, a public mobile app or website with anonymous analytics).
 52- **Review the unauthenticated role's permissions**: run
 53  `aws cognito-identity get-identity-pool-roles --identity-pool-id <pool id>` and inspect the attached policy for the
 54  unauthenticated role. Broad permissions (data store read/write, `iam:*`, cross-service access) on a role reachable
 55  without authentication is a critical misconfiguration regardless of whether this specific call was malicious.
 56- **Review source context**: check `source.ip`, `user_agent.original`, and `source.geo` for the calling identity. A
 57  source unrelated to the application's expected client base (for example, a generic AWS SDK/CLI user agent instead
 58  of a mobile/browser client) is a stronger indicator of discovery/abuse rather than normal app traffic.
 59- **Look for follow-on activity**: search for subsequent API calls made using credentials tied to the same
 60  `identityId` or the unauthenticated role's ARN, to determine what the caller actually did with the credentials.
 61- **Look for pool enumeration**: check for `ListIdentityPools` or repeated `GetId`/`GetCredentialsForIdentity` calls
 62  against multiple different identity pools from the same source in a short window, which suggests systematic
 63  discovery rather than a single legitimate app session.
 64
 65### False positive analysis
 66
 67- Many applications intentionally use unauthenticated Identity Pool access for anonymous analytics or public content
 68  delivery. This rule fires once per identity pool the first time this pattern is observed; if confirmed as
 69  intentional and properly scoped (minimal unauthenticated role permissions), no further action is needed for that
 70  pool.
 71
 72### Response and remediation
 73
 74- If the unauthenticated role is overpermissioned, scope it down immediately to the minimum required for legitimate
 75  anonymous use, or disable `AllowUnauthenticatedIdentities` entirely if guest access is not required.
 76- If credentials were abused, review all activity performed under the unauthenticated role's ARN during the
 77  credential's validity window and revoke/rotate as appropriate (temporary credentials cannot be revoked directly,
 78  but the role's trust policy or permissions can be tightened immediately).
 79- Treat any identity pool ID found in client-side code (mobile app binaries, web JavaScript) as public information,
 80  and ensure the unauthenticated role attached to it is scoped accordingly.
 81
 82"""
 83references = [
 84    "https://docs.aws.amazon.com/cognito/latest/developerguide/identity-pool-roles.html",
 85    "https://docs.aws.amazon.com/cognito/latest/developerguide/logging-using-cloudtrail.html",
 86    "https://hackingthe.cloud/aws/exploitation/cognito_identity_pool_excessive_privileges/",
 87    "https://github.com/RhinoSecurityLabs/pacu/tree/master/pacu/modules/cognito__attack",
 88]
 89risk_score = 47
 90rule_id = "c61fee20-4d00-4b39-a6e6-acddcc4433e2"
 91setup = "Cognito Identity Pool data events must be enabled in CloudTrail to capture GetCredentialsForIdentity, GetId, GetOpenIdToken, GetOpenIdTokenForDeveloperIdentity, and UnlinkIdentity. Add an advanced event selector for eventCategory Data and resources.type AWS::Cognito::IdentityPool to the trail."
 92severity = "medium"
 93tags = [
 94    "Domain: Cloud",
 95    "Data Source: AWS",
 96    "Data Source: Amazon Web Services",
 97    "Data Source: AWS Cognito",
 98    "Use Case: Asset Visibility",
 99    "Resources: Investigation Guide",
100    "Tactic: Credential Access",
101    "Tactic: Initial Access",
102]
103timestamp_override = "event.ingested"
104type = "new_terms"
105
106query = '''
107data_stream.dataset: "aws.cloudtrail"
108    and event.provider: "cognito-identity.amazonaws.com"
109    and event.action: "GetCredentialsForIdentity"
110    and event.outcome: "success"
111    and aws.cloudtrail.user_identity.type: "Unknown"
112'''
113
114
115[[rule.threat]]
116framework = "MITRE ATT&CK"
117[[rule.threat.technique]]
118id = "T1552"
119name = "Unsecured Credentials"
120reference = "https://attack.mitre.org/techniques/T1552/"
121
122
123[rule.threat.tactic]
124id = "TA0006"
125name = "Credential Access"
126reference = "https://attack.mitre.org/tactics/TA0006/"
127[[rule.threat]]
128framework = "MITRE ATT&CK"
129[[rule.threat.technique]]
130id = "T1078"
131name = "Valid Accounts"
132reference = "https://attack.mitre.org/techniques/T1078/"
133[[rule.threat.technique.subtechnique]]
134id = "T1078.004"
135name = "Cloud Accounts"
136reference = "https://attack.mitre.org/techniques/T1078/004/"
137
138
139
140[rule.threat.tactic]
141id = "TA0001"
142name = "Initial Access"
143reference = "https://attack.mitre.org/tactics/TA0001/"
144
145[rule.investigation_fields]
146field_names = [
147    "@timestamp",
148    "user_agent.original",
149    "source.ip",
150    "aws.cloudtrail.resources.arn",
151    "aws.cloudtrail.resources.type",
152    "aws.cloudtrail.user_identity.type",
153    "aws.cloudtrail.request_parameters",
154    "event.action",
155    "event.outcome",
156    "cloud.account.id",
157    "cloud.region",
158]
159
160[rule.new_terms]
161field = "new_terms_fields"
162value = ["aws.cloudtrail.resources.arn"]
163[[rule.new_terms.history_window_start]]
164field = "history_window_start"
165value = "now-7d"

Triage and analysis

Investigating AWS Cognito Unauthenticated Identity Pool Credentials Issued

Amazon Cognito Identity Pools can be configured with AllowUnauthenticatedIdentities, letting a caller obtain a guest identity via GetId and then temporary AWS credentials via GetCredentialsForIdentity, with no login token or authentication of any kind. This is by design for use cases like anonymous app analytics, but if the pool's unauthenticated IAM role is overpermissioned, anyone who discovers the identity pool ID gets a free, unauthenticated path to real AWS credentials.

This rule fires the first time a given identity pool is observed issuing credentials to an unauthenticated caller (aws.cloudtrail.user_identity.type: "Unknown").

Possible investigation steps

  • Identify the pool: review aws.cloudtrail.resources.arn to determine which identity pool issued the credentials, and aws.cloudtrail.request_parameters.identityId for the specific guest identity.
  • Confirm this is intentional guest access: check whether the application this pool belongs to is designed for anonymous/unauthenticated use (for example, a public mobile app or website with anonymous analytics).
  • Review the unauthenticated role's permissions: run aws cognito-identity get-identity-pool-roles --identity-pool-id <pool id> and inspect the attached policy for the unauthenticated role. Broad permissions (data store read/write, iam:*, cross-service access) on a role reachable without authentication is a critical misconfiguration regardless of whether this specific call was malicious.
  • Review source context: check source.ip, user_agent.original, and source.geo for the calling identity. A source unrelated to the application's expected client base (for example, a generic AWS SDK/CLI user agent instead of a mobile/browser client) is a stronger indicator of discovery/abuse rather than normal app traffic.
  • Look for follow-on activity: search for subsequent API calls made using credentials tied to the same identityId or the unauthenticated role's ARN, to determine what the caller actually did with the credentials.
  • Look for pool enumeration: check for ListIdentityPools or repeated GetId/GetCredentialsForIdentity calls against multiple different identity pools from the same source in a short window, which suggests systematic discovery rather than a single legitimate app session.

False positive analysis

  • Many applications intentionally use unauthenticated Identity Pool access for anonymous analytics or public content delivery. This rule fires once per identity pool the first time this pattern is observed; if confirmed as intentional and properly scoped (minimal unauthenticated role permissions), no further action is needed for that pool.

Response and remediation

  • If the unauthenticated role is overpermissioned, scope it down immediately to the minimum required for legitimate anonymous use, or disable AllowUnauthenticatedIdentities entirely if guest access is not required.
  • If credentials were abused, review all activity performed under the unauthenticated role's ARN during the credential's validity window and revoke/rotate as appropriate (temporary credentials cannot be revoked directly, but the role's trust policy or permissions can be tightened immediately).
  • Treat any identity pool ID found in client-side code (mobile app binaries, web JavaScript) as public information, and ensure the unauthenticated role attached to it is scoped accordingly.

References

Related rules

to-top