def test_audit(self):
        statement = {'Effect': 'Allow', 'Principal': '*', 'Condition': {}}
        expected = 'Service is publicly accessible'
        self.assertTrue(
            expected in next(PolicyStatement(statement).audit())['text'])

        statement = {'Effect': 'Allow', 'NotPrincipal': 'arn:aws:'}
        expected = 'NotPrincipal with Allow'
        self.assertTrue(
            expected in next(PolicyStatement(statement).audit())['text'])

        statement = {
            'Effect': 'Allow',
            'Resource': 'arn:aws:sqs:eu-west-1:*:queue'
        }
        expected = 'Unrestricted AWS Account ID'
        self.assertTrue(
            expected in next(PolicyStatement(statement).audit())['text'])

        statement = {'Effect': 'Allow', 'Action': 'sqs:*'}
        expected = 'Unrestricted Action'
        self.assertTrue(
            expected in next(PolicyStatement(statement).audit())['text'])

        statement = {'Effect': 'Allow', 'NotAction': 'sqs:SendMessage'}
        expected = 'NotAction with Allow'
        self.assertTrue(
            expected in next(PolicyStatement(statement).audit())['text'])
 def test_is_unrestricted(self):
     policy = json.loads(
         self.fixtures.joinpath('PolicyUnrestricted.json').read_text())
     for statement in policy['Statement']:
         print(statement)
         self.assertTrue(
             PolicyStatement(statement).is_unrestricted('Principal'))
         self.assertTrue(
             PolicyStatement(statement).is_unrestricted('Action'))
Exemple #3
0
    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
Exemple #4
0
 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, _)
Exemple #5
0
 def test_is_undefined(self):
     policy = json.loads(self.fixtures.joinpath('PolicyUnrestricted.json').read_text())
     for statement in policy['Statement']:
         self.assertTrue(PolicyStatement(statement).is_undefined('Condition'))
Exemple #6
0
    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