Detection rules › Elastic
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.
Known false positives
- Applications that intentionally allow unauthenticated Identity Pool access for legitimate purposes (for example, anonymous usage analytics or unauthenticated content delivery) will trigger this rule the first time that pattern is observed for a given identity pool. Confirm whether the pool's unauthenticated role grants only the minimal permissions the application actually needs, and treat repeated alerts for the same pool as expected once validated.
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Initial Access | |
| Credential Access |
Telemetry coverage
Rule body
[metadata]
creation_date = "2026/07/13"
integration = ["aws"]
maturity = "production"
updated_date = "2026/07/13"
[rule]
author = ["Elastic"]
description = """
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.
"""
false_positives = [
"""
Applications that intentionally allow unauthenticated Identity Pool access for legitimate purposes (for example,
anonymous usage analytics or unauthenticated content delivery) will trigger this rule the first time that pattern is
observed for a given identity pool. Confirm whether the pool's unauthenticated role grants only the minimal
permissions the application actually needs, and treat repeated alerts for the same pool as expected once validated.
""",
]
from = "now-6m"
index = ["logs-aws.cloudtrail-*"]
language = "kuery"
license = "Elastic License v2"
name = "AWS Cognito Unauthenticated Identity Pool Credentials Issued"
note = """## 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 = [
"https://docs.aws.amazon.com/cognito/latest/developerguide/identity-pool-roles.html",
"https://docs.aws.amazon.com/cognito/latest/developerguide/logging-using-cloudtrail.html",
"https://hackingthe.cloud/aws/exploitation/cognito_identity_pool_excessive_privileges/",
"https://github.com/RhinoSecurityLabs/pacu/tree/master/pacu/modules/cognito__attack",
]
risk_score = 47
rule_id = "c61fee20-4d00-4b39-a6e6-acddcc4433e2"
setup = "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."
severity = "medium"
tags = [
"Domain: Cloud",
"Data Source: AWS",
"Data Source: Amazon Web Services",
"Data Source: AWS Cognito",
"Use Case: Asset Visibility",
"Resources: Investigation Guide",
"Tactic: Credential Access",
"Tactic: Initial Access",
]
timestamp_override = "event.ingested"
type = "new_terms"
query = '''
data_stream.dataset: "aws.cloudtrail"
and event.provider: "cognito-identity.amazonaws.com"
and event.action: "GetCredentialsForIdentity"
and event.outcome: "success"
and aws.cloudtrail.user_identity.type: "Unknown"
'''
[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "T1552"
name = "Unsecured Credentials"
reference = "https://attack.mitre.org/techniques/T1552/"
[rule.threat.tactic]
id = "TA0006"
name = "Credential Access"
reference = "https://attack.mitre.org/tactics/TA0006/"
[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "T1078"
name = "Valid Accounts"
reference = "https://attack.mitre.org/techniques/T1078/"
[[rule.threat.technique.subtechnique]]
id = "T1078.004"
name = "Cloud Accounts"
reference = "https://attack.mitre.org/techniques/T1078/004/"
[rule.threat.tactic]
id = "TA0001"
name = "Initial Access"
reference = "https://attack.mitre.org/tactics/TA0001/"
[rule.investigation_fields]
field_names = [
"@timestamp",
"user_agent.original",
"source.ip",
"aws.cloudtrail.resources.arn",
"aws.cloudtrail.resources.type",
"aws.cloudtrail.user_identity.type",
"aws.cloudtrail.request_parameters",
"event.action",
"event.outcome",
"cloud.account.id",
"cloud.region",
]
[rule.new_terms]
field = "new_terms_fields"
value = ["aws.cloudtrail.resources.arn"]
[[rule.new_terms.history_window_start]]
field = "history_window_start"
value = "now-7d"
Stages and Predicates
Stage 1: new_terms
data_stream.dataset: "aws.cloudtrail"
and event.provider: "cognito-identity.amazonaws.com"
and event.action: "GetCredentialsForIdentity"
and event.outcome: "success"
and aws.cloudtrail.user_identity.type: "Unknown"
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
aws.cloudtrail.user_identity.type | eq |
| field:"aws::userIdentity.type" kind:eq value:"Unknown" |
data_stream.dataset | eq |
| field:"data_stream.dataset" kind:eq value:"aws.cloudtrail" |
event.action | eq |
| field:"EventType" kind:eq value:"GetCredentialsForIdentity" |
event.outcome | eq |
| field:"event.outcome" kind:eq value:"success" |
event.provider | eq |
| field:"Provider_Name" kind:eq value:"cognito-identity.amazonaws.com" |