def audit_sg(findings, region): # TODO Check if security groups allow large CIDR range (ex. 1.2.3.4/3) # TODO Check if an SG restricts IPv4 and then opens IPv6 or vice versa. cidrs = {} sg_json = query_aws(region.account, 'ec2-describe-security-groups', region) sgs = pyjq.all('.SecurityGroups[]', sg_json) for sg in sgs: cidr_and_name_list = pyjq.all('.IpPermissions[].IpRanges[]|[.CidrIp,.Description]', sg) for cidr, name in cidr_and_name_list: if not is_external_cidr(cidr): continue if is_unblockable_cidr(cidr): findings.add(Finding( region, 'SG_CIDR_UNNEEDED', sg['GroupId'], resource_details={'cidr': cidr})) continue if cidr.startswith('0.0.0.0') and not cidr.endswith('/0'): findings.add(Finding( region, 'SG_CIDR_UNEXPECTED', sg['GroupId'], resource_details={'cidr': cidr})) continue if cidr == '0.0.0.0/0': continue cidrs[cidr] = cidrs.get(cidr, set()) cidrs[cidr].add(sg['GroupId']) for ip_permissions in sg['IpPermissions']: cidrs_seen = set() for ip_ranges in ip_permissions['IpRanges']: if 'CidrIp' not in ip_ranges: continue cidr = ip_ranges['CidrIp'] for cidr_seen in cidrs_seen: if (IPNetwork(cidr_seen) in IPNetwork(cidr) or IPNetwork(cidr) in IPNetwork(cidr_seen)): findings.add(Finding( region, 'SG_CIDR_OVERLAPS', sg['GroupId'], resource_details={'cidr1': cidr, 'cidr2': cidr_seen})) cidrs_seen.add(cidr) for cidr in cidrs: ip = IPNetwork(cidr) if ip.size > 2048: findings.add(Finding( region, 'SG_LARGE_CIDR', cidr, resource_details={'size': ip.size, 'security_groups': cidrs[cidr]}))
def get_cidrs_for_account(account, cidrs): account = Account(None, account) for region_json in get_regions(account): region = Region(account, region_json) sg_json = query_aws(account, "ec2-describe-security-groups", region) sgs = pyjq.all(".SecurityGroups[]", sg_json) for sg in sgs: cidr_and_name_list = pyjq.all( ".IpPermissions[].IpRanges[]|[.CidrIp,.Description]", sg ) for cidr, name in cidr_and_name_list: if not is_external_cidr(cidr): continue if is_unblockable_cidr(cidr): print( "WARNING: Unneeded cidr used {} in {}".format( cidr, sg["GroupId"] ) ) continue if cidr.startswith("0.0.0.0") and not cidr.endswith("/0"): print( "WARNING: Unexpected CIDR for attempted public access {} in {}".format( cidr, sg["GroupId"] ) ) continue if cidr == "0.0.0.0/0": continue cidrs[cidr] = cidrs.get(cidr, set()) if name is not None: cidrs[cidr].add(name) for ip_permissions in sg["IpPermissions"]: cidrs_seen = set() for ip_ranges in ip_permissions["IpRanges"]: if "CidrIp" not in ip_ranges: continue cidr = ip_ranges["CidrIp"] for cidr_seen in cidrs_seen: if IPNetwork(cidr_seen) in IPNetwork(cidr) or IPNetwork( cidr ) in IPNetwork(cidr_seen): print( "WARNING: Overlapping CIDRs in {}, {} and {}".format( sg["GroupId"], cidr, cidr_seen ) ) cidrs_seen.add(cidr)
def audit_sg(findings, region): # TODO Check if security groups allow large CIDR range (ex. 1.2.3.4/3) # TODO Check if an SG restricts IPv4 and then opens IPv6 or vice versa. cidrs = {} sg_json = query_aws(region.account, "ec2-describe-security-groups", region) sgs = pyjq.all(".SecurityGroups[]", sg_json) for sg in sgs: cidr_and_name_list = pyjq.all( ".IpPermissions[]?.IpRanges[]|[.CidrIp,.Description]", sg) for cidr, name in cidr_and_name_list: if not is_external_cidr(cidr): continue if is_unblockable_cidr(cidr): findings.add( Finding( region, "SG_CIDR_UNNEEDED", sg["GroupId"], resource_details={"cidr": cidr}, )) continue if cidr.startswith("0.0.0.0") and not cidr.endswith("/0"): findings.add( Finding( region, "SG_CIDR_UNEXPECTED", sg["GroupId"], resource_details={"cidr": cidr}, )) continue if cidr == "0.0.0.0/0": continue cidrs[cidr] = cidrs.get(cidr, list()) cidrs[cidr].append(sg["GroupId"]) for ip_permissions in sg.get("IpPermissions", []): cidrs_seen = set() for ip_ranges in ip_permissions.get("IpRanges", []): if "CidrIp" not in ip_ranges: continue cidr = ip_ranges["CidrIp"] for cidr_seen in cidrs_seen: if IPNetwork(cidr_seen) in IPNetwork(cidr) or IPNetwork( cidr) in IPNetwork(cidr_seen): findings.add( Finding( region, "SG_CIDR_OVERLAPS", sg["GroupId"], resource_details={ "cidr1": cidr, "cidr2": cidr_seen }, )) cidrs_seen.add(cidr) for cidr in cidrs: ip = IPNetwork(cidr) if ip.size > 2048: findings.add( Finding( region, "SG_LARGE_CIDR", cidr, resource_details={ "size": ip.size, "security_groups": list(cidrs[cidr]), }, ))