Src/Compliance/ACSC.E8.json

{
    "_meta": {
        "title": "ACSC Essential Eight - Exchange Online Controls",
        "version": "2024-11",
        "source": "ACSC Essential Eight Maturity Model (November 2024)",
        "url": "https://www.cyber.gov.au/resources-business-and-government/essential-cyber-security/essential-eight",
        "notes": "Controls mapped to Exchange Online configuration. ML1=Maturity Level 1, ML2=Level 2, ML3=Level 3. Null staticStatus = runtime evaluation."
    },

    "AntiSpam": {
        "checks": [
            {
                "id": "E8-EXO-SPAM-1",
                "ML": "ML1",
                "control": "Inbound anti-spam policy exists and is enabled",
                "staticStatus": null,
                "statusExpression": "if ($InboundSpamPolicyCount -ge 1) { '[OK]' } else { '[FAIL]' }",
                "detailTemplate": "{InboundSpamPolicyCount} inbound anti-spam policy/policies configured. Default policy must be hardened.",
                "remediation": "Ensure the default inbound anti-spam policy is enabled and at minimum one custom policy exists with appropriate thresholds.",
                "tags": ["spam", "mail-flow", "ML1"]
            },
            {
                "id": "E8-EXO-SPAM-2",
                "ML": "ML1",
                "control": "High-confidence spam action set to Quarantine or Delete",
                "staticStatus": null,
                "statusExpression": "if ($HighConfidenceSpamActionOk) { '[OK]' } else { '[FAIL]' }",
                "detailTemplate": "High-confidence spam action: {HighConfidenceSpamAction}. Recommended: Quarantine or Delete.",
                "remediation": "Set HighConfidenceSpamAction to Quarantine in all inbound anti-spam policies.",
                "tags": ["spam", "quarantine", "ML1"]
            },
            {
                "id": "E8-EXO-SPAM-3",
                "ML": "ML2",
                "control": "Phishing action set to Quarantine or MoveToJMF",
                "staticStatus": null,
                "statusExpression": "if ($PhishSpamActionOk) { '[OK]' } else { '[WARN]' }",
                "detailTemplate": "Phish spam action: {PhishSpamAction}.",
                "remediation": "Set PhishSpamAction to Quarantine in all inbound anti-spam policies.",
                "tags": ["phishing", "spam", "ML2"]
            },
            {
                "id": "E8-EXO-SPAM-4",
                "ML": "ML2",
                "control": "Bulk complaint level (BCL) threshold <= 6",
                "staticStatus": null,
                "statusExpression": "if ($BulkThreshold -le 6) { '[OK]' } elseif ($BulkThreshold -le 7) { '[WARN]' } else { '[FAIL]' }",
                "detailTemplate": "Bulk complaint level threshold set to {BulkThreshold}. Recommended: 6 or lower.",
                "remediation": "Lower BulkThreshold to 6 or below to reduce bulk spam delivery.",
                "tags": ["spam", "bulk", "ML2"]
            },
            {
                "id": "E8-EXO-SPAM-5",
                "ML": "ML2",
                "control": "Outbound spam policy configured with recipient limits",
                "staticStatus": null,
                "statusExpression": "if ($OutboundSpamPolicyCount -ge 1) { '[OK]' } else { '[WARN]' }",
                "detailTemplate": "{OutboundSpamPolicyCount} outbound spam policy/policies found.",
                "remediation": "Configure outbound spam policies with appropriate per-hour recipient limits to prevent account compromise scenarios.",
                "tags": ["spam", "outbound", "ML2"]
            }
        ]
    },

    "AntiMalware": {
        "checks": [
            {
                "id": "E8-EXO-MAL-1",
                "ML": "ML1",
                "control": "Anti-malware policy is enabled",
                "staticStatus": null,
                "statusExpression": "if ($MalwarePolicyEnabled) { '[OK]' } else { '[FAIL]' }",
                "detailTemplate": "Default anti-malware policy enabled: {MalwarePolicyEnabled}.",
                "remediation": "Enable the default anti-malware policy in Exchange Online Protection.",
                "tags": ["malware", "ML1"]
            },
            {
                "id": "E8-EXO-MAL-2",
                "ML": "ML1",
                "control": "Common attachment filter enabled",
                "staticStatus": null,
                "statusExpression": "if ($CommonAttachmentFilterEnabled) { '[OK]' } else { '[FAIL]' }",
                "detailTemplate": "Common attachment type filter enabled: {CommonAttachmentFilterEnabled}.",
                "remediation": "Enable EnableFileFilter (common attachment filter) on all anti-malware policies.",
                "tags": ["malware", "attachments", "ML1"]
            },
            {
                "id": "E8-EXO-MAL-3",
                "ML": "ML2",
                "control": "Zero-hour auto purge (ZAP) for malware is enabled",
                "staticStatus": null,
                "statusExpression": "if ($ZapForMalwareEnabled) { '[OK]' } else { '[WARN]' }",
                "detailTemplate": "Zero-hour auto purge (ZAP) for malware enabled: {ZapForMalwareEnabled}.",
                "remediation": "Enable ZAP for malware in anti-malware policy to retroactively quarantine delivered malicious messages.",
                "tags": ["malware", "ZAP", "ML2"]
            },
            {
                "id": "E8-EXO-MAL-4",
                "ML": "ML2",
                "control": "Admin notifications enabled for malware detections",
                "staticStatus": null,
                "statusExpression": "if ($MalwareAdminNotifyEnabled) { '[OK]' } else { '[WARN]' }",
                "detailTemplate": "Admin notification on malware detection: {MalwareAdminNotifyEnabled}.",
                "remediation": "Configure admin notification email in anti-malware policy so security teams are alerted.",
                "tags": ["malware", "notifications", "ML2"]
            }
        ]
    },

    "AntiPhishing": {
        "checks": [
            {
                "id": "E8-EXO-PHISH-1",
                "ML": "ML1",
                "control": "Anti-phishing policy exists",
                "staticStatus": null,
                "statusExpression": "if ($AntiPhishPolicyCount -ge 1) { '[OK]' } else { '[FAIL]' }",
                "detailTemplate": "{AntiPhishPolicyCount} anti-phishing policy/policies configured.",
                "remediation": "Enable the default anti-phishing policy. Consider creating custom policies with stricter settings.",
                "tags": ["phishing", "ML1"]
            },
            {
                "id": "E8-EXO-PHISH-2",
                "ML": "ML1",
                "control": "Impersonation protection enabled",
                "staticStatus": null,
                "statusExpression": "if ($ImpersonationProtectionEnabled) { '[OK]' } else { '[FAIL]' }",
                "detailTemplate": "Impersonation protection (user + domain) enabled: {ImpersonationProtectionEnabled}.",
                "remediation": "Enable EnableUserImpersonation and EnableOrganizationDomainsProtection in anti-phishing policies.",
                "tags": ["phishing", "impersonation", "ML1"]
            },
            {
                "id": "E8-EXO-PHISH-3",
                "ML": "ML2",
                "control": "Mailbox intelligence enabled",
                "staticStatus": null,
                "statusExpression": "if ($MailboxIntelligenceEnabled) { '[OK]' } else { '[WARN]' }",
                "detailTemplate": "Mailbox intelligence enabled: {MailboxIntelligenceEnabled}.",
                "remediation": "Enable EnableMailboxIntelligence and EnableMailboxIntelligenceProtection in anti-phishing policies.",
                "tags": ["phishing", "intelligence", "ML2"]
            },
            {
                "id": "E8-EXO-PHISH-4",
                "ML": "ML2",
                "control": "Spoof intelligence enabled",
                "staticStatus": null,
                "statusExpression": "if ($SpoofIntelligenceEnabled) { '[OK]' } else { '[FAIL]' }",
                "detailTemplate": "Spoof intelligence enabled: {SpoofIntelligenceEnabled}.",
                "remediation": "Enable EnableSpoofIntelligence on all anti-phishing policies.",
                "tags": ["phishing", "spoof", "ML2"]
            },
            {
                "id": "E8-EXO-PHISH-5",
                "ML": "ML2",
                "control": "DMARC reject action on spoof",
                "staticStatus": null,
                "statusExpression": "if ($DmarcRejectEnabled) { '[OK]' } else { '[WARN]' }",
                "detailTemplate": "Honor DMARC policy on spoof: {DmarcRejectEnabled}.",
                "remediation": "Set HonorDmarcPolicy to $true so phishing messages that fail DMARC are actioned appropriately.",
                "tags": ["phishing", "DMARC", "ML2"]
            },
            {
                "id": "E8-EXO-PHISH-6",
                "ML": "ML3",
                "control": "First contact safety tip enabled",
                "staticStatus": null,
                "statusExpression": "if ($FirstContactSafetyTip) { '[OK]' } else { '[WARN]' }",
                "detailTemplate": "First contact safety tip enabled: {FirstContactSafetyTip}.",
                "remediation": "Enable EnableFirstContactSafetyTips to warn users when receiving email from a new sender.",
                "tags": ["phishing", "safety-tips", "ML3"]
            }
        ]
    },

    "DKIM": {
        "checks": [
            {
                "id": "E8-EXO-DKIM-1",
                "ML": "ML1",
                "control": "DKIM signing enabled for all verified domains",
                "staticStatus": null,
                "statusExpression": "if ($DkimEnabledDomainCount -eq $DkimTotalDomainCount -and $DkimTotalDomainCount -gt 0) { '[OK]' } elseif ($DkimEnabledDomainCount -gt 0) { '[WARN]' } else { '[FAIL]' }",
                "detailTemplate": "{DkimEnabledDomainCount} of {DkimTotalDomainCount} domains have DKIM signing enabled.",
                "remediation": "Enable DKIM for all verified custom domains. Use New-DkimSigningConfig or the Microsoft 365 Admin Center.",
                "tags": ["DKIM", "email-auth", "ML1"]
            },
            {
                "id": "E8-EXO-DKIM-2",
                "ML": "ML2",
                "control": "DKIM 2048-bit keys in use",
                "staticStatus": null,
                "statusExpression": "if ($Dkim2048BitCount -eq $DkimEnabledDomainCount -and $DkimEnabledDomainCount -gt 0) { '[OK]' } elseif ($Dkim2048BitCount -gt 0) { '[WARN]' } else { '[FAIL]' }",
                "detailTemplate": "{Dkim2048BitCount} of {DkimEnabledDomainCount} DKIM-enabled domains use 2048-bit key length.",
                "remediation": "Rotate DKIM keys to 2048-bit on all domains using Rotate-DkimSigningConfig.",
                "tags": ["DKIM", "key-strength", "ML2"]
            }
        ]
    },

    "DMARC": {
        "checks": [
            {
                "id": "E8-EXO-DMARC-1",
                "ML": "ML1",
                "control": "DMARC record published for all domains",
                "staticStatus": null,
                "statusExpression": "if ($DmarcDomainsCoveredPct -ge 100) { '[OK]' } elseif ($DmarcDomainsCoveredPct -ge 50) { '[WARN]' } else { '[FAIL]' }",
                "detailTemplate": "{DmarcDomainsConfigured} of {DmarcDomainsTotal} domains have a DMARC record ({DmarcDomainsCoveredPct}% coverage).",
                "remediation": "Publish a DMARC TXT record at _dmarc.<domain> for all mail-sending domains.",
                "tags": ["DMARC", "email-auth", "ML1"]
            },
            {
                "id": "E8-EXO-DMARC-2",
                "ML": "ML2",
                "control": "DMARC policy set to quarantine or reject",
                "staticStatus": null,
                "statusExpression": "if ($DmarcEnforcedDomainCount -ge $DmarcDomainsConfigured -and $DmarcDomainsConfigured -gt 0) { '[OK]' } elseif ($DmarcEnforcedDomainCount -gt 0) { '[WARN]' } else { '[FAIL]' }",
                "detailTemplate": "{DmarcEnforcedDomainCount} of {DmarcDomainsConfigured} DMARC-configured domains use quarantine or reject policy.",
                "remediation": "Move DMARC policy from p=none to p=quarantine, then p=reject once monitoring is complete.",
                "tags": ["DMARC", "policy-enforcement", "ML2"]
            },
            {
                "id": "E8-EXO-DMARC-3",
                "ML": "ML3",
                "control": "DMARC aggregate reports (rua) configured",
                "staticStatus": null,
                "statusExpression": "if ($DmarcRuaConfiguredCount -ge $DmarcDomainsConfigured -and $DmarcDomainsConfigured -gt 0) { '[OK]' } elseif ($DmarcRuaConfiguredCount -gt 0) { '[WARN]' } else { '[FAIL]' }",
                "detailTemplate": "{DmarcRuaConfiguredCount} of {DmarcDomainsConfigured} DMARC domains have aggregate report (rua) URIs configured.",
                "remediation": "Add an rua= tag to DMARC records pointing to a reporting inbox or third-party service.",
                "tags": ["DMARC", "reporting", "ML3"]
            }
        ]
    },

    "TransportRules": {
        "checks": [
            {
                "id": "E8-EXO-TR-1",
                "ML": "ML1",
                "control": "Transport rules do not bypass spam filtering for all senders",
                "staticStatus": null,
                "statusExpression": "if ($RulesBypassingSpamCount -eq 0) { '[OK]' } elseif ($RulesBypassingSpamCount -le 2) { '[WARN]' } else { '[FAIL]' }",
                "detailTemplate": "{RulesBypassingSpamCount} transport rule(s) are configured to bypass spam filtering.",
                "remediation": "Review transport rules using SetSCL -1. Remove or restrict bypass rules to specific trusted sender lists.",
                "tags": ["transport-rules", "spam-bypass", "ML1"]
            },
            {
                "id": "E8-EXO-TR-2",
                "ML": "ML2",
                "control": "No unrestricted external email forwarding rules",
                "staticStatus": null,
                "statusExpression": "if ($ExternalForwardingRuleCount -eq 0) { '[OK]' } else { '[FAIL]' }",
                "detailTemplate": "{ExternalForwardingRuleCount} transport rule(s) forward email to external recipients without restriction.",
                "remediation": "Disable or restrict transport rules that auto-forward email externally. Block external forwarding via Remote Domain settings.",
                "tags": ["transport-rules", "forwarding", "data-exfiltration", "ML2"]
            }
        ]
    },

    "Connectors": {
        "checks": [
            {
                "id": "E8-EXO-CON-1",
                "ML": "ML2",
                "control": "Inbound connectors require TLS",
                "staticStatus": null,
                "statusExpression": "if ($InboundConnectorNoTlsCount -eq 0) { '[OK]' } else { '[WARN]' }",
                "detailTemplate": "{InboundConnectorNoTlsCount} inbound connector(s) do not enforce TLS encryption.",
                "remediation": "Set RequireTls = $true on all inbound connectors.",
                "tags": ["connectors", "TLS", "encryption", "ML2"]
            },
            {
                "id": "E8-EXO-CON-2",
                "ML": "ML2",
                "control": "Outbound connectors use TLS",
                "staticStatus": null,
                "statusExpression": "if ($OutboundConnectorNoTlsCount -eq 0) { '[OK]' } else { '[WARN]' }",
                "detailTemplate": "{OutboundConnectorNoTlsCount} outbound connector(s) do not enforce TLS.",
                "remediation": "Set TlsSettings to EncryptionOnly or DomainValidation on outbound connectors.",
                "tags": ["connectors", "TLS", "ML2"]
            }
        ]
    },

    "AuditLogging": {
        "checks": [
            {
                "id": "E8-EXO-AUD-1",
                "ML": "ML2",
                "control": "Admin audit log enabled",
                "staticStatus": null,
                "statusExpression": "if ($AdminAuditLogEnabled) { '[OK]' } else { '[FAIL]' }",
                "detailTemplate": "Admin audit log enabled: {AdminAuditLogEnabled}.",
                "remediation": "Run: Set-AdminAuditLogConfig -AdminAuditLogEnabled $true",
                "tags": ["auditing", "logging", "ML2"]
            },
            {
                "id": "E8-EXO-AUD-2",
                "ML": "ML2",
                "control": "Mailbox audit logging enabled by default",
                "staticStatus": null,
                "statusExpression": "if ($MailboxAuditBypassCount -eq 0) { '[OK]' } elseif ($MailboxAuditBypassCount -le 5) { '[WARN]' } else { '[FAIL]' }",
                "detailTemplate": "{MailboxAuditBypassCount} mailbox(es) have audit logging bypassed.",
                "remediation": "Remove AuditBypass entries from mailboxes. Use Set-MailboxAuditBypassAssociation to review assignments.",
                "tags": ["auditing", "mailbox", "ML2"]
            },
            {
                "id": "E8-EXO-AUD-3",
                "ML": "ML3",
                "control": "Audit log retention >= 90 days",
                "staticStatus": null,
                "statusExpression": "if ($AdminAuditLogAgeLimit -ge 90) { '[OK]' } else { '[WARN]' }",
                "detailTemplate": "Admin audit log age limit: {AdminAuditLogAgeLimit} days.",
                "remediation": "Set AdminAuditLogAgeLimit to at least 90 days: Set-AdminAuditLogConfig -AdminAuditLogAgeLimit 90.00:00:00",
                "tags": ["auditing", "retention", "ML3"]
            }
        ]
    },

    "SafeAttachments": {
        "checks": [
            {
                "id": "E8-EXO-SA-1",
                "ML": "ML1",
                "control": "Safe Attachments policy is enabled",
                "staticStatus": null,
                "statusExpression": "if ($SafeAttachPolicyCount -ge 1) { '[OK]' } else { '[FAIL]' }",
                "detailTemplate": "{SafeAttachPolicyCount} Safe Attachments policy/policies are enabled.",
                "remediation": "Enable Safe Attachments in Microsoft Defender for Office 365. Assign policies to all recipients.",
                "tags": ["safe-attachments", "defender", "ML1"]
            },
            {
                "id": "E8-EXO-SA-2",
                "ML": "ML2",
                "control": "Safe Attachments action set to Block or DynamicDelivery",
                "staticStatus": null,
                "statusExpression": "if ($SafeAttachBlockActionCount -ge $SafeAttachPolicyCount -and $SafeAttachPolicyCount -gt 0) { '[OK]' } elseif ($SafeAttachBlockActionCount -gt 0) { '[WARN]' } else { '[FAIL]' }",
                "detailTemplate": "{SafeAttachBlockActionCount} of {SafeAttachPolicyCount} Safe Attachment policies use Block or DynamicDelivery action.",
                "remediation": "Set Action to Block or DynamicDelivery (recommended) in all Safe Attachments policies.",
                "tags": ["safe-attachments", "action", "ML2"]
            },
            {
                "id": "E8-EXO-SA-3",
                "ML": "ML2",
                "control": "Safe Attachments for SharePoint, OneDrive, Teams enabled",
                "staticStatus": null,
                "statusExpression": "if ($SafeAttachForSPOEnabled) { '[OK]' } else { '[WARN]' }",
                "detailTemplate": "Safe Attachments for SharePoint/OneDrive/Teams enabled: {SafeAttachForSPOEnabled}.",
                "remediation": "Run: Set-AtpPolicyForO365 -EnableATPForSPOTeamsODB $true",
                "tags": ["safe-attachments", "SharePoint", "OneDrive", "ML2"]
            }
        ]
    },

    "SafeLinks": {
        "checks": [
            {
                "id": "E8-EXO-SL-1",
                "ML": "ML1",
                "control": "Safe Links policy is enabled",
                "staticStatus": null,
                "statusExpression": "if ($SafeLinksPolicyCount -ge 1) { '[OK]' } else { '[FAIL]' }",
                "detailTemplate": "{SafeLinksPolicyCount} Safe Links policy/policies are enabled.",
                "remediation": "Enable Safe Links in Microsoft Defender for Office 365.",
                "tags": ["safe-links", "defender", "ML1"]
            },
            {
                "id": "E8-EXO-SL-2",
                "ML": "ML2",
                "control": "Safe Links 'do not rewrite' allowlist is empty or minimal",
                "staticStatus": null,
                "statusExpression": "if ($SafeLinksDoNotRewriteUrlCount -eq 0) { '[OK]' } elseif ($SafeLinksDoNotRewriteUrlCount -le 10) { '[WARN]' } else { '[FAIL]' }",
                "detailTemplate": "{SafeLinksDoNotRewriteUrlCount} URLs are excluded from Safe Links rewriting across all policies.",
                "remediation": "Review and minimize the DoNotRewriteUrls exclusion list. Every excluded URL is a potential phishing vector.",
                "tags": ["safe-links", "exclusions", "ML2"]
            },
            {
                "id": "E8-EXO-SL-3",
                "ML": "ML2",
                "control": "Safe Links real-time URL scanning enabled",
                "staticStatus": null,
                "statusExpression": "if ($SafeLinksRealTimeCount -ge $SafeLinksPolicyCount -and $SafeLinksPolicyCount -gt 0) { '[OK]' } else { '[WARN]' }",
                "detailTemplate": "{SafeLinksRealTimeCount} of {SafeLinksPolicyCount} Safe Links policies have real-time URL scanning enabled.",
                "remediation": "Enable ScanUrls and EnableForInternalSenders in Safe Links policies.",
                "tags": ["safe-links", "scanning", "ML2"]
            }
        ]
    }
}