aws-ssm-update-association-modify-code

ssm:UpdateAssociation changes the document or command parameters of a State Manager association, injecting attacker code into the managed instances the association targets.

derived aws emits CanModifyCode

match

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

{'principal': None} HasPermission {'association': None} {'association': None} CanTrigger {'instance': None}

where

effective_action == 'ssm:UpdateAssociation' node_type(?association) == Scheduler ?association.origin_service == 'aws:ssm' node_type(?instance) == VirtualMachine

emit

source typeIdentity
target typeVirtualMachine
source?principal
target?instance
permissionsssm:UpdateAssociation
conditionsiam_permission
state logicACTIVE when ssm:UpdateAssociation is EFFECTIVE on the association ID scope and the instance is in scope of the association's Targets filter and Online. The association has an existing schedule (ScheduleExpression) that provides an automatic run path — cicd-chains inherits ACTIVE state because the modification arms the next scheduled tick. BLOCKED when an SCP denies ssm:UpdateAssociation. CONDITIONAL(iam_permission) when the permission is scoped to specific association IDs and the target is not in scope.

Narrative

{principal.name} can modify State Manager association {association.name} (ssm:UpdateAssociation), injecting attacker-controlled commands that will run automatically on {instance.name} at the next scheduled tick.

Raw rule rules/derived/aws/ssm.yaml

id: aws-ssm-update-association-modify-code
emits: CanModifyCode
description: ssm:UpdateAssociation changes the document or command parameters of a State Manager association,
  injecting attacker code into the managed instances the association targets.
match:
- - principal: null
  - HasPermission
  - association: null
- - association: null
  - CanTrigger
  - instance: null
where:
- effective_action == 'ssm:UpdateAssociation'
- node_type(?association) == Scheduler
- ?association.origin_service == 'aws:ssm'
- node_type(?instance) == VirtualMachine
emit:
  source_type: Identity
  target_type: VirtualMachine
  source: ?principal
  target: ?instance
  permissions:
  - ssm:UpdateAssociation
  conditions:
  - iam_permission
  state_logic: "ACTIVE when ssm:UpdateAssociation is EFFECTIVE on the association ID scope and the instance\
    \ is in scope of the association's Targets filter and Online. The association has an existing schedule\
    \ (ScheduleExpression) that provides an automatic run path \u2014 cicd-chains inherits ACTIVE state\
    \ because the modification arms the next scheduled tick. BLOCKED when an SCP denies ssm:UpdateAssociation.\
    \ CONDITIONAL(iam_permission) when the permission is scoped to specific association IDs and the target\
    \ is not in scope."
  confidence: 0.88
  derived_from:
  - effective ssm:UpdateAssociation on ?association
  - ?association CanTrigger ?instance
  false_positive_note: "UpdateAssociation can change (a) the document ARN (swap to attacker document),\
    \ (b) the Parameters (including commands for AWS-RunShellScript), or (c) the Targets (broaden the\
    \ set of instances). All three are code/config injection; CanModifyCode is emitted because the parameter\
    \ change is equivalent to rewriting the commands the runner executes on the instance. The association's\
    \ ScheduleExpression is the automatic run path that makes this ACTIVE rather than CONDITIONAL(run_path).\
    \ If the association has no schedule (ApplyOnly without a cron), the run path is CONDITIONAL(trigger_exists)\
    \ \u2014 downgrade accordingly. The target is the VirtualMachine (Compute class) the association executes\
    \ on, not the Scheduler node, to satisfy CanModifyCode.target per schema/edges.yaml."
  narrative: '{principal.name} can modify State Manager association {association.name} (ssm:UpdateAssociation),
    injecting attacker-controlled commands that will run automatically on {instance.name} at the next
    scheduled tick.'
move · open · esc close