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.

derived azure emits CanModifyConfiguration

match

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

{'principal': None} HasPermission {'server': None}

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 typeIdentity
target typeRelationalDatabase
source?principal
target?server
permissionsMicrosoft.DBforPostgreSQL/flexibleServers/firewallRules/write Microsoft.DBforMySQL/flexibleServers/firewallRules/write
conditionsiam_permission
state logicif 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.'
move · open · esc close