azure-appgw-attach-mi
An attacker who can write an Application Gateway and pass a user-assigned MI can swap the gateway's identity, gaining that MI's Key Vault (and potentially broader) permissions.
match
A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.
where
?principal has EFFECTIVE Microsoft.
ManagedIdentity/userAssignedIdentities/assign/action on ?userMI
?principal has EFFECTIVE Microsoft.Network/applicationGateways/write on the target Application Gateway
emit
| source type | Identity |
|---|---|
| target type | LoadBalancer |
| source | <principal> |
| target | <Microsoft.Network/applicationGateways> |
| permissions | Microsoft.ManagedIdentity/userAssignedIdentities/assign/action Microsoft.Network/applicationGateways/write |
| conditions | role_compatibility |
| state logic | if both assign/action and applicationGateways/write are confirmed at their respective scopes with no deny assignment: ACTIVE; if assign/action or trust is unknown/unresolved: POTENTIAL(role_compatibility). |
Narrative
{principal.name} can attach user-assigned MI {userMI.name} to Application Gateway {target.name} (assign/action + applicationGateways/write). This grants the gateway - and any process that can read Key Vault secrets via the gateway's identity - the permissions of {userMI.name}.
Raw rule rules/derived/azure/loadbalancer.yaml
id: azure-appgw-attach-mi
emits: CanAttachIdentity
description: An attacker who can write an Application Gateway and pass a user-assigned MI can swap the
gateway's identity, gaining that MI's Key Vault (and potentially broader) permissions.
match:
- - principal: null
- CanPassIdentity
- userMI: null
where:
- ?principal has EFFECTIVE Microsoft.ManagedIdentity/userAssignedIdentities/assign/action on ?userMI
- ?principal has EFFECTIVE Microsoft.Network/applicationGateways/write on the target Application Gateway
emit:
source_type: Identity
target_type: LoadBalancer
source: <principal>
target: <Microsoft.Network/applicationGateways>
permissions:
- Microsoft.ManagedIdentity/userAssignedIdentities/assign/action
- Microsoft.Network/applicationGateways/write
conditions:
- role_compatibility
state_logic: 'if both assign/action and applicationGateways/write are confirmed at their respective
scopes with no deny assignment: ACTIVE; if assign/action or trust is unknown/unresolved: POTENTIAL(role_compatibility).'
derived_from:
- <CanPassIdentity edge_id>
note: 'Emits CanAttachIdentity with nature: derived. CanAttachIdentity in edges.yaml allows nature:
explicit, but this rule is a pattern-based derivation that combines CanPassIdentity + write permission.
Both nature modes are conformant (CanAttachIdentity: nature: explicit in edges.yaml; derived rule
may only emit nature: derived or both, not explicit alone). This rule MUST use nature: both in edges.yaml
or be reformulated as an explicit_rules entry without match:. The current derivation pattern is correct;
CanAttachIdentity''s nature in edges.yaml needs to be updated to both to reflect this reality.'
false_positive_note: "BOTH permissions are required: assign/action on the target MI AND applicationGateways/write\
\ on the gateway. Neither alone attaches the MI. The attached MI on an Application Gateway is used\
\ for Key Vault certificate access \u2014 confirm the MI's role assignments to determine actual blast\
\ radius (may be limited to Key Vault reads). Do not assume subscription-level escalation without\
\ checking the MI's effective permissions."
narrative: "{principal.name} can attach user-assigned MI {userMI.name} to Application Gateway {target.name}\
\ (assign/action + applicationGateways/write). This grants the gateway \u2014 and any process that\
\ can read Key Vault secrets via the gateway's identity \u2014 the permissions of {userMI.name}."