gcp-cloudsql-escalate-via-password-reset
A principal who can reset the root DB user password and then read all data in a Cloud SQL instance has escalated to full DBA-level database privilege.
match
A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.
{'principal': None}
CanResetCredential {'db_user': None}
{'principal': None} CanReadData {'instance': None}
where
node_type(?db_user) ==
GenericIdentity # Cloud SQL root/admin DB user (internal engine identity)
node_type(?instance) == RelationalDatabase
?db_user is the root user of ?instance
?principal.privilege_level < elevated
emit
| source type | Identity |
|---|---|
| target type | GenericIdentity |
| source | ?principal |
| target | ?db_user |
| permissions | cloudsql.users.update |
| conditions | iam_permission |
| state logic | inherit_weakest(CanResetCredential, CanReadData): ACTIVE when both contributing edges are ACTIVE; inherits CONDITIONAL/BLOCKED from whichever contributor is weakest. Only emit when the CanReadData is derived from the password-reset chain (gcp-cloudsql-reset-password-read-data), not from independent IAM auth (which is a legitimate access path, not escalation from credential reset). |
Narrative
{principal.name} can escalate to full DBA-level access on {instance.name} by resetting the root DB user password (cloudsql.users.update) and connecting as root - gaining read/write/admin access to all databases in the instance.
Raw rule rules/derived/gcp/cloudsql.yaml
id: gcp-cloudsql-escalate-via-password-reset
emits: CanEscalateTo
description: A principal who can reset the root DB user password and then read all data in a Cloud SQL
instance has escalated to full DBA-level database privilege.
match:
- - principal: null
- CanResetCredential
- db_user: null
- - principal: null
- CanReadData
- instance: null
where:
- 'node_type(?db_user) == GenericIdentity # Cloud SQL root/admin DB user (internal engine identity)'
- node_type(?instance) == RelationalDatabase
- ?db_user is the root user of ?instance
- ?principal.privilege_level < elevated
emit:
source_type: Identity
target_type: GenericIdentity
source: ?principal
target: ?db_user
permissions:
- cloudsql.users.update
conditions:
- iam_permission
state_logic: 'inherit_weakest(CanResetCredential, CanReadData): ACTIVE when both contributing edges
are ACTIVE; inherits CONDITIONAL/BLOCKED from whichever contributor is weakest. Only emit when the
CanReadData is derived from the password-reset chain (gcp-cloudsql-reset-password-read-data), not
from independent IAM auth (which is a legitimate access path, not escalation from credential reset).'
false_positive_note: "This is a DATA-PLANE escalation: the principal gains DBA-level SQL access over\
\ all databases in the instance, which is above its prior privilege level. It is NOT a GCP IAM management-plane\
\ escalation (no new IAM role is gained). can-control.yaml escalate-via-execute-as handles CanExecuteAs\
\ paths \u2014 do not re-derive that here. Only emit when the principal's effective DB privilege before\
\ the reset is less than DBA (e.g., it had no DB credentials at all or was a read-only DB user). Target\
\ is the root DB user (GenericIdentity, internal engine identity not HumanIdentity), not the principal\
\ itself \u2014 the escalation is to that identity. See gcp-cloudsql-explicit-can-reset-credential\
\ for context."
narrative: "{principal.name} can escalate to full DBA-level access on {instance.name} by resetting the\
\ root DB user password (cloudsql.users.update) and connecting as root \u2014 gaining read/write/admin\
\ access to all databases in the instance."
derived_from:
- ?principal CanResetCredential ?db_user
- ?principal CanReadData ?instance (via gcp-cloudsql-reset-password-read-data)