From 62081cb399947f3d0131987f71209f80579dff2a Mon Sep 17 00:00:00 2001 From: Sergio Garcia <38561120+sergargar@users.noreply.github.com> Date: Thu, 17 Nov 2022 22:34:56 +0100 Subject: [PATCH] feat(ec2): add extra7124 (#1500) Co-authored-by: sergargar --- .../ec2_instance_managed_by_ssm/__init__.py | 0 .../ec2_instance_managed_by_ssm.metadata.json | 35 +++++++++++++++++++ .../ec2_instance_managed_by_ssm.py | 26 ++++++++++++++ .../ec2_instance_public_ip.metadata.json | 2 +- ...allow_ingress_from_internet_to_any_port.py | 2 +- ...om_internet_to_port_mongodb_27017_27018.py | 4 ++- ...ess_from_internet_to_tcp_ftp_port_20_21.py | 4 ++- ...ow_ingress_from_internet_to_tcp_port_22.py | 4 ++- ..._ingress_from_internet_to_tcp_port_3389.py | 4 ++- ...et_to_tcp_port_cassandra_7199_9160_8888.py | 4 ++- ...ort_elasticsearch_kibana_9200_9300_5601.py | 4 ++- ...ss_from_internet_to_tcp_port_kafka_9092.py | 4 ++- ...om_internet_to_tcp_port_memcached_11211.py | 4 ++- ...ss_from_internet_to_tcp_port_mysql_3306.py | 4 ++- ...m_internet_to_tcp_port_oracle_1521_2483.py | 4 ++- ...from_internet_to_tcp_port_postgres_5432.py | 4 ++- ...ss_from_internet_to_tcp_port_redis_6379.py | 4 ++- ...ternet_to_tcp_port_sql_server_1433_1434.py | 4 ++- ...ess_from_internet_to_tcp_port_telnet_23.py | 4 ++- ..._securitygroup_default_restrict_traffic.py | 2 +- providers/aws/services/ec2/ec2_service.py | 1 - .../aws/services/ec2/lib/security_groups.py | 20 +++++++---- providers/aws/services/ssm/ssm_service.py | 29 +++++++++++++++ 23 files changed, 148 insertions(+), 25 deletions(-) create mode 100644 providers/aws/services/ec2/ec2_instance_managed_by_ssm/__init__.py create mode 100644 providers/aws/services/ec2/ec2_instance_managed_by_ssm/ec2_instance_managed_by_ssm.metadata.json create mode 100644 providers/aws/services/ec2/ec2_instance_managed_by_ssm/ec2_instance_managed_by_ssm.py diff --git a/providers/aws/services/ec2/ec2_instance_managed_by_ssm/__init__.py b/providers/aws/services/ec2/ec2_instance_managed_by_ssm/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/providers/aws/services/ec2/ec2_instance_managed_by_ssm/ec2_instance_managed_by_ssm.metadata.json b/providers/aws/services/ec2/ec2_instance_managed_by_ssm/ec2_instance_managed_by_ssm.metadata.json new file mode 100644 index 00000000..8c6e24b7 --- /dev/null +++ b/providers/aws/services/ec2/ec2_instance_managed_by_ssm/ec2_instance_managed_by_ssm.metadata.json @@ -0,0 +1,35 @@ +{ + "Provider": "aws", + "CheckID": "ec2_instance_managed_by_ssm", + "CheckTitle": "Check if EC2 instances are managed by Systems Manager.", + "CheckType": ["Infrastructure Security"], + "ServiceName": "ec2", + "SubServiceName": "instance", + "ResourceIdTemplate": "arn:partition:service:region:account-id:resource-id", + "Severity": "medium", + "ResourceType": "AwsEc2Instance", + "Description": "Check if EC2 instances are managed by Systems Manager.", + "Risk": "AWS Config provides AWS Managed Rules, which are predefined, customizable rules that AWS Config uses to evaluate whether your AWS resource configurations comply with common best practices.", + "RelatedUrl": "", + "Remediation": { + "Code": { + "CLI": "", + "NativeIaC": "", + "Other": "https://www.trendmicro.com/cloudoneconformity/knowledge-base/aws/SSM/ssm-managed-instances.html", + "Terraform": "" + }, + "Recommendation": { + "Text": "Verify and apply Systems Manager Prerequisites.", + "Url": "https://docs.aws.amazon.com/systems-manager/latest/userguide/managed_instances.html" + } + }, + "Categories": [], + "Tags": { + "Tag1Key": "value", + "Tag2Key": "value" + }, + "DependsOn": [], + "RelatedTo": [], + "Notes": "", + "Compliance": [] +} diff --git a/providers/aws/services/ec2/ec2_instance_managed_by_ssm/ec2_instance_managed_by_ssm.py b/providers/aws/services/ec2/ec2_instance_managed_by_ssm/ec2_instance_managed_by_ssm.py new file mode 100644 index 00000000..e2387ccb --- /dev/null +++ b/providers/aws/services/ec2/ec2_instance_managed_by_ssm/ec2_instance_managed_by_ssm.py @@ -0,0 +1,26 @@ +from lib.check.models import Check, Check_Report +from providers.aws.services.ec2.ec2_client import ec2_client +from providers.aws.services.ssm.ssm_client import ssm_client + + +class ec2_instance_managed_by_ssm(Check): + def execute(self): + findings = [] + for instance in ec2_client.instances: + report = Check_Report(self.metadata) + report.region = instance.region + if not ssm_client.managed_instances.get(instance.id): + report.status = "FAIL" + report.status_extended = ( + f"EC2 Instance {instance.id} is not managed by Systems Manager." + ) + report.resource_id = instance.id + else: + report.status = "PASS" + report.status_extended = ( + f"EC2 Instance {instance.id} is managed by Systems Manager." + ) + report.resource_id = instance.id + findings.append(report) + + return findings diff --git a/providers/aws/services/ec2/ec2_instance_public_ip/ec2_instance_public_ip.metadata.json b/providers/aws/services/ec2/ec2_instance_public_ip/ec2_instance_public_ip.metadata.json index 191a7c49..08d0265b 100644 --- a/providers/aws/services/ec2/ec2_instance_public_ip/ec2_instance_public_ip.metadata.json +++ b/providers/aws/services/ec2/ec2_instance_public_ip/ec2_instance_public_ip.metadata.json @@ -7,7 +7,7 @@ "SubServiceName": "instance", "ResourceIdTemplate": "arn:partition:service:region:account-id:resource-id", "Severity": "medium", - "ResourceType": "AwsEc2SecurityGroup", + "ResourceType": "AwsEc2Instance", "Description": "Check for EC2 Instances with Public IP.", "Risk": "Exposing an EC2 directly to internet increases the attack surface and therefore the risk of compromise.", "RelatedUrl": "", diff --git a/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_any_port/ec2_securitygroup_allow_ingress_from_internet_to_any_port.py b/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_any_port/ec2_securitygroup_allow_ingress_from_internet_to_any_port.py index 1f2169cb..422730e8 100644 --- a/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_any_port/ec2_securitygroup_allow_ingress_from_internet_to_any_port.py +++ b/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_any_port/ec2_securitygroup_allow_ingress_from_internet_to_any_port.py @@ -14,7 +14,7 @@ class ec2_securitygroup_allow_ingress_from_internet_to_any_port(Check): report.resource_id = security_group.id # Loop through every security group's ingress rule and check it for ingress_rule in security_group.ingress_rules: - if check_security_group(ingress_rule, "-1"): + if check_security_group(ingress_rule, "-1", any_address=True): report.status = "FAIL" report.status_extended = f"Security group {security_group.name} ({security_group.id}) has all ports open to the Internet." break diff --git a/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_port_mongodb_27017_27018/ec2_securitygroup_allow_ingress_from_internet_to_port_mongodb_27017_27018.py b/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_port_mongodb_27017_27018/ec2_securitygroup_allow_ingress_from_internet_to_port_mongodb_27017_27018.py index bc1d094e..c8a84372 100644 --- a/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_port_mongodb_27017_27018/ec2_securitygroup_allow_ingress_from_internet_to_port_mongodb_27017_27018.py +++ b/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_port_mongodb_27017_27018/ec2_securitygroup_allow_ingress_from_internet_to_port_mongodb_27017_27018.py @@ -15,7 +15,9 @@ class ec2_securitygroup_allow_ingress_from_internet_to_port_mongodb_27017_27018( report.status_extended = f"Security group {security_group.name} ({security_group.id}) has not MongoDB ports 27017 and 27018 open to the Internet." # Loop through every security group's ingress rule and check it for ingress_rule in security_group.ingress_rules: - if check_security_group(ingress_rule, "tcp", check_ports): + if check_security_group( + ingress_rule, "tcp", check_ports, any_address=True + ): report.status = "FAIL" report.status_extended = f"Security group {security_group.name} ({security_group.id}) has MongoDB ports 27017 and 27018 open to the Internet." break diff --git a/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_ftp_port_20_21/ec2_securitygroup_allow_ingress_from_internet_to_tcp_ftp_port_20_21.py b/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_ftp_port_20_21/ec2_securitygroup_allow_ingress_from_internet_to_tcp_ftp_port_20_21.py index 0edd1bce..bf88ed18 100644 --- a/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_ftp_port_20_21/ec2_securitygroup_allow_ingress_from_internet_to_tcp_ftp_port_20_21.py +++ b/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_ftp_port_20_21/ec2_securitygroup_allow_ingress_from_internet_to_tcp_ftp_port_20_21.py @@ -15,7 +15,9 @@ class ec2_securitygroup_allow_ingress_from_internet_to_tcp_ftp_port_20_21(Check) report.resource_id = security_group.id # Loop through every security group's ingress rule and check it for ingress_rule in security_group.ingress_rules: - if check_security_group(ingress_rule, "tcp", check_ports): + if check_security_group( + ingress_rule, "tcp", check_ports, any_address=True + ): report.status = "FAIL" report.status_extended = f"Security group {security_group.name} ({security_group.id}) has FTP ports 20 and 21 open to the Internet." break diff --git a/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_22/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_22.py b/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_22/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_22.py index dbc5ba9b..23a6aae7 100644 --- a/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_22/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_22.py +++ b/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_22/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_22.py @@ -15,7 +15,9 @@ class ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_22(Check): report.resource_id = security_group.id # Loop through every security group's ingress rule and check it for ingress_rule in security_group.ingress_rules: - if check_security_group(ingress_rule, "tcp", check_ports): + if check_security_group( + ingress_rule, "tcp", check_ports, any_address=True + ): report.status = "FAIL" report.status_extended = f"Security group {security_group.name} ({security_group.id}) has SSH port 22 open to the Internet." break diff --git a/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_3389/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_3389.py b/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_3389/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_3389.py index 31ad88b7..e75963fa 100644 --- a/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_3389/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_3389.py +++ b/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_3389/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_3389.py @@ -15,7 +15,9 @@ class ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_3389(Check): report.resource_id = security_group.id # Loop through every security group's ingress rule and check it for ingress_rule in security_group.ingress_rules: - if check_security_group(ingress_rule, "tcp", check_ports): + if check_security_group( + ingress_rule, "tcp", check_ports, any_address=True + ): report.status = "FAIL" report.status_extended = f"Security group {security_group.name} ({security_group.id}) has Microsoft RDP port 3389 open to the Internet." break diff --git a/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_cassandra_7199_9160_8888/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_cassandra_7199_9160_8888.py b/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_cassandra_7199_9160_8888/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_cassandra_7199_9160_8888.py index 8ad081a0..6a093a43 100644 --- a/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_cassandra_7199_9160_8888/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_cassandra_7199_9160_8888.py +++ b/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_cassandra_7199_9160_8888/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_cassandra_7199_9160_8888.py @@ -17,7 +17,9 @@ class ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_cassandra_7199_9 report.status_extended = f"Security group {security_group.name} ({security_group.id}) has not Casandra ports 7199, 8888 and 9160 open to the Internet." # Loop through every security group's ingress rule and check it for ingress_rule in security_group.ingress_rules: - if check_security_group(ingress_rule, "tcp", check_ports): + if check_security_group( + ingress_rule, "tcp", check_ports, any_address=True + ): report.status = "FAIL" report.status_extended = f"Security group {security_group.name} ({security_group.id}) has Casandra ports 7199, 8888 and 9160 open to the Internet." break diff --git a/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_elasticsearch_kibana_9200_9300_5601/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_elasticsearch_kibana_9200_9300_5601.py b/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_elasticsearch_kibana_9200_9300_5601/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_elasticsearch_kibana_9200_9300_5601.py index 69c30ce1..0572319c 100644 --- a/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_elasticsearch_kibana_9200_9300_5601/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_elasticsearch_kibana_9200_9300_5601.py +++ b/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_elasticsearch_kibana_9200_9300_5601/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_elasticsearch_kibana_9200_9300_5601.py @@ -17,7 +17,9 @@ class ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_elasticsearch_ki report.status_extended = f"Security group {security_group.name} ({security_group.id}) has not Elasticsearch/Kibana ports 9200, 9300 and 5601 open to the Internet." # Loop through every security group's ingress rule and check it for ingress_rule in security_group.ingress_rules: - if check_security_group(ingress_rule, "tcp", check_ports): + if check_security_group( + ingress_rule, "tcp", check_ports, any_address=True + ): report.status = "FAIL" report.status_extended = f"Security group {security_group.name} ({security_group.id}) has Elasticsearch/Kibana ports 9200, 9300 and 5601 open to the Internet." break diff --git a/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_kafka_9092/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_kafka_9092.py b/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_kafka_9092/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_kafka_9092.py index d18ca2b9..8b34d0ae 100644 --- a/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_kafka_9092/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_kafka_9092.py +++ b/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_kafka_9092/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_kafka_9092.py @@ -15,7 +15,9 @@ class ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_kafka_9092(Check report.status_extended = f"Security group {security_group.name} ({security_group.id}) has not Kafka port 9092 open to the Internet." # Loop through every security group's ingress rule and check it for ingress_rule in security_group.ingress_rules: - if check_security_group(ingress_rule, "tcp", check_ports): + if check_security_group( + ingress_rule, "tcp", check_ports, any_address=True + ): report.status = "FAIL" report.status_extended = f"Security group {security_group.name} ({security_group.id}) has Kafka port 9092 open to the Internet." break diff --git a/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_memcached_11211/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_memcached_11211.py b/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_memcached_11211/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_memcached_11211.py index 11c5220f..6884fc8a 100644 --- a/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_memcached_11211/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_memcached_11211.py +++ b/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_memcached_11211/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_memcached_11211.py @@ -15,7 +15,9 @@ class ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_memcached_11211( report.status_extended = f"Security group {security_group.name} ({security_group.id}) has not Memcached port 11211 open to the Internet." # Loop through every security group's ingress rule and check it for ingress_rule in security_group.ingress_rules: - if check_security_group(ingress_rule, "tcp", check_ports): + if check_security_group( + ingress_rule, "tcp", check_ports, any_address=True + ): report.status = "FAIL" report.status_extended = f"Security group {security_group.name} ({security_group.id}) has Memcached port 11211 open to the Internet." break diff --git a/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_mysql_3306/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_mysql_3306.py b/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_mysql_3306/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_mysql_3306.py index 7d9dbaea..e04f1dbb 100644 --- a/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_mysql_3306/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_mysql_3306.py +++ b/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_mysql_3306/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_mysql_3306.py @@ -15,7 +15,9 @@ class ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_mysql_3306(Check report.status_extended = f"Security group {security_group.name} ({security_group.id}) has not MySQL port 3306 open to the Internet." # Loop through every security group's ingress rule and check it for ingress_rule in security_group.ingress_rules: - if check_security_group(ingress_rule, "tcp", check_ports): + if check_security_group( + ingress_rule, "tcp", check_ports, any_address=True + ): report.status = "FAIL" report.status_extended = f"Security group {security_group.name} ({security_group.id}) has MySQL port 3306 open to the Internet." report.resource_id = security_group.id diff --git a/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_oracle_1521_2483/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_oracle_1521_2483.py b/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_oracle_1521_2483/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_oracle_1521_2483.py index 6edeb228..6085c877 100644 --- a/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_oracle_1521_2483/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_oracle_1521_2483.py +++ b/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_oracle_1521_2483/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_oracle_1521_2483.py @@ -15,7 +15,9 @@ class ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_oracle_1521_2483 report.status_extended = f"Security group {security_group.name} ({security_group.id}) has not Oracle ports 1521 and 2483 open to the Internet." # Loop through every security group's ingress rule and check it for ingress_rule in security_group.ingress_rules: - if check_security_group(ingress_rule, "tcp", check_ports): + if check_security_group( + ingress_rule, "tcp", check_ports, any_address=True + ): report.status = "FAIL" report.status_extended = f"Security group {security_group.name} ({security_group.id}) has Oracle ports 1521 and 2483 open to the Internet." break diff --git a/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_postgres_5432/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_postgres_5432.py b/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_postgres_5432/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_postgres_5432.py index f7638595..e941e2d7 100644 --- a/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_postgres_5432/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_postgres_5432.py +++ b/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_postgres_5432/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_postgres_5432.py @@ -15,7 +15,9 @@ class ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_postgres_5432(Ch report.status_extended = f"Security group {security_group.name} ({security_group.id}) has not Postgres port 5432 open to the Internet." # Loop through every security group's ingress rule and check it for ingress_rule in security_group.ingress_rules: - if check_security_group(ingress_rule, "tcp", check_ports): + if check_security_group( + ingress_rule, "tcp", check_ports, any_address=True + ): report.status = "FAIL" report.status_extended = f"Security group {security_group.name} ({security_group.id}) has Postgres port 5432 open to the Internet." break diff --git a/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_redis_6379/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_redis_6379.py b/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_redis_6379/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_redis_6379.py index 70202ca5..bb7612ed 100644 --- a/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_redis_6379/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_redis_6379.py +++ b/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_redis_6379/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_redis_6379.py @@ -15,7 +15,9 @@ class ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_redis_6379(Check report.status_extended = f"Security group {security_group.name} ({security_group.id}) has not Redis port 6379 open to the Internet." # Loop through every security group's ingress rule and check it for ingress_rule in security_group.ingress_rules: - if check_security_group(ingress_rule, "tcp", check_ports): + if check_security_group( + ingress_rule, "tcp", check_ports, any_address=True + ): report.status = "FAIL" report.status_extended = f"Security group {security_group.name} ({security_group.id}) has Redis port 6379 open to the Internet." break diff --git a/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_sql_server_1433_1434/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_sql_server_1433_1434.py b/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_sql_server_1433_1434/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_sql_server_1433_1434.py index a0a7eb3c..3c0fbdaa 100644 --- a/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_sql_server_1433_1434/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_sql_server_1433_1434.py +++ b/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_sql_server_1433_1434/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_sql_server_1433_1434.py @@ -17,7 +17,9 @@ class ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_sql_server_1433_ report.status_extended = f"Security group {security_group.name} ({security_group.id}) has not Microsoft SQL Server ports 1433 and 1434 open to the Internet." # Loop through every security group's ingress rule and check it for ingress_rule in security_group.ingress_rules: - if check_security_group(ingress_rule, "tcp", check_ports): + if check_security_group( + ingress_rule, "tcp", check_ports, any_address=True + ): report.status = "FAIL" report.status_extended = f"Security group {security_group.name} ({security_group.id}) has Microsoft SQL Server ports 1433 and 1434 open to the Internet." break diff --git a/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_telnet_23/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_telnet_23.py b/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_telnet_23/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_telnet_23.py index 38b6bac1..4a504686 100644 --- a/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_telnet_23/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_telnet_23.py +++ b/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_telnet_23/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_telnet_23.py @@ -15,7 +15,9 @@ class ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_telnet_23(Check) report.status_extended = f"Security group {security_group.name} ({security_group.id}) has not Telnet port 23 open to the Internet." # Loop through every security group's ingress rule and check it for ingress_rule in security_group.ingress_rules: - if check_security_group(ingress_rule, "tcp", check_ports): + if check_security_group( + ingress_rule, "tcp", check_ports, any_address=True + ): report.status = "FAIL" report.status_extended = f"Security group {security_group.name} ({security_group.id}) has Telnet port 23 open to the Internet." break diff --git a/providers/aws/services/ec2/ec2_securitygroup_default_restrict_traffic/ec2_securitygroup_default_restrict_traffic.py b/providers/aws/services/ec2/ec2_securitygroup_default_restrict_traffic/ec2_securitygroup_default_restrict_traffic.py index c6987368..4f5906b7 100644 --- a/providers/aws/services/ec2/ec2_securitygroup_default_restrict_traffic/ec2_securitygroup_default_restrict_traffic.py +++ b/providers/aws/services/ec2/ec2_securitygroup_default_restrict_traffic/ec2_securitygroup_default_restrict_traffic.py @@ -15,7 +15,7 @@ class ec2_securitygroup_default_restrict_traffic(Check): report.status = "PASS" report.status_extended = f"Default Security Group ({security_group.id}) is not open to the Internet." for ingress_rule in security_group.ingress_rules: - if check_security_group(ingress_rule, "-1"): + if check_security_group(ingress_rule, "-1", any_address=True): report.status = "FAIL" report.status_extended = f"Default Security Group ({security_group.id}) is open to the Internet." break diff --git a/providers/aws/services/ec2/ec2_service.py b/providers/aws/services/ec2/ec2_service.py index fab2b272..6d5fbd60 100644 --- a/providers/aws/services/ec2/ec2_service.py +++ b/providers/aws/services/ec2/ec2_service.py @@ -255,7 +255,6 @@ class EC2: logger.info("EC2 - Describing Elastic IPs...") try: for address in regional_client.describe_addresses()["Addresses"]: - print(address) public_ip = None association_id = None allocation_id = None diff --git a/providers/aws/services/ec2/lib/security_groups.py b/providers/aws/services/ec2/lib/security_groups.py index 564208e9..57b92000 100644 --- a/providers/aws/services/ec2/lib/security_groups.py +++ b/providers/aws/services/ec2/lib/security_groups.py @@ -3,7 +3,9 @@ from typing import Any ################## Security Groups -def check_security_group(ingress_rule: Any, protocol: str, ports: list = []) -> bool: +def check_security_group( + ingress_rule: Any, protocol: str, ports: list = [], any_address: bool = False +) -> bool: """ Check if the security group ingress rule has public access to the check_ports using the protocol @@ -30,15 +32,17 @@ def check_security_group(ingress_rule: Any, protocol: str, ports: list = []) -> @param ports: List of ports to check. (Default: []) + + @param any_address: If True, only 0.0.0.0/0 will be public and do not search for public addresses. (Default: False) """ # Check for all traffic ingress rules regardless of the protocol if ingress_rule["IpProtocol"] == "-1": for ip_ingress_rule in ingress_rule["IpRanges"]: - if _is_cidr_public(ip_ingress_rule["CidrIp"]): + if _is_cidr_public(ip_ingress_rule["CidrIp"], any_address): return True for ip_ingress_rule in ingress_rule["Ipv6Ranges"]: - if _is_cidr_public(ip_ingress_rule["CidrIp"]): + if _is_cidr_public(ip_ingress_rule["CidrIp"], any_address): return True # Check for specific ports in ingress rules @@ -58,7 +62,7 @@ def check_security_group(ingress_rule: Any, protocol: str, ports: list = []) -> # Test Security Group # IPv4 for ip_ingress_rule in ingress_rule["IpRanges"]: - if _is_cidr_public(ip_ingress_rule["CidrIp"]): + if _is_cidr_public(ip_ingress_rule["CidrIp"], any_address): # If there are input ports to check if ports: for port in ports: @@ -87,11 +91,13 @@ def check_security_group(ingress_rule: Any, protocol: str, ports: list = []) -> return False -def _is_cidr_public(cidr: str) -> bool: +def _is_cidr_public(cidr: str, any_address: bool = False) -> bool: """ Check if an input CIDR is public @param cidr: CIDR 10.22.33.44/8 + + @param any_address: If True, only 0.0.0.0/0 will be public and do not search for public addresses. (Default: False) """ public_IPv4 = "0.0.0.0/0" public_IPv6 = "::/0" @@ -100,5 +106,5 @@ def _is_cidr_public(cidr: str) -> bool: # Issue https://github.com/python/cpython/issues/82836 if cidr in (public_IPv4, public_IPv6): return True - - return ipaddress.ip_network(cidr).is_global + if not any_address: + return ipaddress.ip_network(cidr).is_global diff --git a/providers/aws/services/ssm/ssm_service.py b/providers/aws/services/ssm/ssm_service.py index ba8de6c6..6ee5b054 100644 --- a/providers/aws/services/ssm/ssm_service.py +++ b/providers/aws/services/ssm/ssm_service.py @@ -17,10 +17,12 @@ class SSM: self.regional_clients = generate_regional_clients(self.service, audit_info) self.documents = {} self.compliance_resources = {} + self.managed_instances = {} self.__threading_call__(self.__list_documents__) self.__threading_call__(self.__get_document__) self.__threading_call__(self.__describe_document_permission__) self.__threading_call__(self.__list_resource_compliance_summaries__) + self.__threading_call__(self.__describe_instance_information__) def __get_session__(self): return self.session @@ -125,6 +127,28 @@ class SSM: f" {error}" ) + def __describe_instance_information__(self, regional_client): + logger.info("SSM - Describing Instance Information...") + try: + describe_instance_information_paginator = regional_client.get_paginator( + "describe_instance_information" + ) + for page in describe_instance_information_paginator.paginate(): + for item in page["InstanceInformationList"]: + resource_id = item["InstanceId"] + + self.managed_instances[resource_id] = ManagedInstance( + id=resource_id, + region=regional_client.region, + ) + + except Exception as error: + logger.error( + f"{regional_client.region} --" + f" {error.__class__.__name__}[{error.__traceback__.tb_lineno}]:" + f" {error}" + ) + class ResourceStatus(Enum): COMPLIANT = "COMPLIANT" @@ -142,3 +166,8 @@ class Document(BaseModel): region: str content: dict = None account_owners: list[str] = None + + +class ManagedInstance(BaseModel): + id: str + region: str