azure-mi-exposes-credential

A host with a bound MI exposes that identity's bearer token credential via the IMDS / App Service identity endpoint to any code running inside it.

derived azure emits ExposesCredential

match

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

{'host': None} ExecutesAs {'mi': None} {'token': None} CredentialsFor {'mi': None}

where

node_type(?mi) == ManagedIdentity node_type(?token) == Token node_class(?host) == Compute ?host.identity.type != 'None' node_name(?token) matches 'imds-.*' and extract_host_id(?token) == node_id(?host)

emit

source typeCompute
target typeCredential
source?host
target?token
conditionsservice_state
state logicACTIVE when host is running and has the MI binding. CONDITIONAL(service_state) when stopped/deallocated (IMDS is only reachable from a running host).

Narrative

The instance metadata endpoint on {host.name} exposes the bearer token {token.name} (for managed identity {mi.name}) to any code running inside {host.name}. An attacker with code execution on {host.name} can retrieve this token and authenticate as {mi.name}.

Raw rule rules/derived/azure/managedidentity.yaml

id: azure-mi-exposes-credential
emits: ExposesCredential
description: A host with a bound MI exposes that identity's bearer token credential via the IMDS / App
  Service identity endpoint to any code running inside it.
match:
- - host: null
  - ExecutesAs
  - mi: null
- - token: null
  - CredentialsFor
  - mi: null
where:
- node_type(?mi) == ManagedIdentity
- node_type(?token) == Token
- node_class(?host) == Compute
- ?host.identity.type != 'None'
- node_name(?token) matches 'imds-.*' and extract_host_id(?token) == node_id(?host)
emit:
  source_type: Compute
  target_type: Credential
  source: ?host
  target: ?token
  permissions: []
  conditions:
  - service_state
  state_logic: ACTIVE when host is running and has the MI binding. CONDITIONAL(service_state) when stopped/deallocated
    (IMDS is only reachable from a running host).
  confidence: 0.98
  derived_from:
  - ?host ExecutesAs ?mi
  - ?token CredentialsFor ?mi (synthetic IMDS token)
  false_positive_note: "Paired with azure-mi-token-credentials-for. Do NOT emit when identity.type ==\
    \ 'None'. This edge models the FACT that the host's IMDS endpoint exposes the token object to any\
    \ code running inside. The endpoint is link-local \u2014 not accessible from outside the host's network\
    \ stack. The actual traversal value comes from credential-chains (CanReadSecret on the token, then\
    \ CredentialsFor to the MI)."
  narrative: The instance metadata endpoint on {host.name} exposes the bearer token {token.name} (for
    managed identity {mi.name}) to any code running inside {host.name}. An attacker with code execution
    on {host.name} can retrieve this token and authenticate as {mi.name}.
move · open · esc close