def check_thirdparty_access(self, item): for uid in self._get_permissions(item): entity = Entity(category='account', value=uid) if 'THIRDPARTY' in self.inspect_entity(entity, item): self.record_thirdparty_access(item, entity, actions=['createEBSVolume'])
def check_internet_accessible(self, item): policies = self.load_resource_policies(item) for policy in policies: if policy.is_internet_accessible(): entity = Entity(category='principal', value='*') actions = list(policy.internet_accessible_actions()) self.record_internet_access(item, entity, actions)
def check_friendly_access(self, item): for uid in self._get_permissions(item): entity = Entity(category='account', value=uid) if 'FRIENDLY' in self.inspect_entity(entity, item): self.record_friendly_access(item, entity, actions=['createEBSVolume'])
def check_acl_unknown(self, item): acl = item.config.get('Grants', {}) for key in acl.keys(): if key.lower() not in self.KNOWN_ACLS: entity = Entity(category='ACL', value=key) self.record_unknown_access(item, entity, actions=acl[key])
def _check_internet_accessible(self, item, direction='ingress', severity=10): """ Make sure the SG does not contain any 0.0.0.0/0 or ::/0 rules. Called by: check_internet_accessible_ingress() check_internet_accessible_egress() Returns: `none` """ multiplier = _check_empty_security_group(item) score = severity * multiplier for rule in item.config.get("rules", []): if not rule.get("rule_type") == direction: continue cidr = rule.get("cidr_ip") if not str(cidr).endswith('/0'): continue actions = self._port_for_rule(rule) entity = Entity(category='cidr', value=cidr) self.record_internet_access(item, entity, actions, score=score, source='security_group')
def check_unknown_cross_account(self, item): accounts = item.config.get('Attributes', {}).get('restore', []) for account in accounts: if account == 'all': continue if account not in self.FRIENDLY and account not in self.THIRDPARTY: entity = Entity(category='account', value=account) self.record_unknown_access(item, entity, actions=['restore'])
def check_internet_accessible(self, item): accounts = { lp.get('UserId', lp.get('Group')) for lp in item.config.get('LaunchPermissions') } if 'all' in accounts or item.config.get('Public') == True: entity = Entity(category='account', value='all') self.record_internet_access(item, entity, actions=['LaunchPermissions'])
def check_unknown_cross_account(self, item): accounts = {lp.get('UserId', lp.get('Group')) for lp in item.config.get('LaunchPermissions', [])} for account in accounts: if account == 'all': continue if account not in self.FRIENDLY and account not in self.THIRDPARTY: entity = Entity( category='account', value=account) self.record_unknown_access(item, entity, actions=['LaunchPermissions'])
def check_unknown_access(self, item): for uid in self._get_permissions(item): # handled as a special case of internet accessible access. if 'aws-marketplace' == uid: continue entity = Entity(category='account', value=uid) if 'UNKNOWN' in self.inspect_entity(entity, item): self.record_unknown_access(item, entity, actions=['createEBSVolume'])
def check_friendly_cross_account(self, item): accounts = item.config.get('Attributes', {}).get('restore', []) for account in accounts: if account == 'all': continue if account in self.FRIENDLY: entity = Entity(category='account', value=account, account_name=self.FRIENDLY[account], account_identifier=account) self.record_friendly_access(item, entity, actions=['restore'])
def check_thirdparty_cross_account(self, item): accounts = {lp.get('UserId', lp.get('Group')) for lp in item.config.get('LaunchPermissions', [])} for account in accounts: if account == 'all': continue if account in self.THIRDPARTY: entity = Entity( category='account', value=account, account_name=self.THIRDPARTY[account], account_identifier=account) self.record_thirdparty_access(item, entity, actions=['LaunchPermissions'])
def _check_acl(self, item, field, keys, recorder): acl = item.config.get('Grants', {}) owner = item.config["Owner"]["ID"].lower() for key in acl.keys(): if key.lower() not in keys: continue # Canonical ID == Owning Account - No issue if key.lower() == owner.lower(): continue entity = Entity(category='ACL', value=key) account = self._get_account(field, key) if account: entity.account_name = account['name'] entity.account_identifier = account['identifier'] recorder(item, actions=acl[key], entity=entity)
def check_subscriptions_crossaccount(self, item): """ "subscriptions": [ { "Owner": "020202020202", "Endpoint": "*****@*****.**", "Protocol": "email", "TopicArn": ARN_PREFIX + ":sns:" + AWS_DEFAULT_REGION + ":020202020202:somesnstopic", "SubscriptionArn": ARN_PREFIX + ":sns:" + AWS_DEFAULT_REGION + ":020202020202:somesnstopic:..." } ] """ subscriptions = item.config.get('subscriptions', []) for subscription in subscriptions: src_account_number = subscription.get('Owner', None) entity = Entity(category=subscription.get('Protocol'), value=subscription.get('Endpoint'), account_identifier=src_account_number, account_name='UNKNOWN') account = self._get_account('identifier', src_account_number) if not account: self.record_unknown_access(item, entity, actions=['subscription']) continue if account['name'] == item.account: # Same Account continue entity.account_name = account['name'] if account['label'] == 'friendly': self.record_friendly_access(item, entity, actions=['subscription']) elif account['label'] == 'thirdparty': self.record_thirdparty_access(item, entity, actions=['subscription'])
def check_internet_accessible(self, item): if 'all' in item.config.get('Attributes', {}).get('restore', []): entity = Entity(category='account', value='all') self.record_internet_access(item, entity, actions=['restore'])
def check_marketplace_access(self, item): if 'aws-marketplace' in self._get_permissions(item): entity = Entity(category='shared_ebs', value='aws-marketplace') self.record_internet_access(item, entity, actions=['createEBSVolume'])
def check_internet_accessible(self, item): if 'all' in self._get_permissions(item, key='Group'): entity = Entity(category='shared_ebs', value='public') self.record_internet_access(item, entity, actions=['createEBSVolume'])
def _check_cross_account(self, item, key, recorder, direction='ingress', severity=10): """ Inspects each rule to look for cross account access. Called by: - check_friendly_cross_account_* - check_thirdparty_cross_account_* - check_unknown_cross_account_* Looks at both CIDR rules and rules referencing other security groups. Args: item: ChangeItem containing a config member with rules to review. key: One of ['FRIENDLY', 'THIRDPARTY', 'UNKNOWN']. When Auditor::inspect_entity() returns a set containing the provided key, the recorder method will be invoked. recorder: method to invoke to record an issue. Should be one of: Auditor::record_friendly_access() Auditor::record_thirdparty_access() Auditor::record_unknown_access() direction: Either `ingress` or `egress` matching the rule type to inspect. severity: Maximum score to record issue as. If the SG is not attached to any instances, the final final score may be reduced. Returns: `none` """ multiplier = _check_empty_security_group(item) score = severity * multiplier for rule in item.config.get("rules", []): if rule.get("rule_type") != direction: continue ports = self._port_for_rule(rule) if rule.get('owner_id'): entity_value = '{account}/{sg}'.format( account=rule.get('owner_id'), sg=rule.get('group_id')) entity = Entity(category='security_group', value=entity_value) if key in self.inspect_entity(entity, item): recorder(item, entity, ports, score=score, source='security_group') if rule.get('cidr_ip'): if '/0' in rule.get('cidr_ip'): continue entity = Entity(category='cidr', value=rule.get('cidr_ip')) if key in self.inspect_entity(entity, item): recorder(item, entity, ports, score=score, source='security_group')