diff --git a/docs/tutorials/aws/v2_to_v3_checks_mapping.md b/docs/tutorials/aws/v2_to_v3_checks_mapping.md index 275682b5..fe80cd4b 100644 --- a/docs/tutorials/aws/v2_to_v3_checks_mapping.md +++ b/docs/tutorials/aws/v2_to_v3_checks_mapping.md @@ -137,7 +137,6 @@ checks_v3_to_v2_mapping = { "elbv2_internet_facing": "extra79", "elbv2_listeners_underneath": "extra7158", "elbv2_logging_enabled": "extra717", - "elbv2_request_smugling": "extra7142", "elbv2_ssl_listeners": "extra793", "elbv2_waf_acl_attached": "extra7129", "emr_cluster_account_public_block_enabled": "extra7178", diff --git a/poetry.lock b/poetry.lock index 7a4fe970..13204288 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry and should not be changed by hand. +# This file is automatically @generated by Poetry 1.4.0 and should not be changed by hand. [[package]] name = "about-time" diff --git a/prowler/providers/aws/services/elbv2/elbv2_desync_mitigation_mode/elbv2_desync_mitigation_mode.metadata.json b/prowler/providers/aws/services/elbv2/elbv2_desync_mitigation_mode/elbv2_desync_mitigation_mode.metadata.json index c2527db7..11863cb7 100644 --- a/prowler/providers/aws/services/elbv2/elbv2_desync_mitigation_mode/elbv2_desync_mitigation_mode.metadata.json +++ b/prowler/providers/aws/services/elbv2/elbv2_desync_mitigation_mode/elbv2_desync_mitigation_mode.metadata.json @@ -1,7 +1,7 @@ { "Provider": "aws", "CheckID": "elbv2_desync_mitigation_mode", - "CheckTitle": "Check whether the Application Load Balancer is configured with defensive or strictest desync mitigation mode.", + "CheckTitle": "Check whether the Application Load Balancer is configured with defensive or strictest desync mitigation mode, if not check if at least is configured with the drop_invalid_header_fields attribute", "CheckType": [ "Data Protection" ], @@ -10,7 +10,7 @@ "ResourceIdTemplate": "arn:partition:service:region:account-id:resource-id", "Severity": "medium", "ResourceType": "AwsElasticLoadBalancingV2LoadBalancer", - "Description": "Check whether the Application Load Balancer is configured with defensive or strictest desync mitigation mode.", + "Description": "Check whether the Application Load Balancer is configured with defensive or strictest desync mitigation mode, if not check if at least is configured with the drop_invalid_header_fields attribute", "Risk": "HTTP Desync issues can lead to request smuggling and make your applications vulnerable to request queue or cache poisoning; which could lead to credential hijacking or execution of unauthorized commands.", "RelatedUrl": "", "Remediation": { @@ -21,7 +21,7 @@ "Terraform": "" }, "Recommendation": { - "Text": "Ensure Application Load Balancer is configured with defensive or strictest desync mitigation mode.", + "Text": "Ensure Application Load Balancer is configured with defensive or strictest desync mitigation mode or with the drop_invalid_header_fields attribute enabled", "Url": "https://aws.amazon.com/about-aws/whats-new/2020/08/application-and-classic-load-balancers-adding-defense-in-depth-with-introduction-of-desync-mitigation-mode/" } }, diff --git a/prowler/providers/aws/services/elbv2/elbv2_desync_mitigation_mode/elbv2_desync_mitigation_mode.py b/prowler/providers/aws/services/elbv2/elbv2_desync_mitigation_mode/elbv2_desync_mitigation_mode.py index 5dba8731..e52dc8d7 100644 --- a/prowler/providers/aws/services/elbv2/elbv2_desync_mitigation_mode/elbv2_desync_mitigation_mode.py +++ b/prowler/providers/aws/services/elbv2/elbv2_desync_mitigation_mode/elbv2_desync_mitigation_mode.py @@ -15,9 +15,11 @@ class elbv2_desync_mitigation_mode(Check): report.status = "PASS" report.status_extended = f"ELBv2 ALB {lb.name} is configured with correct desync mitigation mode." if lb.desync_mitigation_mode == "monitor": - report.status = "FAIL" - report.status_extended = f"ELBv2 ALB {lb.name} does not have desync mitigation mode set as defensive or strictest." - + if lb.drop_invalid_header_fields == "false": + report.status = "FAIL" + report.status_extended = f"ELBv2 ALB {lb.name} does not have desync mitigation mode set as defensive or strictest and is not dropping invalid header fields" + elif lb.drop_invalid_header_fields == "true": + report.status_extended = f"ELBv2 ALB {lb.name} does not have desync mitigation mode set as defensive or strictest but is dropping invalid header fields" findings.append(report) return findings diff --git a/prowler/providers/aws/services/elbv2/elbv2_request_smugling/__init__.py b/prowler/providers/aws/services/elbv2/elbv2_request_smugling/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/prowler/providers/aws/services/elbv2/elbv2_request_smugling/elbv2_request_smugling.metadata.json b/prowler/providers/aws/services/elbv2/elbv2_request_smugling/elbv2_request_smugling.metadata.json deleted file mode 100644 index 39b259cf..00000000 --- a/prowler/providers/aws/services/elbv2/elbv2_request_smugling/elbv2_request_smugling.metadata.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "Provider": "aws", - "CheckID": "elbv2_request_smugling", - "CheckTitle": "Check if Application Load Balancer is dropping invalid packets to prevent header based HTTP request smuggling.", - "CheckType": [ - "Data Protection" - ], - "ServiceName": "elbv2", - "SubServiceName": "", - "ResourceIdTemplate": "arn:partition:service:region:account-id:resource-id", - "Severity": "medium", - "ResourceType": "AwsElasticLoadBalancingV2LoadBalancer", - "Description": "Check if Application Load Balancer is dropping invalid packets to prevent header based HTTP request smuggling.", - "Risk": "ALB can be target of actors sending bad HTTP headers.", - "RelatedUrl": "", - "Remediation": { - "Code": { - "CLI": "aws elbv2 modify-load-balancer-attributes --load-balancer-arn --attributes Key=routing.http.drop_invalid_header_fields.enabled,Value=true", - "NativeIaC": "", - "Other": "https://www.trendmicro.com/cloudoneconformity/knowledge-base/aws/ELBv2/drop-invalid-header-fields-enabled.html", - "Terraform": "https://docs.bridgecrew.io/docs/ensure-that-alb-drops-http-headers#terraform" - }, - "Recommendation": { - "Text": "Ensure Application Load Balancer is configured for HTTP headers with header fields that are not valid are removed by the load balancer (true).", - "Url": "https://docs.aws.amazon.com/elasticloadbalancing/latest/application/application-load-balancers.html#deletion-protection" - } - }, - "Categories": [], - "DependsOn": [], - "RelatedTo": [], - "Notes": "" -} diff --git a/prowler/providers/aws/services/elbv2/elbv2_request_smugling/elbv2_request_smugling.py b/prowler/providers/aws/services/elbv2/elbv2_request_smugling/elbv2_request_smugling.py deleted file mode 100644 index 263c408b..00000000 --- a/prowler/providers/aws/services/elbv2/elbv2_request_smugling/elbv2_request_smugling.py +++ /dev/null @@ -1,27 +0,0 @@ -from prowler.lib.check.models import Check, Check_Report_AWS -from prowler.providers.aws.services.elbv2.elbv2_client import elbv2_client - - -class elbv2_request_smugling(Check): - def execute(self): - findings = [] - for lb in elbv2_client.loadbalancersv2: - if lb.type == "application": - report = Check_Report_AWS(self.metadata()) - report.region = lb.region - report.resource_id = lb.name - report.resource_arn = lb.arn - report.resource_tags = lb.tags - report.status = "FAIL" - report.status_extended = ( - f"ELBv2 ALB {lb.name} is not dropping invalid header fields." - ) - if lb.drop_invalid_header_fields == "true": - report.status = "PASS" - report.status_extended = ( - f"ELBv2 ALB {lb.name} is dropping invalid header fields." - ) - - findings.append(report) - - return findings diff --git a/tests/providers/aws/services/elbv2/elbv2_desync_mitigation_mode/elbv2_desync_mitigation_mode_test.py b/tests/providers/aws/services/elbv2/elbv2_desync_mitigation_mode/elbv2_desync_mitigation_mode_test.py index ff213233..cbdbcdf9 100644 --- a/tests/providers/aws/services/elbv2/elbv2_desync_mitigation_mode/elbv2_desync_mitigation_mode_test.py +++ b/tests/providers/aws/services/elbv2/elbv2_desync_mitigation_mode/elbv2_desync_mitigation_mode_test.py @@ -11,7 +11,6 @@ AWS_ACCOUNT_NUMBER = "123456789012" class Test_elbv2_desync_mitigation_mode: @mock_elbv2 def test_elb_no_balancers(self): - from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info from prowler.providers.aws.services.elbv2.elbv2_service import ELBv2 @@ -33,7 +32,7 @@ class Test_elbv2_desync_mitigation_mode: @mock_ec2 @mock_elbv2 - def test_elbv2_without_desync_mitigation_mode(self): + def test_elbv2_without_desync_mitigation_mode_and_not_dropping_headers(self): conn = client("elbv2", region_name=AWS_REGION) ec2 = resource("ec2", region_name=AWS_REGION) @@ -60,6 +59,10 @@ class Test_elbv2_desync_mitigation_mode: LoadBalancerArn=lb["LoadBalancerArn"], Attributes=[ {"Key": "routing.http.desync_mitigation_mode", "Value": "monitor"}, + { + "Key": "routing.http.drop_invalid_header_fields.enabled", + "Value": "false", + }, ], ) @@ -82,7 +85,68 @@ class Test_elbv2_desync_mitigation_mode: assert len(result) == 1 assert result[0].status == "FAIL" assert search( - "does not have desync mitigation mode set as defensive or strictest", + "does not have desync mitigation mode set as defensive or strictest and is not dropping invalid header fields", + result[0].status_extended, + ) + assert result[0].resource_id == "my-lb" + assert result[0].resource_arn == lb["LoadBalancerArn"] + + @mock_ec2 + @mock_elbv2 + def test_elbv2_without_desync_mitigation_mode_but_dropping_headers(self): + conn = client("elbv2", region_name=AWS_REGION) + ec2 = resource("ec2", region_name=AWS_REGION) + + security_group = ec2.create_security_group( + GroupName="a-security-group", Description="First One" + ) + vpc = ec2.create_vpc(CidrBlock="172.28.7.0/24", InstanceTenancy="default") + subnet1 = ec2.create_subnet( + VpcId=vpc.id, CidrBlock="172.28.7.192/26", AvailabilityZone=f"{AWS_REGION}a" + ) + subnet2 = ec2.create_subnet( + VpcId=vpc.id, CidrBlock="172.28.7.0/26", AvailabilityZone=f"{AWS_REGION}b" + ) + + lb = conn.create_load_balancer( + Name="my-lb", + Subnets=[subnet1.id, subnet2.id], + SecurityGroups=[security_group.id], + Scheme="internal", + Type="application", + )["LoadBalancers"][0] + + conn.modify_load_balancer_attributes( + LoadBalancerArn=lb["LoadBalancerArn"], + Attributes=[ + {"Key": "routing.http.desync_mitigation_mode", "Value": "monitor"}, + { + "Key": "routing.http.drop_invalid_header_fields.enabled", + "Value": "true", + }, + ], + ) + + from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info + from prowler.providers.aws.services.elbv2.elbv2_service import ELBv2 + + current_audit_info.audited_partition = "aws" + + with mock.patch( + "prowler.providers.aws.services.elbv2.elbv2_desync_mitigation_mode.elbv2_desync_mitigation_mode.elbv2_client", + new=ELBv2(current_audit_info), + ): + from prowler.providers.aws.services.elbv2.elbv2_desync_mitigation_mode.elbv2_desync_mitigation_mode import ( + elbv2_desync_mitigation_mode, + ) + + check = elbv2_desync_mitigation_mode() + result = check.execute() + + assert len(result) == 1 + assert result[0].status == "PASS" + assert search( + "does not have desync mitigation mode set as defensive or strictest but is dropping invalid header fields", result[0].status_extended, ) assert result[0].resource_id == "my-lb" diff --git a/tests/providers/aws/services/elbv2/elbv2_internet_facing/elbv2_internet_facing_test.py b/tests/providers/aws/services/elbv2/elbv2_internet_facing/elbv2_internet_facing_test.py index e2871c01..08315284 100644 --- a/tests/providers/aws/services/elbv2/elbv2_internet_facing/elbv2_internet_facing_test.py +++ b/tests/providers/aws/services/elbv2/elbv2_internet_facing/elbv2_internet_facing_test.py @@ -8,10 +8,9 @@ AWS_REGION = "eu-west-1" AWS_ACCOUNT_NUMBER = "123456789012" -class Test_elbv2_request_smugling: +class Test_elbv2_internet_facing: @mock_elbv2 def test_elb_no_balancers(self): - from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info from prowler.providers.aws.services.elbv2.elbv2_service import ELBv2 diff --git a/tests/providers/aws/services/elbv2/elbv2_request_smugling/elbv2_request_smugling_test.py b/tests/providers/aws/services/elbv2/elbv2_request_smugling/elbv2_request_smugling_test.py deleted file mode 100644 index 1cd6acee..00000000 --- a/tests/providers/aws/services/elbv2/elbv2_request_smugling/elbv2_request_smugling_test.py +++ /dev/null @@ -1,151 +0,0 @@ -from re import search -from unittest import mock - -from boto3 import client, resource -from moto import mock_ec2, mock_elbv2 - -AWS_REGION = "eu-west-1" -AWS_ACCOUNT_NUMBER = "123456789012" - - -class Test_elbv2_request_smugling: - @mock_elbv2 - def test_elb_no_balancers(self): - - from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info - from prowler.providers.aws.services.elbv2.elbv2_service import ELBv2 - - current_audit_info.audited_partition = "aws" - - with mock.patch( - "prowler.providers.aws.services.elbv2.elbv2_request_smugling.elbv2_request_smugling.elbv2_client", - new=ELBv2(current_audit_info), - ): - # Test Check - from prowler.providers.aws.services.elbv2.elbv2_request_smugling.elbv2_request_smugling import ( - elbv2_request_smugling, - ) - - check = elbv2_request_smugling() - result = check.execute() - - assert len(result) == 0 - - @mock_ec2 - @mock_elbv2 - def test_elbv2_without_dropping(self): - conn = client("elbv2", region_name=AWS_REGION) - ec2 = resource("ec2", region_name=AWS_REGION) - - security_group = ec2.create_security_group( - GroupName="a-security-group", Description="First One" - ) - vpc = ec2.create_vpc(CidrBlock="172.28.7.0/24", InstanceTenancy="default") - subnet1 = ec2.create_subnet( - VpcId=vpc.id, CidrBlock="172.28.7.192/26", AvailabilityZone=f"{AWS_REGION}a" - ) - subnet2 = ec2.create_subnet( - VpcId=vpc.id, CidrBlock="172.28.7.0/26", AvailabilityZone=f"{AWS_REGION}b" - ) - - lb = conn.create_load_balancer( - Name="my-lb", - Subnets=[subnet1.id, subnet2.id], - SecurityGroups=[security_group.id], - Scheme="internal", - Type="application", - )["LoadBalancers"][0] - - conn.modify_load_balancer_attributes( - LoadBalancerArn=lb["LoadBalancerArn"], - Attributes=[ - { - "Key": "routing.http.drop_invalid_header_fields.enabled", - "Value": "false", - }, - ], - ) - - from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info - from prowler.providers.aws.services.elbv2.elbv2_service import ELBv2 - - current_audit_info.audited_partition = "aws" - - with mock.patch( - "prowler.providers.aws.services.elbv2.elbv2_request_smugling.elbv2_request_smugling.elbv2_client", - new=ELBv2(current_audit_info), - ): - from prowler.providers.aws.services.elbv2.elbv2_request_smugling.elbv2_request_smugling import ( - elbv2_request_smugling, - ) - - check = elbv2_request_smugling() - result = check.execute() - - assert len(result) == 1 - assert result[0].status == "FAIL" - assert search( - "is not dropping invalid header fields", - result[0].status_extended, - ) - assert result[0].resource_id == "my-lb" - assert result[0].resource_arn == lb["LoadBalancerArn"] - - @mock_ec2 - @mock_elbv2 - def test_elbv2_with_dropping(self): - conn = client("elbv2", region_name=AWS_REGION) - ec2 = resource("ec2", region_name=AWS_REGION) - - security_group = ec2.create_security_group( - GroupName="a-security-group", Description="First One" - ) - vpc = ec2.create_vpc(CidrBlock="172.28.7.0/24", InstanceTenancy="default") - subnet1 = ec2.create_subnet( - VpcId=vpc.id, CidrBlock="172.28.7.192/26", AvailabilityZone=f"{AWS_REGION}a" - ) - subnet2 = ec2.create_subnet( - VpcId=vpc.id, CidrBlock="172.28.7.0/26", AvailabilityZone=f"{AWS_REGION}b" - ) - - lb = conn.create_load_balancer( - Name="my-lb", - Subnets=[subnet1.id, subnet2.id], - SecurityGroups=[security_group.id], - Scheme="internal", - )["LoadBalancers"][0] - - conn.modify_load_balancer_attributes( - LoadBalancerArn=lb["LoadBalancerArn"], - Attributes=[ - { - "Key": "routing.http.drop_invalid_header_fields.enabled", - "Value": "true", - }, - ], - ) - - from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info - from prowler.providers.aws.services.elbv2.elbv2_service import ELBv2 - - current_audit_info.audited_partition = "aws" - - with mock.patch( - "prowler.providers.aws.services.elbv2.elbv2_request_smugling.elbv2_request_smugling.elbv2_client", - new=ELBv2(current_audit_info), - ): - from prowler.providers.aws.services.elbv2.elbv2_request_smugling.elbv2_request_smugling import ( - elbv2_request_smugling, - ) - - check = elbv2_request_smugling() - result = check.execute() - - assert len(result) == 1 - assert result[0].status == "PASS" - assert search( - "is dropping invalid header fields", - result[0].status_extended, - ) - assert result[0].resource_id == "my-lb" - assert result[0].resource_arn == lb["LoadBalancerArn"]