azure-b2c-policy-write-trust-injection

A principal who can write B2C custom policy XML can inject a Technical Profile trusting an attacker-controlled OIDC/SAML IdP.

derived azure emits CanModifyTrust

match

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

{'principal': None} CanModifyConfiguration {'policy': None}

where

node_type(?policy) == TrustPolicy # B2C IEF custom policy ?policy.provider_type in ['Microsoft.AzureActiveDirectory/b2cDirectories/trustFramework/policies']

emit

source typeIdentity
target typeTrustPolicy
source?principal
target?policy
permissionsPolicy.ReadWrite.TrustFramework
conditionsiam_permission
state logicACTIVE when the principal holds effective B2C IEF Policy Administrator or Global Administrator directory role in the B2C tenant (CanModifyConfiguration on the policy is ACTIVE). CONDITIONAL if the policy write permission is itself CONDITIONAL (e.g. behind MFA / PIM / Just-In-Time activation). BLOCKED if the policy upload API is restricted by a Conditional Access policy blocking the principal.

Narrative

{principal.name} can write B2C custom policy XML (IEF Policy Administrator / Global Admin), effectively modifying the trust configuration. An attacker can inject a Technical Profile trusting an external OIDC/SAML identity provider they control, which will then be accepted by all relying party applications served by {policy.name}.

Raw rule rules/derived/azure/b2c.yaml

id: azure-b2c-policy-write-trust-injection
emits: CanModifyTrust
description: A principal who can write B2C custom policy XML can inject a Technical Profile trusting an
  attacker-controlled OIDC/SAML IdP.
match:
- - principal: null
  - CanModifyConfiguration
  - policy: null
where:
- 'node_type(?policy) == TrustPolicy  # B2C IEF custom policy'
- ?policy.provider_type in ['Microsoft.AzureActiveDirectory/b2cDirectories/trustFramework/policies']
emit:
  source_type: Identity
  target_type: TrustPolicy
  source: ?principal
  target: ?policy
  permissions:
  - Policy.ReadWrite.TrustFramework
  conditions:
  - iam_permission
  state_logic: ACTIVE when the principal holds effective B2C IEF Policy Administrator or Global Administrator
    directory role in the B2C tenant (CanModifyConfiguration on the policy is ACTIVE). CONDITIONAL if
    the policy write permission is itself CONDITIONAL (e.g. behind MFA / PIM / Just-In-Time activation).
    BLOCKED if the policy upload API is restricted by a Conditional Access policy blocking the principal.
  confidence: 0.8
  derived_from:
  - azure-b2c-policy-admin-can-modify-config (rule 5, derived)
  false_positive_note: "Requires confirmed B2C IEF Policy Administrator or Global Administrator role INSIDE\
    \ the B2C tenant (not just ARM Contributor on the subscription resource). ARM Contributor on Microsoft.AzureActiveDirectory/b2cDirectories\
    \ does NOT confer directory roles \u2014 do not emit if only ARM permissions are observed. Once the\
    \ attacker rewrites the policy to inject an IdP they control, the explicit azure-b2c-idp-trusts-external\
    \ rule produces TrustsExternalIdentity on the next collection, and federation-chains will roll this\
    \ up to CanFederateAs."
  narrative: '{principal.name} can write B2C custom policy XML (IEF Policy Administrator / Global Admin),
    effectively modifying the trust configuration. An attacker can inject a Technical Profile trusting
    an external OIDC/SAML identity provider they control, which will then be accepted by all relying party
    applications served by {policy.name}.'
move · open · esc close