aws-cognito-role-mapping-claim-override
An Identity Pool role mapping rule selects a privileged IAM role based on a token claim value the pool user can write (e.g. a custom User Pool attribute updatable via UpdateUserAttributes), enabling self-escalation to the mapped role.
match
A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.
where
node_type(?federated) in [
FederatedIdentity, ExternalIdentity]
node_type(?privileged_role) == Role
?pool.RoleMappings[*].RulesConfiguration is not null (Type==Rules)
the claim driving the matching rule is a User Pool attribute writable by the user (not admin-only)
the matching claim value maps to ?privileged_role (not the default authenticated role)
emit
| source type | FederatedIdentity |
|---|---|
| target type | Role |
| source | ?federated |
| target | ?privileged_role |
| permissions | cognito-idp:UpdateUserAttributes cognito-identity:GetId cognito-identity:GetCredentialsForIdentity |
| conditions | trust_condition |
| state logic | ACTIVE when the claim is writable via cognito-idp:UpdateUserAttributes (or similarly user-writable flow) with no admin involvement — the pool user sets the claim to the escalating value, gets a new token, calls GetCredentialsForIdentity, and receives the privileged role's credentials. CONDITIONAL(trust_condition) when the claim is admin-only (only settable via AdminUpdateUserAttributes — the attacker needs admin access to the User Pool). POTENTIAL when the claim source cannot be determined from collected data. |
Narrative
Identity Pool {pool.name} uses claim-based role mapping; the claim {claim.name} drives selection of {privileged_role.name} and is writable by the pool user via cognito-idp:UpdateUserAttributes. An attacker who sets {claim.name}={escalating_value} in their profile receives a token with that claim and can then call GetCredentialsForIdentity to receive credentials for {privileged_role.name}.
Raw rule rules/derived/aws/cognito.yaml
id: aws-cognito-role-mapping-claim-override
emits: CanFederateAs
description: An Identity Pool role mapping rule selects a privileged IAM role based on a token claim value
the pool user can write (e.g. a custom User Pool attribute updatable via UpdateUserAttributes), enabling
self-escalation to the mapped role.
applies_to:
- aws
match:
- - federated: null
- ExternalIdentityMapsTo
- privileged_role: null
where:
- node_type(?federated) in [FederatedIdentity, ExternalIdentity]
- node_type(?privileged_role) == Role
- ?pool.RoleMappings[*].RulesConfiguration is not null (Type==Rules)
- the claim driving the matching rule is a User Pool attribute writable by the user (not admin-only)
- the matching claim value maps to ?privileged_role (not the default authenticated role)
emit:
source_type: FederatedIdentity
target_type: Role
source: ?federated
target: ?privileged_role
permissions:
- cognito-idp:UpdateUserAttributes
- cognito-identity:GetId
- cognito-identity:GetCredentialsForIdentity
conditions:
- trust_condition
state_logic: "ACTIVE when the claim is writable via cognito-idp:UpdateUserAttributes (or similarly user-writable\
\ flow) with no admin involvement \u2014 the pool user sets the claim to the escalating value, gets\
\ a new token, calls GetCredentialsForIdentity, and receives the privileged role's credentials. CONDITIONAL(trust_condition)\
\ when the claim is admin-only (only settable via AdminUpdateUserAttributes \u2014 the attacker needs\
\ admin access to the User Pool). POTENTIAL when the claim source cannot be determined from collected\
\ data."
confidence: 0.8
derived_from:
- ?federated ExternalIdentityMapsTo ?privileged_role
- cognito-identity:GetIdentityPoolRoles.RoleMappings[*].RulesConfiguration (claim -> role mapping)
- cognito-idp:DescribeUserPool / DescribeUserPoolClient (schema writeability of the claim attribute)
false_positive_note: 'This rule fires only when the claim is USER-WRITABLE (no admin) and maps to a
DIFFERENT (more privileged) role than the default authenticated role. Many User Pool custom attributes
are read-only from the user''s perspective (admin-set-only via AdminUpdateUserAttributes or AdminSetUserPassword);
if the claim is admin-only, downgrade to CONDITIONAL and require the AdminUpdateUserAttributes path
instead. Honor the ''Match Type'' of the rule: an ''Equals'' match on a specific admin-set value is
not exploitable by the user; a ''Contains''/''NotEqual'' on a writable attribute is. Do not emit for
the default authenticated role (no claim mismatch escalation). If Rules-based role assignment is disabled
or the pool uses Token (not Rules) resolution, do not emit this rule.'
narrative: Identity Pool {pool.name} uses claim-based role mapping; the claim {claim.name} drives selection
of {privileged_role.name} and is writable by the pool user via cognito-idp:UpdateUserAttributes. An
attacker who sets {claim.name}={escalating_value} in their profile receives a token with that claim
and can then call GetCredentialsForIdentity to receive credentials for {privileged_role.name}.