diff --git a/prowler/providers/aws/services/ecs/ecs_task_definitions_no_privileged_containers/__init__.py b/prowler/providers/aws/services/ecs/ecs_task_definitions_no_privileged_containers/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/prowler/providers/aws/services/ecs/ecs_task_definitions_no_privileged_containers/ecs_task_definitions_no_privileged_containers.metadata.json b/prowler/providers/aws/services/ecs/ecs_task_definitions_no_privileged_containers/ecs_task_definitions_no_privileged_containers.metadata.json new file mode 100644 index 0000000000..79cb560d0b --- /dev/null +++ b/prowler/providers/aws/services/ecs/ecs_task_definitions_no_privileged_containers/ecs_task_definitions_no_privileged_containers.metadata.json @@ -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 --container-definitions '[{\"name\":\"\",\"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": "" +} diff --git a/prowler/providers/aws/services/ecs/ecs_task_definitions_no_privileged_containers/ecs_task_definitions_no_privileged_containers.py b/prowler/providers/aws/services/ecs/ecs_task_definitions_no_privileged_containers/ecs_task_definitions_no_privileged_containers.py new file mode 100644 index 0000000000..c6f04a87bb --- /dev/null +++ b/prowler/providers/aws/services/ecs/ecs_task_definitions_no_privileged_containers/ecs_task_definitions_no_privileged_containers.py @@ -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 diff --git a/tests/providers/aws/services/ecs/ecs_task_definitions_no_privileged_containers/ecs_task_definitions_no_privileged_containers_test.py b/tests/providers/aws/services/ecs/ecs_task_definitions_no_privileged_containers/ecs_task_definitions_no_privileged_containers_test.py new file mode 100644 index 0000000000..e5c989eecb --- /dev/null +++ b/tests/providers/aws/services/ecs/ecs_task_definitions_no_privileged_containers/ecs_task_definitions_no_privileged_containers_test.py @@ -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}" + )