def __init__(self, report, *args, **kwargs): self.report = report self.args = args[0] self.profile = args[0].profile self.access_key_id = args[0].keys[0] self.secret_access_key = args[0].keys[1] self.security = {'count': {}, 'items': []} self.item = None # item currently scanned if self.args.sonarqube: self.sonarqube = SonarQube(self.args.sonarqube, self.args.output) self.scan()
def __init__(self, report, *args, **kwargs): self.report = report self.args = args[0] self.profile = args[0].profile self.access_key_id = args[0].keys[0] self.secret_access_key = args[0].keys[1] self.security = {'count': {}, 'items': []} self.item = None # item currently scanned if self.args.sonarqube: try: self.sonarqube = SonarQube(self.args.sonarqube, self.args.output) except Exception: debug('Invalid SonarQube configuration') self.args.sonarqube = None # disable SonarQube self.scan()
class Scan: def __init__(self, report, *args, **kwargs): self.report = report self.args = args[0] self.profile = args[0].profile self.access_key_id = args[0].keys[0] self.secret_access_key = args[0].keys[1] self.security = {'count': {}, 'items': []} self.item = None # item currently scanned if self.args.sonarqube: self.sonarqube = SonarQube(self.args.sonarqube, self.args.output) self.scan() def track(self, arn, item): ''' Example: track('arn:...', {'level':'high','text':'...'}) @param idx Index in Statistics dictionary @param value Value ''' item['where'] = arn if self.item: item['where'] += f'\n\n{self.item.info}' if item in self.security['items']: return # Avoid duplicates level = item['level'] if level in self.security['count']: self.security['count'][level] += 1 else: self.security['count'][level] = 1 self.security['items'].append(item) def scan(self): ''' Scan Lambda report for vulnerabilities and provide recommendations. ''' # Audit Function policy if not self.report['policy']['function']: self.track(self.report['arn'], { 'level': 'info', 'text': 'Function policy is not defined' }) else: if 'Statement' in self.report['policy']['function']: for statement in self.report['policy']['function'][ 'Statement']: for _ in PolicyStatement(statement).audit(): self.track(self.report['arn'], _) # Audit Execution role policy if not len(self.report['policy']['role']['policies']): self.track(self.report['arn'], { 'level': 'info', 'text': 'Execution Role policy is not defined' }) else: for policy in self.report['policy']['role']['policies']: if 'Statement' in policy['document']: for statement in policy['document']['Statement']: for _ in PolicyStatement(statement, policy=policy).audit(): self.track(self.report['role'], _) # Audit Resources if 'logs' not in self.report['resources']['services']: self.track( self.report['arn'], { 'level': 'low', 'text': 'Function activity is not monitored by CloudWatch due to missing logs permissions' }) # Audit Triggers and Resources items = list( set( list(self.report['triggers']['items'].keys()) + list(self.report['resources']['items'].keys()))) for arn in items: if arn == '*': continue arn = arnparse(arn) if arn.resource in ['*', '']: continue self.item = None if arn.service == 's3': if arn.resource_type: # S3 object path continue self.item = S3(arn.full, profile=self.profile, access_key_id=self.access_key_id, secret_access_key=self.secret_access_key) for _ in AccessControlList(self.item.acl).audit(): self.track(arn.full, _) for _ in Encryption(self.item).audit(): self.track(arn.full, _) elif arn.service == 'sqs': self.item = SQS(arn.full, profile=self.profile, access_key_id=self.access_key_id, secret_access_key=self.secret_access_key) elif arn.service == 'sns': self.item = SNS(arn.full, profile=self.profile, access_key_id=self.access_key_id, secret_access_key=self.secret_access_key) elif arn.service == 'apigateway': self.item = APIGateway( arn.full, profile=self.profile, access_key_id=self.access_key_id, secret_access_key=self.secret_access_key) elif arn.service == 'dynamodb': self.item = DynamoDB(arn.full, profile=self.profile, access_key_id=self.access_key_id, secret_access_key=self.secret_access_key) if self.item: # Audit item Resource-based Policy if 'Statement' in self.item.policy: for statement in self.item.policy['Statement']: for _ in PolicyStatement(statement).audit(): self.track(arn.full, _) # If policy is missing, the the service is public else: for _ in Public(self.item).audit(): self.track(arn.full, _) # SonarQube if self.args.sonarqube: self.scan_sonarqube(arn, self.report['codeURL'], self.report['runtime']) for layer in self.report['layers']: self.scan_sonarqube(arn, layer['codeURL'], self.report['runtime']) # Sort findings by level sorted_items = [] for sort in ['high', 'medium', 'low', 'info']: for item in self.security['items']: if item['level'] == sort: if item not in sorted_items: sorted_items.append(item) self.security['items'] = sorted_items def scan_sonarqube(self, arn, codeURL, runtime): for _ in self.sonarqube.scan(codeURL, runtime): self.track(arn.full, _)
class Scan: def __init__(self, report, *args, **kwargs): self.report = report self.args = args[0] self.profile = args[0].profile self.access_key_id = args[0].keys[0] self.secret_access_key = args[0].keys[1] self.security = {"count": {}, "items": []} self.item = None # item currently scanned if self.args.sonarqube: try: self.sonarqube = SonarQube(self.args.sonarqube, self.args.output) except Exception: debug("Invalid SonarQube configuration") self.args.sonarqube = None # disable SonarQube self.scan() def track(self, arn, item): """ Example: track('arn:...', {'level':'high','text':'...'}) @param idx Index in Statistics dictionary @param value Value """ item["where"] = arn if self.item: item["where"] += f"\n\n{self.item.info}" if item in self.security["items"]: return # Avoid duplicates level = item["level"] if level in self.security["count"]: self.security["count"][level] += 1 else: self.security["count"][level] = 1 self.security["items"].append(item) def scan(self): """ Scan Lambda report for vulnerabilities and provide recommendations. """ # Audit Function policy if not self.report["policy"]["function"]: self.track( self.report["arn"], { "level": "info", "text": "Function policy is not defined" }, ) else: if "Statement" in self.report["policy"]["function"]: for statement in self.report["policy"]["function"][ "Statement"]: for _ in PolicyStatement(statement).audit(): self.track(self.report["arn"], _) # Audit Execution role policy if not len(self.report["policy"]["role"]["policies"]): self.track( self.report["arn"], { "level": "info", "text": "Execution Role policy is not defined" }, ) else: for policy in self.report["policy"]["role"]["policies"]: if "Statement" in policy["document"]: for statement in policy["document"]["Statement"]: for _ in PolicyStatement(statement, policy=policy).audit(): self.track(self.report["role"], _) # Audit KMS if "kms" in self.report: self.item = KMS( self.report["kms"], profile=self.profile, access_key_id=self.access_key_id, secret_access_key=self.secret_access_key, ) if not self.item.rotation: self.track( self.report["kms"], { "level": "medium", "text": ("Automatic rotation of key material is disabled\n" "https://docs.aws.amazon.com/kms/latest/developerguide/rotate-keys.html" ), }, ) for _, policy in self.item.policies.items(): self.audit_policy_statements(self.item.arn, policy) # Audit Resources if "logs" not in self.report["resources"]["services"]: self.track( self.report["arn"], { "level": "low", "text": "Function activity is not monitored by CloudWatch due to missing logs permissions", }, ) # Audit Triggers and Resources items = list( set( list(self.report["triggers"]["items"].keys()) + list(self.report["resources"]["items"].keys()))) for arn in items: if arn == "*": continue arn = arnparse(arn) if arn.resource in ["*", ""]: continue self.item = None if arn.service == "s3": if arn.resource_type: # S3 object path continue self.item = S3( arn.full, profile=self.profile, access_key_id=self.access_key_id, secret_access_key=self.secret_access_key, ) for _ in AccessControlList(self.item.acl).audit(): self.track(arn.full, _) for _ in Encryption(self.item).audit(): self.track(arn.full, _) elif arn.service == "sqs": self.item = SQS( arn.full, profile=self.profile, access_key_id=self.access_key_id, secret_access_key=self.secret_access_key, ) elif arn.service == "sns": self.item = SNS( arn.full, profile=self.profile, access_key_id=self.access_key_id, secret_access_key=self.secret_access_key, ) elif arn.service == "apigateway": self.item = APIGateway( arn.full, profile=self.profile, access_key_id=self.access_key_id, secret_access_key=self.secret_access_key, ) elif arn.service == "dynamodb": self.item = DynamoDB( arn.full, profile=self.profile, access_key_id=self.access_key_id, secret_access_key=self.secret_access_key, ) elif arn.service == "kms": self.item = KMS( arn.full, profile=self.profile, access_key_id=self.access_key_id, secret_access_key=self.secret_access_key, ) if self.item: if type(self.item) == KMS: # Audit KMS Policies for _, policy in self.item.policies.items(): self.audit_policy_statements(self.item.arn, policy) else: # Audit item Resource-based Policy self.audit_policy_statements(self.item.arn, self.item.policy) # If policy is missing, then the service is public for _ in Public(self.item).audit(): self.track(arn.full, _) # SonarQube if self.args.sonarqube: self.scan_sonarqube(arn, self.report["codeURL"], self.report["runtime"]) for layer in self.report["layers"]: self.scan_sonarqube(arn, layer["codeURL"], self.report["runtime"]) # Sort findings by level sorted_items = [] for sort in ["high", "medium", "low", "info"]: for item in self.security["items"]: if item["level"] == sort: if item not in sorted_items: sorted_items.append(item) self.security["items"] = sorted_items def audit_policy_statements(self, arn, policy): if "Statement" in policy: for statement in policy["Statement"]: for _ in PolicyStatement(statement).audit(): self.track(arn.full, _) def scan_sonarqube(self, arn, codeURL, runtime): for _ in self.sonarqube.scan(codeURL, runtime): self.track(arn.full, _)