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.

derived aws emits CanFederateAs

match

A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.

{'federated': None} ExternalIdentityMapsTo {'privileged_role': None}

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 typeFederatedIdentity
target typeRole
source?federated
target?privileged_role
permissionscognito-idp:UpdateUserAttributes cognito-identity:GetId cognito-identity:GetCredentialsForIdentity
conditionstrust_condition
state logicACTIVE 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}.
move · open · esc close