feat(ecs): Ensure ECS containers run as non-privileged (#5214)

This commit is contained in:
Mario Rodriguez Lopez
2024-09-26 20:05:11 +02:00
committed by GitHub
parent 1a679f371f
commit 0474c7995c
4 changed files with 167 additions and 0 deletions
@@ -0,0 +1,34 @@
{
"Provider": "aws",
"CheckID": "ecs_task_definitions_no_privileged_containers",
"CheckTitle": "ECS task definitions shouldn't have privileged containers",
"CheckType": [
"Software and Configuration Checks/AWS Security Best Practices"
],
"ServiceName": "ecs",
"SubServiceName": "taskDefinition",
"ResourceIdTemplate": "arn:aws:ecs:{region}:{account-id}:task-definition/{task-definition-name}",
"Severity": "high",
"ResourceType": "AwsEcsTaskDefinition",
"Description": "This control checks if the privileged parameter in the container definition of Amazon ECS Task Definitions is set to true. The control fails if this parameter is equal to true.",
"Risk": "Running containers with elevated privileges increases the risk of privilege escalation attacks, potentially allowing unauthorized access to the host and other containers.",
"RelatedUrl": "https://docs.aws.amazon.com/config/latest/developerguide/ecs-containers-nonprivileged.html",
"Remediation": {
"Code": {
"CLI": "aws ecs register-task-definition --family <task-family> --container-definitions '[{\"name\":\"<container-name>\",\"image\":\"<image>\",\"privileged\":false}]'",
"NativeIaC": "",
"Other": "https://docs.aws.amazon.com/securityhub/latest/userguide/ecs-controls.html#ecs-4",
"Terraform": ""
},
"Recommendation": {
"Text": "Ensure that containers are running without elevated privileges to minimize the risk of privilege escalation.",
"Url": "https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definition_parameters.html#container_definition_security"
}
},
"Categories": [
"vulnerabilities"
],
"DependsOn": [],
"RelatedTo": [],
"Notes": ""
}
@@ -0,0 +1,25 @@
from prowler.lib.check.models import Check, Check_Report_AWS
from prowler.providers.aws.services.ecs.ecs_client import ecs_client
class ecs_task_definitions_no_privileged_containers(Check):
def execute(self):
findings = []
for task_definition in ecs_client.task_definitions.values():
report = Check_Report_AWS(self.metadata())
report.region = task_definition.region
report.resource_id = f"{task_definition.name}:{task_definition.revision}"
report.resource_arn = task_definition.arn
report.resource_tags = task_definition.tags
report.status = "PASS"
report.status_extended = f"ECS task definition {task_definition.name} does not have privileged containers."
failed_containers = []
for container in task_definition.container_definitions:
if container.privileged:
report.status = "FAIL"
failed_containers.append(container.name)
if failed_containers:
report.status_extended = f"ECS task definition {task_definition.name} has privileged containers: {', '.join(failed_containers)}"
findings.append(report)
return findings
@@ -0,0 +1,108 @@
from unittest import mock
from prowler.providers.aws.services.ecs.ecs_service import (
ContainerDefinition,
ContainerEnvVariable,
TaskDefinition,
)
from tests.providers.aws.utils import AWS_ACCOUNT_NUMBER, AWS_REGION_US_EAST_1
TASK_NAME = "test-task"
TASK_REVISION = "1"
CONTAINER_NAME = "test-container"
TASK_ARN = f"arn:aws:ecs:{AWS_REGION_US_EAST_1}:{AWS_ACCOUNT_NUMBER}:task-definition/{TASK_NAME}:{TASK_REVISION}"
class Test_ecs_task_definitions_no_privileged_containers:
def test_no_task_definitions(self):
ecs_client = mock.MagicMock
ecs_client.task_definitions = {}
with mock.patch(
"prowler.providers.aws.services.ecs.ecs_service.ECS",
ecs_client,
):
from prowler.providers.aws.services.ecs.ecs_task_definitions_no_privileged_containers.ecs_task_definitions_no_privileged_containers import (
ecs_task_definitions_no_privileged_containers,
)
check = ecs_task_definitions_no_privileged_containers()
result = check.execute()
assert len(result) == 0
def test_task_definition_no_priviled_container(self):
ecs_client = mock.MagicMock
ecs_client.task_definitions = {}
ecs_client.task_definitions[TASK_ARN] = TaskDefinition(
name=TASK_NAME,
arn=TASK_ARN,
revision=TASK_REVISION,
region=AWS_REGION_US_EAST_1,
network_mode="bridge",
container_definitions=[
ContainerDefinition(
name=CONTAINER_NAME,
privileged=False,
user="",
environment=[
ContainerEnvVariable(
name="env_var_name_no_secrets",
value="env_var_value_no_secrets",
)
],
)
],
)
with mock.patch(
"prowler.providers.aws.services.ecs.ecs_service.ECS",
ecs_client,
):
from prowler.providers.aws.services.ecs.ecs_task_definitions_no_privileged_containers.ecs_task_definitions_no_privileged_containers import (
ecs_task_definitions_no_privileged_containers,
)
check = ecs_task_definitions_no_privileged_containers()
result = check.execute()
assert len(result) == 1
assert result[0].status == "PASS"
assert (
result[0].status_extended
== f"ECS task definition {TASK_NAME} does not have privileged containers."
)
def test_task_definition_privileged_container(self):
ecs_client = mock.MagicMock
ecs_client.task_definitions = {}
ecs_client.task_definitions[TASK_ARN] = TaskDefinition(
name=TASK_NAME,
arn=TASK_ARN,
revision=TASK_REVISION,
region=AWS_REGION_US_EAST_1,
network_mode="host",
container_definitions=[
ContainerDefinition(
name=CONTAINER_NAME,
privileged=True,
user="root",
environment=[],
)
],
)
with mock.patch(
"prowler.providers.aws.services.ecs.ecs_service.ECS",
ecs_client,
):
from prowler.providers.aws.services.ecs.ecs_task_definitions_no_privileged_containers.ecs_task_definitions_no_privileged_containers import (
ecs_task_definitions_no_privileged_containers,
)
check = ecs_task_definitions_no_privileged_containers()
result = check.execute()
assert len(result) == 1
assert result[0].status == "FAIL"
assert (
result[0].status_extended
== f"ECS task definition {TASK_NAME} has privileged containers: {CONTAINER_NAME}"
)