From b27b41a3280e6319f5012ea6f646b4c479aa3835 Mon Sep 17 00:00:00 2001 From: vigneswararaomacharla Date: Wed, 7 Aug 2019 15:24:16 +0530 Subject: [PATCH 1/8] Updated with Insecure SG known ip sources Updated with Insecure SG known ip sources --- deployment/configs/config.json | 3 ++- hammer/library/aws/security_groups.py | 30 ++++++++++++++++++++++++--- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/deployment/configs/config.json b/deployment/configs/config.json index de6db85a..a4f47ebf 100755 --- a/deployment/configs/config.json +++ b/deployment/configs/config.json @@ -75,7 +75,8 @@ "reporting": false, "remediation": false, "remediation_accounts": ["210987654321", "654321210987"], - "remediation_retention_period": 21 + "remediation_retention_period": 21, + "known_ip_sources": ["205.203.150.72/32", "205.203.130.22/32"] }, "user_inactivekeys": { "enabled": true, diff --git a/hammer/library/aws/security_groups.py b/hammer/library/aws/security_groups.py index 814d88aa..c1ba72c3 100755 --- a/hammer/library/aws/security_groups.py +++ b/hammer/library/aws/security_groups.py @@ -8,12 +8,14 @@ from library.utility import jsonDumps from library.aws.s3 import S3Operations from library.aws.utility import convert_tags +from library.config import Config class RestrictionStatus(Enum): Restricted = "restricted" OpenCompletely = "open_completely" OpenPartly = "open_partly" + SafeIP = "safe_ips" class SecurityGroupOperations: @@ -372,6 +374,19 @@ def __str__(self): perms = ", ".join([str(perm) for perm in self.permissions]) return f"{self.__class__.__name__}(Name={self.name}, Id={self.id}, Permissions=[{perms}])" + def validate_known_ip_soource(self, cidr): + """ + + :param cidr: ip address + :return: boolean + """ + config = Config() + known_ip_sources = config.sg.known_ip_sources + for ip_address in known_ip_sources: + if ip_address == cidr: + return True + return False + def restriction_status(self, cidr): """ Check restriction status of cidr @@ -380,11 +395,19 @@ def restriction_status(self, cidr): :return: RestrictionStatus with check result """ + is_known_ip = self.validate_ip_soource(cidr) + if is_known_ip: + status = RestrictionStatus.Restricted + status = RestrictionStatus.Restricted if cidr.endswith("/0"): status = RestrictionStatus.OpenCompletely elif ipaddress.ip_network(cidr).is_global: status = RestrictionStatus.OpenPartly + + elif is_known_ip: + status = RestrictionStatus.SafeIP + logging.debug(f"Checked '{cidr}' - '{status.value}'") return status @@ -406,10 +429,11 @@ def check(self, restricted_ports): logging.debug(f"Checking '{perm.protocol}' '{perm.from_port}-{perm.to_port}' ports for {ip_range}") # first condition - CIDR is Global/Public status = self.restriction_status(ip_range.cidr) - if status == RestrictionStatus.Restricted: - logging.debug(f"Skipping restricted '{ip_range}'") + if status in (RestrictionStatus.Restricted, RestrictionStatus.SafeIP): + logging.debug(f"Skipping restricted/safe IP address '{ip_range}'") continue - # second - check if ports from `restricted_ports` list has intersection with ports from FromPort..ToPort range + # second - check if ports from `restricted_ports` list has intersection with ports from FromPort.. + # ToPort range if perm.from_port is None or perm.to_port is None: logging.debug(f"Marking world-wide open all ports from '{ip_range}'") ip_range.status = status From e970bb175e70531ca7c965767962dd78fd03a1ad Mon Sep 17 00:00:00 2001 From: vigneswararaomacharla Date: Wed, 7 Aug 2019 16:33:58 +0530 Subject: [PATCH 2/8] Updated with SG known IP sources. Updated with SG known IP sources. --- hammer/library/aws/security_groups.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/hammer/library/aws/security_groups.py b/hammer/library/aws/security_groups.py index c1ba72c3..2bb685db 100755 --- a/hammer/library/aws/security_groups.py +++ b/hammer/library/aws/security_groups.py @@ -395,9 +395,7 @@ def restriction_status(self, cidr): :return: RestrictionStatus with check result """ - is_known_ip = self.validate_ip_soource(cidr) - if is_known_ip: - status = RestrictionStatus.Restricted + is_known_ip = self.validate_known_ip_soource(cidr) status = RestrictionStatus.Restricted if cidr.endswith("/0"): @@ -405,7 +403,7 @@ def restriction_status(self, cidr): elif ipaddress.ip_network(cidr).is_global: status = RestrictionStatus.OpenPartly - elif is_known_ip: + if is_known_ip: status = RestrictionStatus.SafeIP logging.debug(f"Checked '{cidr}' - '{status.value}'") From 1377437b2998311a6829d7897c486fd3ca66bd7d Mon Sep 17 00:00:00 2001 From: vigneswararaomacharla Date: Wed, 7 Aug 2019 22:39:28 +0530 Subject: [PATCH 3/8] Updated with InsecureSG known ips. Updated with InsecureSG known ips. --- deployment/configs/config.json | 2 +- hammer/library/aws/security_groups.py | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/deployment/configs/config.json b/deployment/configs/config.json index a4f47ebf..38c0ead5 100755 --- a/deployment/configs/config.json +++ b/deployment/configs/config.json @@ -76,7 +76,7 @@ "remediation": false, "remediation_accounts": ["210987654321", "654321210987"], "remediation_retention_period": 21, - "known_ip_sources": ["205.203.150.72/32", "205.203.130.22/32"] + "known_ip_sources": ["205.203.150.72", "205.203.130.22"] }, "user_inactivekeys": { "enabled": true, diff --git a/hammer/library/aws/security_groups.py b/hammer/library/aws/security_groups.py index 2bb685db..2eee9b97 100755 --- a/hammer/library/aws/security_groups.py +++ b/hammer/library/aws/security_groups.py @@ -382,8 +382,9 @@ def validate_known_ip_soource(self, cidr): """ config = Config() known_ip_sources = config.sg.known_ip_sources + for ip_address in known_ip_sources: - if ip_address == cidr: + if ip_address in str(list(ipaddress.ip_network(cidr))): return True return False From cfad136dd7736a90800e5340385df1ae08c26e27 Mon Sep 17 00:00:00 2001 From: vigneswararaomacharla Date: Thu, 8 Aug 2019 14:24:11 +0530 Subject: [PATCH 4/8] Updated with Insecure SG known CIDR range changes. Updated with Insecure SG known CIDR range changes. --- hammer/library/aws/security_groups.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/hammer/library/aws/security_groups.py b/hammer/library/aws/security_groups.py index 2eee9b97..7be0a071 100755 --- a/hammer/library/aws/security_groups.py +++ b/hammer/library/aws/security_groups.py @@ -374,18 +374,22 @@ def __str__(self): perms = ", ".join([str(perm) for perm in self.permissions]) return f"{self.__class__.__name__}(Name={self.name}, Id={self.id}, Permissions=[{perms}])" - def validate_known_ip_soource(self, cidr): + def validate_known_ip_soource(self, source_ip): """ - :param cidr: ip address + :param source_ip: ip address :return: boolean """ config = Config() known_ip_sources = config.sg.known_ip_sources + source_cidr = ipaddress.ip_network(source_ip) - for ip_address in known_ip_sources: - if ip_address in str(list(ipaddress.ip_network(cidr))): + for ip in known_ip_sources: + ip_cidr = ipaddress.ip_network(ip) + + if (ip_cidr == source_cidr) or (source_cidr in str(list(ip_cidr))) or (source_cidr.subnet_of(ip_cidr)): return True + return False def restriction_status(self, cidr): From 585e52aae9efa6f1d596d5af0821f52497b71f49 Mon Sep 17 00:00:00 2001 From: vigneswararaomacharla Date: Thu, 8 Aug 2019 19:58:29 +0530 Subject: [PATCH 5/8] Updated with InsecureSG known source ips. Updated with InsecureSG known source ips. --- hammer/library/aws/security_groups.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/hammer/library/aws/security_groups.py b/hammer/library/aws/security_groups.py index 7be0a071..eac1526b 100755 --- a/hammer/library/aws/security_groups.py +++ b/hammer/library/aws/security_groups.py @@ -384,12 +384,17 @@ def validate_known_ip_soource(self, source_ip): known_ip_sources = config.sg.known_ip_sources source_cidr = ipaddress.ip_network(source_ip) - for ip in known_ip_sources: - ip_cidr = ipaddress.ip_network(ip) - - if (ip_cidr == source_cidr) or (source_cidr in str(list(ip_cidr))) or (source_cidr.subnet_of(ip_cidr)): + for known_ip in known_ip_sources: + known_ip_cidr = ipaddress.ip_network(known_ip) + if known_ip_cidr == source_cidr: return True - + elif source_ip.endswith("/32"): + for ip in known_ip_cidr: + if str(source_cidr) == str(ipaddress.ip_network(ip)): + return True + # ipaddress.subnet_of() function new to Python 3.7. Not available in 3.6 + """elif source_cidr.subnet_of(known_ip_cidr): + return True""" return False def restriction_status(self, cidr): From b828715a6d7a7db197e85e3b13d2fb811ca06356 Mon Sep 17 00:00:00 2001 From: vigneswararaomacharla Date: Mon, 19 Aug 2019 13:56:24 +0530 Subject: [PATCH 6/8] Updated with SG source ip review comments. Updated with SG source ip review comments. --- .../describe_sec_grps_unrestricted_access.py | 1 + hammer/library/aws/security_groups.py | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/hammer/identification/lambdas/sg-issues-identification/describe_sec_grps_unrestricted_access.py b/hammer/identification/lambdas/sg-issues-identification/describe_sec_grps_unrestricted_access.py index 5228a266..1249afbd 100755 --- a/hammer/identification/lambdas/sg-issues-identification/describe_sec_grps_unrestricted_access.py +++ b/hammer/identification/lambdas/sg-issues-identification/describe_sec_grps_unrestricted_access.py @@ -54,6 +54,7 @@ def lambda_handler(event, context): if checker.check(): for sg in checker.groups: logging.debug(f"Checking {sg.name} ({sg.id})") + logging.debug("SG status Testing::: {sg.status.value}" ) if not sg.restricted: # TODO: move instances detection for security group from reporting to identification #ec2_instances = EC2Operations.get_instance_details_of_sg_associated(account.client("ec2"), sg.id) diff --git a/hammer/library/aws/security_groups.py b/hammer/library/aws/security_groups.py index eac1526b..5d2e0dac 100755 --- a/hammer/library/aws/security_groups.py +++ b/hammer/library/aws/security_groups.py @@ -15,7 +15,7 @@ class RestrictionStatus(Enum): Restricted = "restricted" OpenCompletely = "open_completely" OpenPartly = "open_partly" - SafeIP = "safe_ips" + Safe = "safe" class SecurityGroupOperations: @@ -383,7 +383,7 @@ def validate_known_ip_soource(self, source_ip): config = Config() known_ip_sources = config.sg.known_ip_sources source_cidr = ipaddress.ip_network(source_ip) - + logging.debug("Source IP Testing: {source_cidr[-1]}") for known_ip in known_ip_sources: known_ip_cidr = ipaddress.ip_network(known_ip) if known_ip_cidr == source_cidr: @@ -414,7 +414,7 @@ def restriction_status(self, cidr): status = RestrictionStatus.OpenPartly if is_known_ip: - status = RestrictionStatus.SafeIP + status = RestrictionStatus.Safe logging.debug(f"Checked '{cidr}' - '{status.value}'") return status @@ -437,7 +437,7 @@ def check(self, restricted_ports): logging.debug(f"Checking '{perm.protocol}' '{perm.from_port}-{perm.to_port}' ports for {ip_range}") # first condition - CIDR is Global/Public status = self.restriction_status(ip_range.cidr) - if status in (RestrictionStatus.Restricted, RestrictionStatus.SafeIP): + if status in (RestrictionStatus.Restricted, RestrictionStatus.Safe): logging.debug(f"Skipping restricted/safe IP address '{ip_range}'") continue # second - check if ports from `restricted_ports` list has intersection with ports from FromPort.. From 9fc5fbfe18b44ce0e5e20043ef022e5fb79fbab7 Mon Sep 17 00:00:00 2001 From: vigneswararaomacharla Date: Mon, 19 Aug 2019 15:11:40 +0530 Subject: [PATCH 7/8] Updated with Review comments. Updated with Review comments. --- .../describe_sec_grps_unrestricted_access.py | 1 - hammer/library/aws/security_groups.py | 13 +++++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/hammer/identification/lambdas/sg-issues-identification/describe_sec_grps_unrestricted_access.py b/hammer/identification/lambdas/sg-issues-identification/describe_sec_grps_unrestricted_access.py index 1249afbd..5228a266 100755 --- a/hammer/identification/lambdas/sg-issues-identification/describe_sec_grps_unrestricted_access.py +++ b/hammer/identification/lambdas/sg-issues-identification/describe_sec_grps_unrestricted_access.py @@ -54,7 +54,6 @@ def lambda_handler(event, context): if checker.check(): for sg in checker.groups: logging.debug(f"Checking {sg.name} ({sg.id})") - logging.debug("SG status Testing::: {sg.status.value}" ) if not sg.restricted: # TODO: move instances detection for security group from reporting to identification #ec2_instances = EC2Operations.get_instance_details_of_sg_associated(account.client("ec2"), sg.id) diff --git a/hammer/library/aws/security_groups.py b/hammer/library/aws/security_groups.py index 5d2e0dac..d4ef2fbb 100755 --- a/hammer/library/aws/security_groups.py +++ b/hammer/library/aws/security_groups.py @@ -383,15 +383,20 @@ def validate_known_ip_soource(self, source_ip): config = Config() known_ip_sources = config.sg.known_ip_sources source_cidr = ipaddress.ip_network(source_ip) - logging.debug("Source IP Testing: {source_cidr[-1]}") + for known_ip in known_ip_sources: known_ip_cidr = ipaddress.ip_network(known_ip) if known_ip_cidr == source_cidr: return True elif source_ip.endswith("/32"): - for ip in known_ip_cidr: - if str(source_cidr) == str(ipaddress.ip_network(ip)): - return True + if source_cidr[-1] in known_ip_sources: + logging.info(f"Source IP Testing: {source_cidr[-1]}") + return True + """ + for ip in known_ip_cidr: + if str(source_cidr) == str(ipaddress.ip_network(ip)): + return True + """ # ipaddress.subnet_of() function new to Python 3.7. Not available in 3.6 """elif source_cidr.subnet_of(known_ip_cidr): return True""" From 35dc6fa9841c02addfabbf167ca33ae2afe5e75c Mon Sep 17 00:00:00 2001 From: vigneswararaomacharla Date: Mon, 19 Aug 2019 15:31:32 +0530 Subject: [PATCH 8/8] Upated with review comments. Upated with review comments. --- hammer/library/aws/security_groups.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/hammer/library/aws/security_groups.py b/hammer/library/aws/security_groups.py index d4ef2fbb..bab672d7 100755 --- a/hammer/library/aws/security_groups.py +++ b/hammer/library/aws/security_groups.py @@ -389,14 +389,8 @@ def validate_known_ip_soource(self, source_ip): if known_ip_cidr == source_cidr: return True elif source_ip.endswith("/32"): - if source_cidr[-1] in known_ip_sources: - logging.info(f"Source IP Testing: {source_cidr[-1]}") + if source_cidr[-1] in known_ip_cidr: return True - """ - for ip in known_ip_cidr: - if str(source_cidr) == str(ipaddress.ip_network(ip)): - return True - """ # ipaddress.subnet_of() function new to Python 3.7. Not available in 3.6 """elif source_cidr.subnet_of(known_ip_cidr): return True"""