gcp-dm-execute-as-via-typeprovider

A principal with deploymentmanager.typeProviders.create registers a custom type provider backed by an attacker-controlled endpoint; a DM deployment using that type causes DM to call the endpoint as the cloudservices SA, yielding execution as that SA. Uses CanModifyConfiguration path (typeProviders.create emits CanModifyConfiguration on the Deployment).

derived gcp emits CanExecuteAs

match

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

{'principal': None} CanModifyConfiguration {'deployment': None} {'deployment': None} ExecutesAs {'sa': None}

where

node_type(?deployment) == BuildWorker # DM Deployment node the CanModifyConfiguration edge originates from gcp-dm-typeprovider-create (typeProviders.create/update)

optional

Present → upgrade the emitted state; absent → downgrade (not a hard requirement).

{'principal': None} CanModifyCode {'deployment': None}

emit

source typeIdentity
target typeServiceAccount
source?principal
target?sa
permissionsdeploymentmanager.typeProviders.create deploymentmanager.deployments.create
conditionsnetwork_reachability api_enabled trigger_exists
state logicCONDITIONAL(trigger_exists, network_reachability) by default — the type provider must be instantiated by a deployment AND the attacker endpoint must be reachable. ACTIVE when the principal also holds deployments.create (matched optional[0]: CanModifyCode on the same deployment) AND the endpoint is reachable. BLOCKED by VPC Service Controls perimeter on the DM API or the external endpoint egress.

Narrative

{principal.name} can register a custom type provider (deploymentmanager.typeProviders.create) backed by an attacker-controlled HTTPS endpoint. When a DM deployment uses a resource of that type, DM calls the endpoint AS {sa.name}, executing attacker-controlled code with the SA's permissions (type provider = modified build config for the runner).

Raw rule rules/derived/gcp/deploymentmanager.yaml

id: gcp-dm-execute-as-via-typeprovider
emits: CanExecuteAs
description: A principal with deploymentmanager.typeProviders.create registers a custom type provider
  backed by an attacker-controlled endpoint; a DM deployment using that type causes DM to call the endpoint
  as the cloudservices SA, yielding execution as that SA. Uses CanModifyConfiguration path (typeProviders.create
  emits CanModifyConfiguration on the Deployment).
match:
- - principal: null
  - CanModifyConfiguration
  - deployment: null
- - deployment: null
  - ExecutesAs
  - sa: null
where:
- 'node_type(?deployment) == BuildWorker  # DM Deployment node'
- the CanModifyConfiguration edge originates from gcp-dm-typeprovider-create (typeProviders.create/update)
optional:
- - principal: null
  - CanModifyCode
  - deployment: null
emit:
  source_type: Identity
  target_type: ServiceAccount
  source: ?principal
  target: ?sa
  permissions:
  - deploymentmanager.typeProviders.create
  - deploymentmanager.deployments.create
  conditions:
  - network_reachability
  - api_enabled
  - trigger_exists
  state_logic: "CONDITIONAL(trigger_exists, network_reachability) by default \u2014 the type provider\
    \ must be instantiated by a deployment AND the attacker endpoint must be reachable. ACTIVE when the\
    \ principal also holds deployments.create (matched optional[0]: CanModifyCode on the same deployment)\
    \ AND the endpoint is reachable. BLOCKED by VPC Service Controls perimeter on the DM API or the external\
    \ endpoint egress."
  confidence: min(contributing_confidences) * 0.80
  derived_from:
  - gcp-dm-typeprovider-create (CanModifyConfiguration edge on Deployment)
  - gcp-dm-executes-as (ExecutesAs edge)
  - can-execute-as.yaml execute-as-via-code-modify (linchpin, deduped via CanModifyConfiguration variant)
  false_positive_note: "Two-step attack: (1) register malicious type provider, (2) a deployment must actuate\
    \ a resource of that type. If the principal cannot create deployments (only typeProviders.create without\
    \ deployments.create), this stays CONDITIONAL(trigger_exists). typeProviders.update on a EXISTING\
    \ provider already used by a live deployment is ACTIVE once the backend is swapped \u2014 check for\
    \ existing deployments referencing the type. Network reachability of the attacker-controlled endpoint\
    \ from GCP control plane must be verified before marking ACTIVE."
  narrative: '{principal.name} can register a custom type provider (deploymentmanager.typeProviders.create)
    backed by an attacker-controlled HTTPS endpoint. When a DM deployment uses a resource of that type,
    DM calls the endpoint AS {sa.name}, executing attacker-controlled code with the SA''s permissions
    (type provider = modified build config for the runner).'
move · open · esc close