aws-sf-create-workload-as
Create a new Step Functions state machine bound to any role passable to states.amazonaws.com, then start an execution to run arbitrary Task states as that role.
match
A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.
where
?principal has EFFECTIVE states:CreateStateMachine (resource scope covers a new state machine)
?role trust policy allows states.amazonaws.com as a trusted service principal
iam:PassRole for ?role permits iam:PassedToService including states.amazonaws.com (or is unconditioned)
emit
| source type | Identity |
|---|---|
| target type | MachineIdentity |
| source | ?principal |
| target | ?role |
| permissions | iam:PassRole states:CreateStateMachine states:StartExecution? |
| conditions | role_compatibility iam_permission |
| state logic | ACTIVE when the principal can create the state machine (states:CreateStateMachine), pass ?role to it (iam:PassRole scoped to states.amazonaws.com), and start an execution (states:StartExecution or states:StartSyncExecution on the new machine). POTENTIAL(role_compatibility) when the role trust / PassedToService is unknown or unresolved — downgrade until trust is confirmed. CONDITIONAL(trigger_exists) when CreateStateMachine and PassRole are confirmed but StartExecution is not yet established (the attacker can create and bind, but must still trigger). |
Narrative
{principal.name} can create a new Step Functions state machine bound to {role.name} (states:CreateStateMachine + iam:PassRole to states.amazonaws.com) and start an execution, running arbitrary AWS SDK Task states as {role.name}.
Raw rule rules/derived/aws/stepfunctions.yaml
id: aws-sf-create-workload-as
emits: CanCreateWorkloadAs
description: Create a new Step Functions state machine bound to any role passable to states.amazonaws.com,
then start an execution to run arbitrary Task states as that role.
match:
- - principal: null
- CanPassIdentity
- role: null
where:
- ?principal has EFFECTIVE states:CreateStateMachine (resource scope covers a new state machine)
- ?role trust policy allows states.amazonaws.com as a trusted service principal
- iam:PassRole for ?role permits iam:PassedToService including states.amazonaws.com (or is unconditioned)
emit:
source_type: Identity
target_type: MachineIdentity
source: ?principal
target: ?role
permissions:
- iam:PassRole
- states:CreateStateMachine
- states:StartExecution?
conditions:
- role_compatibility
- iam_permission
state_logic: "ACTIVE when the principal can create the state machine (states:CreateStateMachine), pass\
\ ?role to it (iam:PassRole scoped to states.amazonaws.com), and start an execution (states:StartExecution\
\ or states:StartSyncExecution on the new machine). POTENTIAL(role_compatibility) when the role trust\
\ / PassedToService is unknown or unresolved \u2014 downgrade until trust is confirmed. CONDITIONAL(trigger_exists)\
\ when CreateStateMachine and PassRole are confirmed but StartExecution is not yet established (the\
\ attacker can create and bind, but must still trigger)."
confidence: min(contributing_confidences) * 0.95
derived_from:
- <CanPassIdentity edge_id ?principal -> ?role>
false_positive_note: "Honor iam:PassedToService: a role passable only to ec2.amazonaws.com or lambda.amazonaws.com\
\ does NOT yield Step Functions execution \u2014 downgrade to POTENTIAL(role_compatibility) when PassedToService\
\ excludes states.amazonaws.com. The role MUST trust states.amazonaws.com in its trust policy or CreateStateMachine\
\ will fail with an invalid role error. This rule folds states:CreateStateMachine (confirmed in where-clause)\
\ as the CanDeploy-equivalent; no separate CanDeploy edge is emitted for Step Functions. Dedupes with\
\ can-execute-as execute-as-via-new-workload on (CanExecuteAs, ?principal, ?role) after the CanCreateWorkloadAs\
\ -> CanExecuteAs collapse in can-execute-as."
narrative: '{principal.name} can create a new Step Functions state machine bound to {role.name} (states:CreateStateMachine
+ iam:PassRole to states.amazonaws.com) and start an execution, running arbitrary AWS SDK Task states
as {role.name}.'