From d18b430c16c0a6efd38d5f6d71ecbaa3b3a9f068 Mon Sep 17 00:00:00 2001 From: Sergio Garcia <38561120+sergargar@users.noreply.github.com> Date: Mon, 22 Aug 2022 09:33:43 +0100 Subject: [PATCH] feat(new_checks): add check for ec2 and iam (#1337) * fix(key_error): remove KeyError. * feat(ftp_check): add ec2_securitygroup_allow_ingress_from_internet_to_tcp_ftp_port_20_21 check. * feat(password_check): iam_password_policy_expires_passwords_within_15_days_or_less added. * change days to 90 Co-authored-by: sergargar --- .../__init__.py | 0 ...ternet_to_tcp_ftp_port_20_21.metadata.json | 46 +++++++++++++++++++ ...ess_from_internet_to_tcp_ftp_port_20_21.py | 27 +++++++++++ .../__init__.py | 0 ...words_within_90_days_or_less.metadata.json | 46 +++++++++++++++++++ ...xpires_passwords_within_90_days_or_less.py | 29 ++++++++++++ 6 files changed, 148 insertions(+) create mode 100644 providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_ftp_port_20_21/__init__.py create mode 100644 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.metadata.json create mode 100644 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 create mode 100644 providers/aws/services/iam/iam_password_policy_expires_passwords_within_90_days_or_less/__init__.py create mode 100644 providers/aws/services/iam/iam_password_policy_expires_passwords_within_90_days_or_less/iam_password_policy_expires_passwords_within_90_days_or_less.metadata.json create mode 100644 providers/aws/services/iam/iam_password_policy_expires_passwords_within_90_days_or_less/iam_password_policy_expires_passwords_within_90_days_or_less.py diff --git a/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_ftp_port_20_21/__init__.py b/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_ftp_port_20_21/__init__.py new file mode 100644 index 00000000..e69de29b 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.metadata.json 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.metadata.json new file mode 100644 index 00000000..cc0a3c47 --- /dev/null +++ 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.metadata.json @@ -0,0 +1,46 @@ +{ + "Provider": "aws", + "CheckID": "ec2_securitygroup_allow_ingress_from_internet_to_tcp_ftp_port_20_21", + "CheckTitle": "Ensure no security groups allow ingress from 0.0.0.0/0 or ::/0 to FTP ports 20 or 21.", + "CheckType": "Infrastructure Security", + "ServiceName": "ec2", + "SubServiceName": "securitygroup", + "ResourceIdTemplate": "arn:partition:service:region:account-id:resource-id", + "Severity": "high", + "ResourceType": "AwsEc2SecurityGroup", + "Description": "Ensure no security groups allow ingress from 0.0.0.0/0 or ::/0 to FTP ports 20 or 21.", + "Risk": "If Security groups are not properly configured the attack surface is increased.", + "RelatedUrl": "", + "Remediation": { + "Code": { + "CLI": "", + "NativeIaC": "", + "Other": "", + "Terraform": "" + }, + "Recommendation": { + "Text": "Use a Zero Trust approach. Narrow ingress traffic as much as possible. Consider north-south as well as east-west traffic.", + "Url": "https://docs.aws.amazon.com/vpc/latest/userguide/VPC_SecurityGroups.html" + } + }, + "Categories": [], + "Tags": { + "Tag1Key": "value", + "Tag2Key": "value" + }, + "DependsOn": [], + "RelatedTo": [], + "Notes": "", + "Compliance": [ + { + "Control": [ + "4.1" + ], + "Framework": "CIS-AWS", + "Group": [ + "level2" + ], + "Version": "1.4" + } + ] +} 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 new file mode 100644 index 00000000..45291e95 --- /dev/null +++ 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 @@ -0,0 +1,27 @@ +from lib.check.models import Check, Check_Report +from providers.aws.services.ec2.ec2_service import check_security_group, ec2_client + + +class ec2_securitygroup_allow_ingress_from_internet_to_tcp_ftp_port_20_21(Check): + def execute(self): + findings = [] + check_ports = [20, 21] + for security_group in ec2_client.security_groups: + public = False + report = Check_Report(self.metadata) + report.region = security_group.region + # Loop through every security group's ingress rule and check it + for ingress_rule in security_group.ingress_rules: + public = check_security_group(ingress_rule, "tcp", check_ports) + # Check + if public: + 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." + report.resource_id = security_group.id + else: + report.status = "PASS" + report.status_extended = f"Security group {security_group.name} ({security_group.id}) has not FPT ports 20 and 21 open to the Internet." + report.resource_id = security_group.id + findings.append(report) + + return findings diff --git a/providers/aws/services/iam/iam_password_policy_expires_passwords_within_90_days_or_less/__init__.py b/providers/aws/services/iam/iam_password_policy_expires_passwords_within_90_days_or_less/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/providers/aws/services/iam/iam_password_policy_expires_passwords_within_90_days_or_less/iam_password_policy_expires_passwords_within_90_days_or_less.metadata.json b/providers/aws/services/iam/iam_password_policy_expires_passwords_within_90_days_or_less/iam_password_policy_expires_passwords_within_90_days_or_less.metadata.json new file mode 100644 index 00000000..d8c3458e --- /dev/null +++ b/providers/aws/services/iam/iam_password_policy_expires_passwords_within_90_days_or_less/iam_password_policy_expires_passwords_within_90_days_or_less.metadata.json @@ -0,0 +1,46 @@ +{ + "Provider": "aws", + "CheckID": "iam-password-policy-expires-passwords-within-90-days-or-less", + "CheckTitle": "Ensure IAM password policy expires passwords within 90 days or less", + "CheckType": "Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark", + "ServiceName": "iam", + "SubServiceName": "", + "ResourceIdTemplate": "arn:partition:service:region:account-id:resource-id", + "Severity": "medium", + "ResourceType": "AwsIamPasswordPolicy", + "Description": "Ensure IAM password policy expires passwords within 90 days or less", + "Risk": "Password policies are used to enforce password complexity requirements. IAM password policies can be used to ensure password are comprised of different character sets. It is recommended that the password policy require at least one uppercase letter.", + "RelatedUrl": "", + "Remediation": { + "Code": { + "CLI": "", + "NativeIaC": "", + "Other": "", + "Terraform": "" + }, + "Recommendation": { + "Text": "Ensure Password expiration period (in days): is set to 90 or less.", + "Url": "https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_passwords_account-policy.html" + } + }, + "Categories": [], + "Tags": { + "Tag1Key": "value", + "Tag2Key": "value" + }, + "DependsOn": [], + "RelatedTo": [], + "Notes": "", + "Compliance": [ + { + "Control": [ + "1.11" + ], + "Framework": "CIS-AWS", + "Group": [ + "level1" + ], + "Version": "1.4" + } + ] +} diff --git a/providers/aws/services/iam/iam_password_policy_expires_passwords_within_90_days_or_less/iam_password_policy_expires_passwords_within_90_days_or_less.py b/providers/aws/services/iam/iam_password_policy_expires_passwords_within_90_days_or_less/iam_password_policy_expires_passwords_within_90_days_or_less.py new file mode 100644 index 00000000..52c85d3f --- /dev/null +++ b/providers/aws/services/iam/iam_password_policy_expires_passwords_within_90_days_or_less/iam_password_policy_expires_passwords_within_90_days_or_less.py @@ -0,0 +1,29 @@ +from lib.check.models import Check, Check_Report +from providers.aws.services.iam.iam_service import iam_client + + +class iam_password_policy_expires_passwords_within_90_days_or_less(Check): + def execute(self) -> Check_Report: + findings = [] + report = Check_Report(self.metadata) + report.region = iam_client.region + report.resource_id = "password_policy" + # Check if password policy exists + if iam_client.password_policy: + # Check if password policy expiration exists + if iam_client.password_policy.max_age: + if iam_client.password_policy.max_age < 90: + report.status = "PASS" + report.status_extended = f"Password expiration is set lower than 90 days ({iam_client.password_policy.max_age} days)." + else: + report.status = "FAIL" + report.status_extended = f"Password expiration is set greater than 90 days ({iam_client.password_policy.max_age} days)." + else: + report.status = "FAIL" + report.status_extended = "Password expiration is not set." + else: + report.status = "FAIL" + report.status_extended = "Password policy cannot be found." + findings.append(report) + + return findings