azure-firewall-write-weaken
Write access to the Azure Firewall object (classic model) lets an attacker add or replace NAT, Network, or Application rule collections - inserting ALLOW rules or DNAT entries to open previously blocked network paths. When a Firewall Policy is attached, the classic inline rule collections become read-only (policy model takes precedence).
match (effective permission)
{
"action": "Microsoft.Network/azureFirewalls/write",
"scope_type": "resource|resourceGroup|subscription"
}
emit
| source type | Identity |
|---|---|
| target type | Network |
| source | <principal> |
| target | <Azure Firewall (Firewall node)> |
| permissions | Microsoft.Network/azureFirewalls/write |
| state logic | ACTIVE: if firewall.properties.firewallPolicy is null or empty. The principal can PUT a modified firewall object (replacing the entire classic rule set in one ARM PUT); effect realized at next Azure Firewall rule-processing cycle (near-instant). CONDITIONAL(service_state): if firewall has a linked firewallPolicy, the classic inline rule collections are read-only. The write action is accepted but produces no rule-change effect. BLOCKED if a deny assignment covers azureFirewalls/write at the firewall/RG/sub scope, or if Azure Policy (deny effect) blocks firewall writes at an assigned scope. |
Narrative
{principal.name} can modify rule collections on Azure Firewall {target.name} via Microsoft.Network/azureFirewalls/write (classic model), enabling insertion of ALLOW or DNAT rules that open previously blocked network paths. Effect only applies if no Firewall Policy is attached.
Raw rule rules/derived/azure/firewall.yaml
id: azure-firewall-write-weaken
emits: CanModifyConfiguration
description: "Write access to the Azure Firewall object (classic model) lets an attacker add or replace\
\ NAT, Network, or Application rule collections \u2014 inserting ALLOW rules or DNAT entries to open\
\ previously blocked network paths. When a Firewall Policy is attached, the classic inline rule collections\
\ become read-only (policy model takes precedence)."
match_effective_permission:
action: Microsoft.Network/azureFirewalls/write
scope_type: resource|resourceGroup|subscription
emit:
source_type: Identity
target_type: Network
source: <principal>
target: <Azure Firewall (Firewall node)>
permissions:
- Microsoft.Network/azureFirewalls/write
state_logic: 'ACTIVE: if firewall.properties.firewallPolicy is null or empty. The principal can PUT
a modified firewall object (replacing the entire classic rule set in one ARM PUT); effect realized
at next Azure Firewall rule-processing cycle (near-instant). CONDITIONAL(service_state): if firewall
has a linked firewallPolicy, the classic inline rule collections are read-only. The write action is
accepted but produces no rule-change effect. BLOCKED if a deny assignment covers azureFirewalls/write
at the firewall/RG/sub scope, or if Azure Policy (deny effect) blocks firewall writes at an assigned
scope.'
false_positive_note: "The classic azureFirewalls/write only grants control over inline rule collections.\
\ When a Firewall Policy is linked (firewallPolicy property non-null), the policy model overrides\
\ classic rules \u2014 the write still succeeds but is ineffective for adding attack rules. A Reader\
\ assignment (azureFirewalls/read only) does NOT yield this capability. In a hub-spoke topology, control\
\ of the hub firewall affects traffic for all spoke VNets."
narrative: '{principal.name} can modify rule collections on Azure Firewall {target.name} via Microsoft.Network/azureFirewalls/write
(classic model), enabling insertion of ALLOW or DNAT rules that open previously blocked network paths.
Effect only applies if no Firewall Policy is attached.'
derived_from:
- iam:effective_permission(Microsoft.Network/azureFirewalls/write, {source}, {target})