azure-msgraph-user-password-reset

A service principal holding User.ReadWrite.All (or Directory.ReadWrite.All) can reset any non-protected Entra user's password via PATCH /users/{id} with a new passwordProfile, taking over that user's account and inheriting their RBAC and group memberships.

derived azure emits CanResetCredential

match

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

{'sp': None} HasRole {'approle': None}

where

node_type(?sp) in [MachineIdentity, ApplicationIdentity] ?approle is one of: User.ReadWrite.All (id: 741f803b-c850-494e-b5df-cde7c675a1ca) OR Directory.ReadWrite.All (id: 19dbc75e-c2e2-444c-a770-ec69d8559fc7) on microsoft.graph SP for all HumanIdentity nodes (?user) in the tenant where ?user is NOT a protected administrator in Entra (Global Administrator, Privileged Role Administrator, Password Administrator, User Administrator, Authentication Administrator, Helpdesk Administrator — cross-check against /roleManagement/directory/roleAssignments)

emit

source typeIdentity
target typeHumanIdentity
source?sp
target?user
permissionsUser.ReadWrite.All Directory.ReadWrite.All
conditionsiam_permission service_state
state logicACTIVE when the appRoleAssignment is granted, SP credential is valid, and the target user is confirmed NOT a protected administrator. BLOCKED when the target user holds Global Administrator, Privileged Role Administrator, or any other role that Entra restricts from credential reset by lower-tier actors (Entra enforces this at API call time — the PATCH returns 403). CONDITIONAL(service_state) if the SP credential is expired. If the target user's role membership cannot be confirmed (collection gap), emit as CONDITIONAL(role_compatibility) and flag for analyst review. Conditional Access policies requiring MFA to set passwordProfile do not block an SP calling as itself (app-only context); they apply to interactive sessions.

Narrative

{sp.name} holds User.ReadWrite.All and can reset the password of {user.name} via PATCH /users/{id} (passwordProfile), taking over their account and inheriting all RBAC role assignments and group memberships they hold - subject to Entra's restriction blocking resets of protected administrator accounts.

Raw rule rules/derived/azure/msgraph.yaml

id: azure-msgraph-user-password-reset
emits: CanResetCredential
description: A service principal holding User.ReadWrite.All (or Directory.ReadWrite.All) can reset any
  non-protected Entra user's password via PATCH /users/{id} with a new passwordProfile, taking over that
  user's account and inheriting their RBAC and group memberships.
match:
- - sp: null
  - HasRole
  - approle: null
where:
- node_type(?sp) in [MachineIdentity, ApplicationIdentity]
- '?approle is one of: User.ReadWrite.All (id: 741f803b-c850-494e-b5df-cde7c675a1ca) OR Directory.ReadWrite.All
  (id: 19dbc75e-c2e2-444c-a770-ec69d8559fc7) on microsoft.graph SP'
- "for all HumanIdentity nodes (?user) in the tenant where ?user is NOT a protected administrator in Entra\
  \ (Global Administrator, Privileged Role Administrator, Password Administrator, User Administrator,\
  \ Authentication Administrator, Helpdesk Administrator \u2014 cross-check against /roleManagement/directory/roleAssignments)"
emit:
  source_type: Identity
  target_type: HumanIdentity
  source: ?sp
  target: ?user
  permissions:
  - User.ReadWrite.All
  - Directory.ReadWrite.All
  conditions:
  - iam_permission
  - service_state
  state_logic: "ACTIVE when the appRoleAssignment is granted, SP credential is valid, and the target user\
    \ is confirmed NOT a protected administrator. BLOCKED when the target user holds Global Administrator,\
    \ Privileged Role Administrator, or any other role that Entra restricts from credential reset by lower-tier\
    \ actors (Entra enforces this at API call time \u2014 the PATCH returns 403). CONDITIONAL(service_state)\
    \ if the SP credential is expired. If the target user's role membership cannot be confirmed (collection\
    \ gap), emit as CONDITIONAL(role_compatibility) and flag for analyst review. Conditional Access policies\
    \ requiring MFA to set passwordProfile do not block an SP calling as itself (app-only context); they\
    \ apply to interactive sessions."
  confidence: '0.9'
  derived_from:
  - <HasRole edge_id (appRoleAssignment User.ReadWrite.All or Directory.ReadWrite.All on ?sp)>
  - "azure/identity-escalation.yaml#azure-reset-password (directory-role path covering Authentication/User\
    \ Administrator \u2014 parallel; this covers the app-permission path)"
  false_positive_note: "Entra's restricted-admin protection prevents password reset for users holding\
    \ privileged directory roles \u2014 the API enforces this, not just convention. Always check the target\
    \ user's role assignments; if the user holds ANY admin directory role, emit BLOCKED rather than ACTIVE\
    \ (unless the collector confirms the role set is empty). User.ReadWrite.All does NOT permit resetting\
    \ MFA methods (that requires Authentication.ReadWrite \u2014 not modeled here). Directory.ReadWrite.All\
    \ may not cover passwordProfile update in all Entra configurations \u2014 prefer User.ReadWrite.All\
    \ appRoleId match for highest confidence. Self-service password reset (SSPR) does not interact with\
    \ this edge (this is an app-only API call, not user-initiated). The rule matches all HumanIdentity\
    \ nodes (regardless of prior role assignment data), filtering out protected admins at the where clause;\
    \ non-admin users without any direct directory role are valid targets and must not be silently excluded\
    \ by match-time role constraints."
  narrative: "{sp.name} holds User.ReadWrite.All and can reset the password of {user.name} via PATCH /users/{id}\
    \ (passwordProfile), taking over their account and inheriting all RBAC role assignments and group\
    \ memberships they hold \u2014 subject to Entra's restriction blocking resets of protected administrator\
    \ accounts."
move · open · esc close