Example #1
0
def rules(projectId):
    db = TinyDB("project_dbs/" + object_id_to_directory_name(projectId) +
                ".json")

    class Rule:
        def __init__(self, rule_title, category, filter_func):
            try:
                formatted_title = rule_title
                #                formatted_title = "%s - %s" % (category, rule_title)
                # print("Inserting %s" % (formatted_title))
                db.table('Rule').insert({
                    "title": formatted_title,
                    "category": category
                })
                for entity in list(
                        filter(filter_func,
                               db.table(category).all())):
                    add_finding.add_finding(db, category, entity.eid,
                                            rule_title)
            except Exception as e:
                print("Error inserting %s: %s" % (rule_title, e))
            except KeyError:
                pass

    Rule("Unused Network", "Network",
         lambda network: not network.get('members'))

    Rule(
        "VPC Flow Logs Disabled for Subnet", "Subnet", lambda subnet:
        not 'enableFlowLogs' in subnet.keys() or not subnet['enableFlowLogs'])

    # This isn't really a security finding, but there's not a good way to include it as informational without changing a bunch of other things
    Rule(
        "VPC Flow Logs Enabled for Subnet", "Subnet", lambda subnet:
        'enableFlowLogs' in subnet.keys() and subnet['enableFlowLogs'])

    Rule(
        "Unrestriced Internal Traffic", "Network",
        lambda network: network.get('firewallRules') and [
            True for rule in network['firewallRules']
            if "10.128.0.0/9" in rule['sourceRanges'] and [
                True for allow in rule['allowed']
                if not allow.get('ports') or "0-65535" in allow['ports']
            ]
        ])

    Rule(
        "Primitive Roles in Use", "Role", lambda role: role['role'] in
        ["roles/owner", "roles/editor", "roles/viewer"])

    try:
        Rule(
            "Role Assigned Directly to User", "Role", lambda role: [
                True for member in role['members']
                if ((len(member) > 4) and (member[:4] == "user"))
            ])
    except Exception as e:
        print("Error adding 'Role Assigned Directly to User' rule: %s" % (e))

    Rule(
        "Bucket Grants Access to allUsers", "Bucket",
        lambda bucket: 'acls' in bucket.keys(
        ) and [True for acl in bucket['acls'] if acl['scope'] == "allUsers"])

    Rule(
        "Bucket Grants Access to allAuthenticatedUsers", "Bucket",
        lambda bucket: 'acls' in bucket.keys() and [
            True for acl in bucket['acls']
            if acl['scope'] == "allAuthenticatedUsers"
        ])

    try:
        Rule(
            "User Assigned Bucket Permissions Directly", "Bucket",
            lambda bucket: 'acls' in bucket.keys() and
            [True for acl in bucket['acls'] if acl['scope'][:4] == "user"])
    except Exception as e:
        print(
            "Error adding 'User Assigned Bucket Permissions Directly' rule: %s"
            % (e))

    Rule("Bucket Logging Not Enabled", "Bucket",
         lambda bucket: "logging" not in bucket)

    Rule("Bucket Versioning Not Enabled", "Bucket",
         lambda bucket: "versioning" not in bucket)

    Rule(
        "Owner Role for allUsers in Bucket Default ACL", "Bucket",
        lambda bucket: bucket.get('defacls') and [
            True for defacl in bucket['defacls'] if defacl['scope'] ==
            "allUsers" and defacl['permission'] == "OWNER"
        ])

    Rule(
        "Read Role for allUsers in Bucket Default ACL", "Bucket",
        lambda bucket: bucket.get('defacls') and [
            True for defacl in bucket['defacls'] if defacl['scope'] ==
            "allUsers" and defacl['permission'] == "READER"
        ])
    try:
        Rule(
            "No Recent Compute Engine Backup Images", "Compute Engine",
            lambda instance: db.table('Snapshot').all() and [
                True for snapshot in db.table('Snapshot').all() if not [
                    True for disk in instance['disks']
                    if snapshot['sourceDisk'] in disk.values()
                ] and 'creationTimestamp' in snapshot.keys() and len(snapshot[
                    'creationTimestamp']) > 10 and datetime.datetime.strptime(
                        snapshot['creationTimestamp'][:10], "%Y-%m-%d") <
                datetime.datetime.now() - datetime.timedelta(days=30)
            ])
    except Exception as e:
        print(
            "Error creating 'No Recent Compute Engine Backup Images' rule: %s"
            % (e))

    try:
        #       Rule("Allows full access to all Cloud APIs", "Compute Engine", lambda instance: "https://www.googleapis.com/auth/cloud-platform" in instance['serviceAccounts'][0]['scopes'])
        # This is kind of a bad check, because it doesn't take into account the IAM policies which apply to the service accounts.
        # Access scopes are also a "legacy" method according to Google: https://cloud.google.com/compute/docs/access/service-accounts
        # Having it is arguably better than not having it, but it's misleading.
        # On the other hand, trying to take the IAM policies into account would also be a challenge.
        Rule(
            "Service Account is Allowed Full Access to all Cloud APIs via Instance",
            "Compute Engine",
            lambda instance: 'serviceAccounts' in instance.keys() and [
                True for service_account in instance['serviceAccounts']
                if 'scopes' in service_account.keys(
                ) and "https://www.googleapis.com/auth/cloud-platform" in
                service_account['scopes']
            ])
    except Exception as e:
        print("Error adding rule 'Allows full access to all Cloud APIs': %s" %
              (e))

    Rule(
        "Compute Engine with Serial Port Enabled", "Compute Engine",
        lambda instance: instance.get("metadata").get("items") and [
            True for item in instance.get("metadata").get("items")
            if item['key'] == "serial-port-enable" and item['value'] == 'true'
        ])

    Rule(
        "Cloud SQL Automatic Backup Disabled",
        "SQL Instance",
        #         lambda instance: not instance.get('settings').get('backupConfiguration').get('enabled'))
        # Ignore this rule for replicas
        lambda instance: 'REPLICA' not in instance.get('instanceType') and
        not instance.get('settings').get('backupConfiguration').get('enabled'))

    Rule(
        "Cloud SQL Binary Log Disabled",
        "SQL Instance",
        # Ignore this rule for replicas
        # PostgreSQL on GCP does not currently support binary logging
        lambda instance: 'POSTGRES' not in instance.get('databaseVersion') and
        'REPLICA' not in instance.get('instanceType') and not instance.get(
            'settings').get('backupConfiguration').get('binaryLogEnabled'))

    Rule(
        "Cloud SQL Instance does not Require TLS Connections", "SQL Instance",
        lambda instance: not instance.get('settings').get('ipConfiguration'
                                                          ).get('requireSsl'))

    Rule(
        "Service Account with Unrotated Keys", "Service Account",
        lambda account: account.get('keys') and
        [True for key in account.get('keys') if key_is_old(key)])

    Rule(
        "Service Account with allUsers Permission", "Service Account",
        lambda account: account.get('iam_policies') and [
            True for policy in account.get('iam_policies')
            if "allUsers" in policy['scope']
        ])

    Rule(
        "MongoDB Port Open to All", "Firewall", lambda firewall: firewall.get(
            "sourceRanges") and "0.0.0.0/0" in firewall['sourceRanges'] and [
                True for rule in firewall['allowed']
                if rule.get('ports') and "27017" in rule['ports']
            ])

    Rule(
        "PostgreSQL Port Open to All", "Firewall", lambda firewall: firewall.
        get("sourceRanges") and "0.0.0.0/0" in firewall['sourceRanges'] and [
            True for rule in firewall['allowed']
            if rule.get('ports') and "54322" in rule['ports']
        ])

    Rule(
        "Oracle Port Open to All", "Firewall", lambda firewall: firewall.get(
            "sourceRanges") and "0.0.0.0/0" in firewall['sourceRanges'] and [
                True for rule in firewall['allowed']
                if rule.get('ports') and "1521" in rule['ports']
            ])

    # "MySQL" and "MS SQL" are not the same thing
    Rule(
        "MySQL Port Open to All", "Firewall",
        lambda firewall: firewall.get("sourceRanges") and "0.0.0.0/0" in
        firewall['sourceRanges'] and test_allowed(firewall, "tcp", [3306]))

    Rule(
        "Microsoft SQL Server Port Open to All", "Firewall",
        lambda firewall: firewall.get("sourceRanges") and "0.0.0.0/0" in
        firewall['sourceRanges'] and test_allowed(firewall, "tcp", [1433]))

    Rule(
        "DNS Port Open to All", "Firewall", lambda firewall: firewall.get(
            "sourceRanges") and "0.0.0.0/0" in firewall['sourceRanges'] and [
                True for rule in firewall['allowed']
                if rule.get('ports') and "53" in rule['ports']
            ])

    Rule(
        "FTP Port Open to All", "Firewall", lambda firewall: firewall.get(
            "sourceRanges") and "0.0.0.0/0" in firewall['sourceRanges'] and [
                True for rule in firewall['allowed']
                if rule.get('ports') and "21" in rule['ports']
            ])

    Rule(
        "Telnet Port Open to All", "Firewall", lambda firewall: firewall.get(
            "sourceRanges") and "0.0.0.0/0" in firewall['sourceRanges'] and [
                True for rule in firewall['allowed']
                if rule.get('ports') and "23" in rule['ports']
            ])

    Rule(
        "RDP Port Open to All", "Firewall", lambda firewall: firewall.get(
            "sourceRanges") and "0.0.0.0/0" in firewall['sourceRanges'] and [
                True for rule in firewall['allowed']
                if rule.get('ports') and "3389" in rule['ports']
            ])

    Rule(
        "SSH Port Open to All", "Firewall", lambda firewall: firewall.get(
            "sourceRanges") and "0.0.0.0/0" in firewall['sourceRanges'] and [
                True for rule in firewall['allowed']
                if rule.get('ports') and "22" in rule['ports']
            ])

    Rule(
        "All Ports Open to All", "Firewall", lambda firewall: firewall.get(
            "sourceRanges") and "0.0.0.0/0" in firewall['sourceRanges'] and
        (not firewall.get('allowed')[0].get('ports') or [
            True for rule in firewall['allowed']
            if rule.get('ports') and '0-65535' in rule.get('ports')
        ]))

    Rule(
        "Use of Port Ranges in Firewall Rule", "Firewall", lambda firewall: [
            allow for allow in firewall['allowed'] if allow.get('ports') and
            [port for port in allow['ports'] if "-" in port]
        ])

    Rule("Unused Firewall Rules", "Firewall",
         lambda firewall: not firewall.get('affectedInstances'))

    #GKE
    Rule("Legacy ABAC in Use", "Cluster",
         lambda cluster: cluster.get("legacyAbac"))
    Rule("Basic Authentication Enabled", "Cluster",
         lambda cluster: cluster.get("masterAuth").get("username"))
    Rule("Client Certificate Enabled", "Cluster",
         lambda cluster: cluster.get("masterAuth").get("clientCertificate"))
    Rule(
        "No Network Policy", "Cluster", lambda cluster: cluster.get(
            "addonsConfig").get("networkPolicyConfig").get("disabled"))
    #I don't know why this is here too, since node version is in node pools. (same with service account and imageType)
    # Rule("Node Version Outdated", "Cluster", lambda cluster: cluster.get('currentNodeVersion') != '')
    Rule("Not Using Private Cluster Master", "Cluster",
         lambda cluster: not cluster.get('privateClusterConfig'))
    Rule("Not Using Private Cluster Nodes", "Cluster",
         lambda cluster: not cluster.get('enablePrivateNodes'))
    Rule(
        "Stackdriver Logging Disabled", "Cluster",
        lambda cluster: not cluster.get('loggingService') or
        (cluster.get("loggingService") == "none"))
    #Rule("Istio Not Enabled", "Cluster", lambda cluster: )
    Rule(
        "Dashboard Configured", "Cluster",
        lambda cluster: cluster.get("addonsConfig").get("kubernetesDashboard"))
    Rule("No Pod Security Policy", "Cluster",
         lambda cluster: not cluster.get("podSecurityPolicyConfig"))

    #Node Pools
    Rule(
        "Auto Upgrade Disabled", "Cluster",
        lambda cluster: cluster.get("nodePools") and [
            True for nodePool in cluster.get("nodePools")
            if nodePool.get('management').get('autoUpgrade')
        ])
    Rule(
        "Image Type not Container Optimized OS", "Cluster",
        lambda cluster: cluster.get("nodePools") and [
            True for nodePool in cluster.get("nodePools")
            if nodePool.get("config").get("imageType") != "COS"
        ])
    Rule(
        "Node Uses Default Service Account", "Cluster",
        lambda cluster: cluster.get("nodePools") and [
            True for nodePool in cluster.get("nodePools")
            if "default" in nodePool.get("config").get("serviceAccount")
        ])
    Rule(
        "Node Version Outdated", "Cluster",
        lambda cluster: cluster.get("nodePools") and [
            True for nodePool in cluster.get("nodePools")
            if nodePool.get("version") != "1.11.5-gke.5"
        ])
Example #2
0
def rules(projectId):
    db = TinyDB("project_dbs/" + projectId + ".json")

    class Rule:
        def __init__(self, rule_title, category, filter_func):
            try:
                db.table('Rule').insert({
                    "title": rule_title,
                    "category": category
                })
                for entity in list(
                        filter(filter_func,
                               db.table(category).all())):
                    add_finding.add_finding(db, category, entity.eid,
                                            rule_title)
            except KeyError:
                pass

    Rule("Unused Network", "Network",
         lambda network: not network.get('members'))

    Rule(
        "Unrestriced Internal Traffic", "Network",
        lambda network: network.get('firewallRules') and [
            True for rule in network['firewallRules']
            if "10.128.0.0/9" in rule['sourceRanges'] and [
                True for allow in rule['allowed']
                if not allow.get('ports') or "0-65535" in allow['ports']
            ]
        ])

    Rule(
        "Primitive Roles in Use", "Role", lambda role: role['role'] in
        ["roles/owner", "roles/editor", "roles/viewer"])

    Rule(
        "Role Given to User", "Role", lambda role:
        [True for member in role['members'] if member[:4] == "user"])

    Rule(
        "allUsers Permissions in Use", "Bucket", lambda bucket:
        [True for acl in bucket['acls'] if acl['scope'] == "allUsers"])

    Rule(
        "User Given Permissions", "Bucket", lambda bucket:
        [True for acl in bucket['acls'] if acl['scope'][:4] == "user"])

    Rule("Bucket Logging Not Enabled", "Bucket",
         lambda bucket: "logging" not in bucket)

    Rule("Bucket Versioning Not Enabled", "Bucket",
         lambda bucket: "versioning" not in bucket)

    Rule(
        "Owner Role for allUsers in DefACL", "Bucket", lambda bucket: [
            True for defacl in bucket['defacls'] if defacl['scope'] ==
            "allUsers" and defacl['permission'] == "OWNER"
        ])

    Rule(
        "Read Role for allUsers in DefACL", "Bucket", lambda bucket: [
            True for defacl in bucket['defacls'] if defacl['scope'] ==
            "allUsers" and defacl['permission'] == "READER"
        ])

    Rule(
        "No Recent Backup Images", "Compute Engine",
        lambda instance: db.table('Snapshot').all() and [
            True for snapshot in db.table('Snapshot').all() if not [
                True for disk in instance['disks']
                if snapshot['sourceDisk'] in disk.values()
            ] and datetime.datetime.strptime(
                snapshot['creationTimestamp'][:10], "%Y-%m-%d") < datetime.
            datetime.now() - datetime.timedelta(days=30)
        ])

    Rule(
        "Allows full access to all Cloud APIs", "Compute Engine",
        lambda instance: "https://www.googleapis.com/auth/cloud-platform" in
        instance['serviceAccounts'][0]['scopes'])

    Rule(
        "Serial Port Enabled", "Compute Engine",
        lambda instance: instance.get("metadata").get("items") and [
            True for item in instance.get("metadata").get("items")
            if item['key'] == "serial-port-enable" and item['value'] == 'true'
        ])

    Rule(
        "Automatic Backup Disabled", "SQL Instance", lambda instance:
        not instance.get('settings').get('backupConfiguration').get('enabled'))

    Rule(
        "Binary Log Disabled", "SQL Instance", lambda instance: not instance.
        get('settings').get('backupConfiguration').get('binaryLogEnabled'))

    Rule(
        "SSL Not Required", "SQL Instance", lambda instance: not instance.get(
            'settings').get('ipConfiguration').get('requireSsl'))

    Rule(
        "Unrotated Keys", "Service Account",
        lambda account: account.get('keys') and
        [True for key in account.get('keys') if key_is_old(key)])

    Rule(
        "allUsers Have Permissions", "Service Account",
        lambda account: account.get('iam_policies') and [
            True for policy in account.get('iam_policies')
            if "allUsers" in policy['scope']
        ])

    Rule(
        "MongoDB Port Open to All", "Firewall", lambda firewall: firewall.get(
            "sourceRanges") and "0.0.0.0/0" in firewall['sourceRanges'] and [
                True for rule in firewall['allowed']
                if rule.get('ports') and "27017" in rule['ports']
            ])

    Rule(
        "PostgreSQL Port Open to All", "Firewall", lambda firewall: firewall.
        get("sourceRanges") and "0.0.0.0/0" in firewall['sourceRanges'] and [
            True for rule in firewall['allowed']
            if rule.get('ports') and "54322" in rule['ports']
        ])

    Rule(
        "Oracle Port Open to All", "Firewall", lambda firewall: firewall.get(
            "sourceRanges") and "0.0.0.0/0" in firewall['sourceRanges'] and [
                True for rule in firewall['allowed']
                if rule.get('ports') and "1521" in rule['ports']
            ])

    Rule(
        "MySQL Port Open to All", "Firewall", lambda firewall: firewall.get(
            "sourceRanges") and "0.0.0.0/0" in firewall['sourceRanges'] and
        test_allowed(firewall, "tcp", [3306, 1433]))

    Rule(
        "DNS Port Open to All", "Firewall", lambda firewall: firewall.get(
            "sourceRanges") and "0.0.0.0/0" in firewall['sourceRanges'] and [
                True for rule in firewall['allowed']
                if rule.get('ports') and "53" in rule['ports']
            ])

    Rule(
        "FTP Port Open to All", "Firewall", lambda firewall: firewall.get(
            "sourceRanges") and "0.0.0.0/0" in firewall['sourceRanges'] and [
                True for rule in firewall['allowed']
                if rule.get('ports') and "21" in rule['ports']
            ])

    Rule(
        "Telnet Port Open to All", "Firewall", lambda firewall: firewall.get(
            "sourceRanges") and "0.0.0.0/0" in firewall['sourceRanges'] and [
                True for rule in firewall['allowed']
                if rule.get('ports') and "23" in rule['ports']
            ])

    Rule(
        "RDP Port Open to All", "Firewall", lambda firewall: firewall.get(
            "sourceRanges") and "0.0.0.0/0" in firewall['sourceRanges'] and [
                True for rule in firewall['allowed']
                if rule.get('ports') and "3389" in rule['ports']
            ])

    Rule(
        "SSH Port Open to All", "Firewall", lambda firewall: firewall.get(
            "sourceRanges") and "0.0.0.0/0" in firewall['sourceRanges'] and [
                True for rule in firewall['allowed']
                if rule.get('ports') and "22" in rule['ports']
            ])

    Rule(
        "All Ports Open to All", "Firewall", lambda firewall: firewall.get(
            "sourceRanges") and "0.0.0.0/0" in firewall['sourceRanges'] and
        (not firewall.get('allowed')[0].get('ports') or [
            True for rule in firewall['allowed']
            if rule.get('ports') and '0-65535' in rule.get('ports')
        ]))

    Rule(
        "Use of Port Ranges", "Firewall", lambda firewall: [
            allow for allow in firewall['allowed'] if allow.get('ports') and
            [port for port in allow['ports'] if "-" in port]
        ])

    Rule("Unused Firewall Rules", "Firewall",
         lambda firewall: not firewall.get('affectedInstances'))
Example #3
0
         lambda firewall: firewall.get("sourceRanges")
                          and "0.0.0.0/0" in firewall['sourceRanges']
                          and [True for rule in firewall['allowed'] if rule.get('ports')
                               and "54322" in rule['ports']])

    Rule("Oracle Port Open to All", "Firewall",
         lambda firewall: firewall.get("sourceRanges")
                          and "0.0.0.0/0" in firewall['sourceRanges']
                          and [True for rule in firewall['allowed'] if rule.get('ports')
                               and "1521" in rule['ports']])

    # "MySQL" and "MS SQL" are not the same thing
    Rule("MySQL Port Open to All", "Firewall",
         lambda firewall: firewall.get("sourceRanges")
                          and "0.0.0.0/0" in firewall['sourceRanges']
                          and test_allowed(firewall, "tcp", [3306]))

    Rule("Microsoft SQL Server Port Open to All", "Firewall",
         lambda firewall: firewall.get("sourceRanges")
                          and "0.0.0.0/0" in firewall['sourceRanges']
                          and test_allowed(firewall, "tcp", [1433]))

    Rule("DNS Port Open to All", "Firewall",
         lambda firewall: firewall.get("sourceRanges")
                          and "0.0.0.0/0" in firewall['sourceRanges']
                          and [True for rule in firewall['allowed'] if rule.get('ports')
                               and "53" in rule['ports']])

    Rule("FTP Port Open to All", "Firewall",
         lambda firewall: firewall.get("sourceRanges")
                          and "0.0.0.0/0" in firewall['sourceRanges']