azure-postgres-mysql-firewall-write-exposure
Firewall write permission on a public-access server allows creating an allow-all rule, exposing the DB endpoint to the internet.
match
A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.
where
node_class(?server) == Data and node_type(?server) ==
RelationalDatabase
node_type(?server) matched provider_type in ['Microsoft.DBforPostgreSQL/flexibleServers', 'Microsoft.DBforMySQL/flexibleServers']
?server.properties.publicNetworkAccess == 'Enabled'
?principal has EFFECTIVE Microsoft.DBforPostgreSQL/flexibleServers/firewallRules/write OR Microsoft.DBforMySQL/flexibleServers/firewallRules/write (as applicable) at ?server scope
emit
| source type | Identity |
|---|---|
| target type | RelationalDatabase |
| source | ?principal |
| target | ?server |
| permissions | Microsoft.DBforPostgreSQL/flexibleServers/firewallRules/write Microsoft.DBforMySQL/flexibleServers/firewallRules/write |
| conditions | iam_permission |
| state logic | if a deny assignment or deny Azure Policy covers firewallRules/write at effective scope: BLOCKED; elif ?server.properties.publicNetworkAccess == 'Disabled': POTENTIAL (caller has permission to modify firewall, but private-access topology has no public endpoint; the rule would have no effect); elif a rule admitting 0.0.0.0–255.255.255.255 already exists: ACTIVE (network exposure is already realized; this rule is redundant); else POTENTIAL (the caller can create the exposure by adding a new rule, but has not done so yet). NOTE: This rule represents configuration authority (firewallRules/write) that can lead to network exposure (configuration→ network_exposure→data_read chain). The immediate downstream effect is to enable public reachability (ExposedToInternet), not execution. |
Narrative
{principal.name} can create or modify firewall rules on {server.name} (Microsoft.DBforPostgreSQL/flexibleServers/firewallRules/write). By adding a rule with startIpAddress=0.0.0.0 and endIpAddress=255.255.255.255, the attacker can expose the database endpoint to the public internet, enabling the network_reachability condition for the CanModifyConfiguration -> CanReadData escalation.
Raw rule rules/derived/azure/postgres-mysql.yaml
id: azure-postgres-mysql-firewall-write-exposure
emits: CanModifyConfiguration
description: Firewall write permission on a public-access server allows creating an allow-all rule, exposing
the DB endpoint to the internet.
match:
- - principal: null
- HasPermission
- server: null
where:
- node_class(?server) == Data and node_type(?server) == RelationalDatabase
- node_type(?server) matched provider_type in ['Microsoft.DBforPostgreSQL/flexibleServers', 'Microsoft.DBforMySQL/flexibleServers']
- ?server.properties.publicNetworkAccess == 'Enabled'
- ?principal has EFFECTIVE Microsoft.DBforPostgreSQL/flexibleServers/firewallRules/write OR Microsoft.DBforMySQL/flexibleServers/firewallRules/write
(as applicable) at ?server scope
emit:
source_type: Identity
target_type: RelationalDatabase
source: ?principal
target: ?server
permissions:
- Microsoft.DBforPostgreSQL/flexibleServers/firewallRules/write
- Microsoft.DBforMySQL/flexibleServers/firewallRules/write
conditions:
- iam_permission
state_logic: "if a deny assignment or deny Azure Policy covers firewallRules/write at effective scope:\
\ BLOCKED; elif ?server.properties.publicNetworkAccess == 'Disabled': POTENTIAL (caller has permission\
\ to modify firewall, but private-access topology has no public endpoint; the rule would have no effect);\
\ elif a rule admitting 0.0.0.0\u2013255.255.255.255 already exists: ACTIVE (network exposure is already\
\ realized; this rule is redundant); else POTENTIAL (the caller can create the exposure by adding\
\ a new rule, but has not done so yet). NOTE: This rule represents configuration authority (firewallRules/write)\
\ that can lead to network exposure (configuration\u2192 network_exposure\u2192data_read chain). The\
\ immediate downstream effect is to enable public reachability (ExposedToInternet), not execution."
confidence: '0.91'
derived_from:
- 'HasPermission edge: source=?principal, target=?server, action=(Microsoft.DBforPostgreSQL/flexibleServers/firewallRules/write
| Microsoft.DBforMySQL/flexibleServers/firewallRules/write)'
false_positive_note: "Verify effective firewallRules/write permission via role definition resolution.\
\ Private-access servers (publicNetworkAccess == Disabled) render this permission inert \u2014 emit\
\ POTENTIAL only, not ACTIVE, since the public endpoint does not exist. For public-access servers:\
\ check if a full-internet rule (0.0.0.0\u2013255.255.255.255) already exists; if so, the exposure\
\ is already ACTIVE and this rule is a supporting evidence, not a new capability. Emit POTENTIAL when\
\ the permission exists but the exposure rule does not yet. This edge should be chained to ExposedToInternet\
\ via a downstream derived rule (not currently implemented \u2014 TODO: add azure-postgres-mysql-firewall-write-creates-exposure)."
narrative: '{principal.name} can create or modify firewall rules on {server.name} (Microsoft.DBforPostgreSQL/flexibleServers/firewallRules/write).
By adding a rule with startIpAddress=0.0.0.0 and endIpAddress=255.255.255.255, the attacker can expose
the database endpoint to the public internet, enabling the network_reachability condition for the
CanModifyConfiguration -> CanReadData escalation.'