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.
match
A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.
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. |
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}.'