From d51cdc068b61ab16a922e00ba7482d6275520c36 Mon Sep 17 00:00:00 2001 From: Sergio Garcia <38561120+sergargar@users.noreply.github.com> Date: Fri, 21 Apr 2023 10:42:05 +0200 Subject: [PATCH] fix(iam_role_cross_service_confused_deputy_prevention): avoid service linked roles (#2249) --- ...ross_service_confused_deputy_prevention.py | 8 +-- ...service_confused_deputy_prevention_test.py | 64 ++++++++++++++++++- 2 files changed, 66 insertions(+), 6 deletions(-) diff --git a/prowler/providers/aws/services/iam/iam_role_cross_service_confused_deputy_prevention/iam_role_cross_service_confused_deputy_prevention.py b/prowler/providers/aws/services/iam/iam_role_cross_service_confused_deputy_prevention/iam_role_cross_service_confused_deputy_prevention.py index 9546b1f5..ed20464d 100644 --- a/prowler/providers/aws/services/iam/iam_role_cross_service_confused_deputy_prevention/iam_role_cross_service_confused_deputy_prevention.py +++ b/prowler/providers/aws/services/iam/iam_role_cross_service_confused_deputy_prevention/iam_role_cross_service_confused_deputy_prevention.py @@ -6,15 +6,15 @@ class iam_role_cross_service_confused_deputy_prevention(Check): def execute(self) -> Check_Report_AWS: findings = [] for role in iam_client.roles: - # This check should only be performed against service roles - if role.is_service_role: + # This check should only be performed against service roles (avoid Service Linked Roles since the trust relationship cannot be changed) + if role.is_service_role and "aws-service-role" not in role.arn: report = Check_Report_AWS(self.metadata()) report.region = iam_client.region report.resource_arn = role.arn report.resource_id = role.name report.resource_tags = role.tags report.status = "FAIL" - report.status_extended = f"IAM Service Role {role.name} prevents against a cross-service confused deputy attack" + report.status_extended = f"IAM Service Role {role.name} does not prevent against a cross-service confused deputy attack" for statement in role.assume_role_policy["Statement"]: if ( statement["Effect"] == "Allow" @@ -59,7 +59,7 @@ class iam_role_cross_service_confused_deputy_prevention(Check): ) ): report.status = "PASS" - report.status_extended = f"IAM Service Role {role.name} does not prevent against a cross-service confused deputy attack" + report.status_extended = f"IAM Service Role {role.name} prevents against a cross-service confused deputy attack" break findings.append(report) diff --git a/tests/providers/aws/services/iam/iam_role_cross_service_confused_deputy_prevention/iam_role_cross_service_confused_deputy_prevention_test.py b/tests/providers/aws/services/iam/iam_role_cross_service_confused_deputy_prevention/iam_role_cross_service_confused_deputy_prevention_test.py index 3c9ef69d..0ace9ab3 100644 --- a/tests/providers/aws/services/iam/iam_role_cross_service_confused_deputy_prevention/iam_role_cross_service_confused_deputy_prevention_test.py +++ b/tests/providers/aws/services/iam/iam_role_cross_service_confused_deputy_prevention/iam_role_cross_service_confused_deputy_prevention_test.py @@ -5,6 +5,7 @@ from boto3 import client, session from moto import mock_iam from prowler.providers.aws.lib.audit_info.models import AWS_Audit_Info +from prowler.providers.aws.services.iam.iam_service import Role AWS_REGION = "us-east-1" AWS_ACCOUNT_ID = "123456789012" @@ -34,6 +35,65 @@ class Test_iam_role_cross_service_confused_deputy_prevention: return audit_info + @mock_iam + def test_no_roles(self): + from prowler.providers.aws.services.iam.iam_service import IAM + + current_audit_info = self.set_mocked_audit_info() + current_audit_info.audited_account = AWS_ACCOUNT_ID + with mock.patch( + "prowler.providers.aws.lib.audit_info.audit_info.current_audit_info", + new=current_audit_info, + ), mock.patch( + "prowler.providers.aws.services.iam.iam_role_cross_service_confused_deputy_prevention.iam_role_cross_service_confused_deputy_prevention.iam_client", + new=IAM(current_audit_info), + ): + # Test Check + from prowler.providers.aws.services.iam.iam_role_cross_service_confused_deputy_prevention.iam_role_cross_service_confused_deputy_prevention import ( + iam_role_cross_service_confused_deputy_prevention, + ) + + check = iam_role_cross_service_confused_deputy_prevention() + result = check.execute() + assert len(result) == 0 + + @mock_iam + def test_only_aws_service_linked_roles(self): + iam_client = mock.MagicMock + iam_client.roles = [] + iam_client.roles.append( + Role( + name="AWSServiceRoleForAmazonGuardDuty", + arn="arn:aws:iam::106908755756:role/aws-service-role/guardduty.amazonaws.com/AWSServiceRoleForAmazonGuardDuty", + assume_role_policy={ + "Version": "2008-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": {"Service": "ec2.amazonaws.com"}, + "Action": "sts:AssumeRole", + } + ], + }, + is_service_role=True, + ) + ) + + current_audit_info = self.set_mocked_audit_info() + current_audit_info.audited_account = AWS_ACCOUNT_ID + with mock.patch( + "prowler.providers.aws.services.iam.iam_service.IAM", + iam_client, + ): + # Test Check + from prowler.providers.aws.services.iam.iam_role_cross_service_confused_deputy_prevention.iam_role_cross_service_confused_deputy_prevention import ( + iam_role_cross_service_confused_deputy_prevention, + ) + + check = iam_role_cross_service_confused_deputy_prevention() + result = check.execute() + assert len(result) == 0 + @mock_iam def test_iam_service_role_without_cross_service_confused_deputy_prevention(self): iam_client = client("iam", region_name=AWS_REGION) @@ -74,7 +134,7 @@ class Test_iam_role_cross_service_confused_deputy_prevention: assert result[0].status == "FAIL" assert ( result[0].status_extended - == "IAM Service Role test prevents against a cross-service confused deputy attack" + == "IAM Service Role test does not prevent against a cross-service confused deputy attack" ) assert result[0].resource_id == "test" assert result[0].resource_arn == response["Role"]["Arn"] @@ -122,7 +182,7 @@ class Test_iam_role_cross_service_confused_deputy_prevention: assert result[0].status == "PASS" assert ( result[0].status_extended - == "IAM Service Role test does not prevent against a cross-service confused deputy attack" + == "IAM Service Role test prevents against a cross-service confused deputy attack" ) assert result[0].resource_id == "test" assert result[0].resource_arn == response["Role"]["Arn"]