m365advisor-tests/iso27001/Test-MtIso-Defender.Tests.ps1
|
########################################################################## # ISO 27001 / ISO 27002 - Defender for Office 365 Security Tests # Ported from M365-Assess: Security/Defender* Checks # Controls: A.8.13, A.8.21, A.8.22 ########################################################################## Describe "ISO 27001 - Defender Anti-Phishing & Anti-Spam" -Tag "ISO 27001", "ISO 27002", "ISO27001:A.8.21", "ISO27002:A.8.21" { BeforeAll { $script:antiPhishAvailable = Get-Command -Name Get-AntiPhishPolicy -ErrorAction SilentlyContinue $script:antiSpamAvailable = Get-Command -Name Get-HostedContentFilterPolicy -ErrorAction SilentlyContinue } It "ISO27001.A.8.21.1: Phishing threshold, Spoof Intel, and DMARC policies must be configured" { if (-not $script:antiPhishAvailable) { Set-ItResult -Skipped -Because "Defender for Office 365 / Get-AntiPhishPolicy is not available in this session" return } $policies = Get-AntiPhishPolicy -ErrorAction Stop if (@($policies).Count -eq 0) { $null | Should -Not -Be $null -Because "ISO A.8.21 requires at least one Anti-Phishing policy configured" return } foreach ($policy in @($policies)) { if (-not $policy.IsDefault) { continue } # detailed checks on default policy # Phish threshold level: 2 (Aggressive) or higher [int]$policy.PhishThresholdLevel | Should -BeGreaterOrEqual 2 -Because "ISO A.8.21 requires aggressive phishing thresholds to block suspicious mail" $policy.EnableSpoofIntelligence | Should -Be $true -Because "ISO A.8.21 requires spoof intelligence to block domain spoofing attacks" $policy.HonorDmarcPolicy | Should -Be $true -Because "ISO A.8.21 requires honoring sender DMARC records to validate sender authenticity" } } It "ISO27001.A.8.21.2: Bulk threshold, spam actions, and ZAP must be enabled" { if (-not $script:antiSpamAvailable) { Set-ItResult -Skipped -Because "Exchange Online / Get-HostedContentFilterPolicy is not available" return } $policies = Get-HostedContentFilterPolicy -ErrorAction Stop if (@($policies).Count -eq 0) { $null | Should -Not -Be $null -Because "ISO A.8.21 requires at least one Anti-Spam policy configured" return } foreach ($policy in @($policies)) { if (-not $policy.IsDefault) { continue } [int]$policy.BulkThreshold | Should -BeLessOrEqual 6 -Because "ISO A.8.21 requires bulk mail threshold set to 6 or lower to minimize spam delivery" $policy.HighConfidencePhishAction | Should -Be 'Quarantine' -Because "ISO A.8.21 requires quarantining high-confidence phishing messages" $policy.ZapEnabled | Should -Be $true -Because "ISO A.8.21 requires Zero-Hour Auto Purge (ZAP) enabled to remove delivered threats post-delivery" } } It "ISO27001.A.8.21.3: Inbound spam policy must not allow sender domains globally" { if (-not $script:antiSpamAvailable) { Set-ItResult -Skipped -Because "Exchange Online / Get-HostedContentFilterPolicy is not available" return } $policies = Get-HostedContentFilterPolicy -ErrorAction Stop foreach ($policy in @($policies)) { if (-not $policy.IsDefault) { continue } @($policy.AllowedSenderDomains).Count | Should -Be 0 -Because "ISO A.8.21 / A.8.13 prohibit global domain whitelisting as it bypasses all anti-spam/phishing filtering" } } } Describe "ISO 27001 - Defender Safe Links & Attachments" -Tag "ISO 27001", "ISO 27002", "ISO27001:A.8.21", "ISO27001:A.8.22", "ISO27002:A.8.21", "ISO27002:A.8.22" { BeforeAll { $script:slAvailable = Get-Command -Name Get-SafeLinksPolicy -ErrorAction SilentlyContinue $script:saAvailable = Get-Command -Name Get-SafeAttachmentPolicy -ErrorAction SilentlyContinue $script:atpAvailable = Get-Command -Name Get-AtpPolicyForO365 -ErrorAction SilentlyContinue } It "ISO27001.A.8.21.4: Safe Links URL scanning and click tracking must be enabled" { if (-not $script:slAvailable) { Set-ItResult -Skipped -Because "Defender for Office 365 P1/P2 (Safe Links cmdlets) not available" return } $policies = Get-SafeLinksPolicy -ErrorAction Stop $policies.Count | Should -BeGreaterThan 0 -Because "ISO A.8.21 requires Safe Links policies to protect users against malicious URLs" foreach ($policy in @($policies)) { $policy.ScanUrls | Should -Be $true -Because "ISO A.8.21 requires real-time Safe Links scanning for all link clicks" $policy.DoNotTrackUserClicks | Should -Be $false -Because "ISO A.8.21 requires click tracking enabled to identify and audit links clicked by users" } } It "ISO27001.A.8.21.5: Safe Attachments policy must be enabled and set to block malicious files" { if (-not $script:saAvailable) { Set-ItResult -Skipped -Because "Defender for Office 365 P1/P2 (Safe Attachments cmdlets) not available" return } $policies = Get-SafeAttachmentPolicy -ErrorAction Stop $policies.Count | Should -BeGreaterThan 0 -Because "ISO A.8.21 / A.8.22 require Safe Attachments policies to scan email files" foreach ($policy in @($policies)) { $policy.Enable | Should -Be $true -Because "ISO A.8.22 requires Safe Attachments protection to be enabled" $policy.Action | Should -Match 'Block|Replace|DynamicDelivery' -Because "ISO A.8.22 action must be set to Block, Replace, or Dynamic Delivery (not Allow)" } } It "ISO27001.A.8.21.6: Safe Attachments for SharePoint, OneDrive, and Teams must be enabled" { if (-not $script:atpAvailable) { Set-ItResult -Skipped -Because "Defender for Office 365 / Get-AtpPolicyForO365 is not available" return } $atpPolicy = Get-AtpPolicyForO365 -ErrorAction Stop $atpPolicy.EnableATPForSPOTeamsODB | Should -Be $true -Because "ISO A.8.21 / A.8.22 require extending attachment protections to Teams, OneDrive, and SharePoint repositories" } } Describe "ISO 27001 - Defender Anti-Malware & Outbound Spam" -Tag "ISO 27001", "ISO 27002", "ISO27001:A.8.22", "ISO27001:A.5.14", "ISO27002:A.8.22", "ISO27002:A.5.14" { BeforeAll { $script:malwareAvailable = Get-Command -Name Get-MalwareFilterPolicy -ErrorAction SilentlyContinue $script:outboundAvailable = Get-Command -Name Get-HostedOutboundSpamFilterPolicy -ErrorAction SilentlyContinue } It "ISO27001.A.8.22.1: Common Attachment Filter and Malware ZAP must be enabled" { if (-not $script:malwareAvailable) { Set-ItResult -Skipped -Because "Exchange Online / Get-MalwareFilterPolicy is not available" return } $policies = Get-MalwareFilterPolicy -ErrorAction Stop foreach ($policy in @($policies)) { if (-not $policy.IsDefault) { continue } $policy.EnableFileFilter | Should -Be $true -Because "ISO A.8.22 requires the common attachment filter to block known high-risk file extensions" $policy.ZapEnabled | Should -Be $true -Because "ISO A.8.22 requires Zero-Hour Auto Purge (ZAP) for malware to neutralize newly discovered threats" } } It "ISO27001.A.8.22.2: Malware filter must block comprehensive list of dangerous extensions" { if (-not $script:malwareAvailable) { Set-ItResult -Skipped -Because "Exchange Online / Get-MalwareFilterPolicy is not available" return } $policies = Get-MalwareFilterPolicy -ErrorAction Stop foreach ($policy in @($policies)) { if (-not $policy.IsDefault) { continue } $fileTypes = @($policy.FileTypes) $requiredTypes = @('ace','ani','apk','app','cab','cmd','com','deb','dmg','exe', 'hta','img','iso','jar','js','jse','lnk','msi','pif','ps1','reg','rgs', 'scr','sct','vb','vbe','vbs','vhd','vxd','wsc','wsf','wsh') $missing = @($requiredTypes | Where-Object { $fileTypes -notcontains $_ }) $missing.Count | Should -Be 0 -Because "ISO A.8.22 requires blocking all common dangerous script and executable file types: $($missing -join ', ')" } } It "ISO27001.A.5.14.1: Automatic external forwarding must be disabled in Outbound Spam policy" { if (-not $script:outboundAvailable) { Set-ItResult -Skipped -Because "Exchange Online / Get-HostedOutboundSpamFilterPolicy is not available" return } $policies = Get-HostedOutboundSpamFilterPolicy -ErrorAction Stop foreach ($policy in @($policies)) { if (-not $policy.IsDefault) { continue } $policy.AutoForwardingMode | Should -Be 'Off' -Because "ISO A.5.14 / A.8.21 require outbound forwarding rules disabled to prevent stealth data exfiltration via auto-forwarding" } } } |