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.
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 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 — 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.'