Src/Private/Get-AbrExoAntiPhishing.ps1
|
function Get-AbrExoAntiPhishing { <# .SYNOPSIS Documents Exchange Online anti-phishing policy configuration with ACSC E8 and CIS compliance assessments. .NOTES Version: 0.1.0 Author: Pai Wei Sing #> [CmdletBinding()] param ( [Parameter(Position = 0, Mandatory)] [string]$TenantId ) begin { Write-PScriboMessage -Message "Collecting Exchange Online Anti-Phishing configuration for $TenantId." Show-AbrDebugExecutionTime -Start -TitleMessage 'AntiPhishing' } process { Section -Style Heading2 'Anti-Phishing Policies' { Paragraph "The following section documents the anti-phishing policies configured for tenant $TenantId." BlankLine # Compliance variable defaults $AntiPhishPolicyCount = 0 $ImpersonationProtectionEnabled = $false $MailboxIntelligenceEnabled = $false $SpoofIntelligenceEnabled = $false $DmarcRejectEnabled = $false $FirstContactSafetyTip = $false try { Write-Host " - Retrieving anti-phishing policies..." $AntiPhishPolicies = Get-AntiPhishPolicy -ErrorAction Stop | Sort-Object IsDefault -Descending $AntiPhishPolicyCount = @($AntiPhishPolicies).Count if ($AntiPhishPolicies) { $DefaultPolicy = $AntiPhishPolicies | Where-Object { $_.IsDefault } | Select-Object -First 1 if (-not $DefaultPolicy) { $DefaultPolicy = $AntiPhishPolicies | Select-Object -First 1 } $ImpersonationProtectionEnabled = ($DefaultPolicy.EnableUserImpersonation -eq $true -or $DefaultPolicy.EnableOrganizationDomainsProtection -eq $true) $MailboxIntelligenceEnabled = ($DefaultPolicy.EnableMailboxIntelligence -eq $true) $SpoofIntelligenceEnabled = ($DefaultPolicy.EnableSpoofIntelligence -eq $true) $DmarcRejectEnabled = ($DefaultPolicy.HonorDmarcPolicy -eq $true) $FirstContactSafetyTip = ($DefaultPolicy.EnableFirstContactSafetyTips -eq $true) # Summary object — key security toggles only (11 columns) $PhishSumObj = [System.Collections.ArrayList]::new() # Detail object — full settings in List format (stored for Excel, rendered per-policy if InfoLevel 2) $PhishObj = [System.Collections.ArrayList]::new() foreach ($Policy in $AntiPhishPolicies) { $phishSumInObj = [ordered] @{ 'Policy Name' = $Policy.Name 'Default' = $Policy.IsDefault 'Enabled' = $Policy.Enabled 'Threshold' = $Policy.PhishThresholdLevel 'User Imp.' = $Policy.EnableUserImpersonation 'Domain Imp.' = $Policy.EnableOrganizationDomainsProtection 'Mailbox Intel' = $Policy.EnableMailboxIntelligence 'Spoof Intel' = $Policy.EnableSpoofIntelligence 'DMARC Honor' = $Policy.HonorDmarcPolicy 'First Contact Tip' = $Policy.EnableFirstContactSafetyTips 'Unauth Sender' = $Policy.EnableUnauthenticatedSender } $PhishSumObj.Add([pscustomobject](ConvertTo-HashToYN $phishSumInObj)) | Out-Null $phishInObj = [ordered] @{ 'Policy Name' = $Policy.Name 'Default Policy' = $Policy.IsDefault 'Enabled' = $Policy.Enabled 'Phish Threshold Level' = $Policy.PhishThresholdLevel 'User Impersonation Protection' = $Policy.EnableUserImpersonation 'Domain Impersonation Protection' = $Policy.EnableOrganizationDomainsProtection 'Mailbox Intelligence' = $Policy.EnableMailboxIntelligence 'Mailbox Intel Protection' = $Policy.EnableMailboxIntelligenceProtection 'Spoof Intelligence' = $Policy.EnableSpoofIntelligence 'Honor DMARC Policy' = $Policy.HonorDmarcPolicy 'First Contact Safety Tip' = $Policy.EnableFirstContactSafetyTips 'Unauth Sender Indicator' = $Policy.EnableUnauthenticatedSender 'Impersonation Action (User)' = $Policy.TargetedUserProtectionAction 'Impersonation Action (Domain)' = $Policy.TargetedDomainProtectionAction 'Mailbox Intel Action' = $Policy.MailboxIntelligenceProtectionAction 'Spoof Action' = $Policy.AuthenticationFailAction } $PhishObj.Add([pscustomobject](ConvertTo-HashToYN $phishInObj)) | Out-Null } $null = (& { if ($HealthCheck.ExchangeOnline.AntiPhishing) { $null = ($PhishSumObj | Where-Object { $_.'User Imp.' -eq 'No' -or $_.'Domain Imp.' -eq 'No' } | Set-Style -Style Critical | Out-Null) $null = ($PhishSumObj | Where-Object { $_.'Spoof Intel' -eq 'No' } | Set-Style -Style Critical | Out-Null) $null = ($PhishSumObj | Where-Object { $_.'Mailbox Intel' -eq 'No' } | Set-Style -Style Warning | Out-Null) $null = ($PhishSumObj | Where-Object { $_.'DMARC Honor' -eq 'No' } | Set-Style -Style Warning | Out-Null) } }) # Summary table — 11 cols = 100% $PhishTableParams = @{ Name = "Anti-Phishing Policy Summary - $TenantId" List = $false ColumnWidths = 16, 7, 7, 8, 8, 9, 9, 9, 9, 10, 8 } if ($Report.ShowTableCaptions) { $PhishTableParams['Caption'] = "- $($PhishTableParams.Name)" } $PhishSumObj | Table @PhishTableParams # Full detail in List format (InfoLevel 2) if ($InfoLevel.AntiPhishing -ge 2) { BlankLine foreach ($PolicyDetail in $PhishObj) { $PhishDetailParams = @{ Name = "Anti-Phishing Policy Detail: $($PolicyDetail.'Policy Name') - $TenantId"; List = $true; ColumnWidths = 45, 55 } if ($Report.ShowTableCaptions) { $PhishDetailParams['Caption'] = "- $($PhishDetailParams.Name)" } $PolicyDetail | Table @PhishDetailParams } } $script:ExcelSheets['Anti-Phishing'] = $PhishObj #region Protected Users (Impersonation) if ($InfoLevel.AntiPhishing -ge 2) { $AllProtectedUsers = [System.Collections.ArrayList]::new() foreach ($Policy in $AntiPhishPolicies) { if ($Policy.TargetedUsersToProtect -and $Policy.TargetedUsersToProtect.Count -gt 0) { foreach ($User in $Policy.TargetedUsersToProtect) { $null = $AllProtectedUsers.Add([pscustomobject]@{ 'Policy' = $Policy.Name 'Protected User' = $User }) } } } if ($AllProtectedUsers.Count -gt 0) { Section -Style Heading3 'Impersonation Protected Users' { Paragraph "The following users are configured for impersonation protection across all anti-phishing policies." BlankLine $PuTableParams = @{ Name = "Protected Users - $TenantId"; List = $false; ColumnWidths = 40, 60 } if ($Report.ShowTableCaptions) { $PuTableParams['Caption'] = "- $($PuTableParams.Name)" } $AllProtectedUsers | Table @PuTableParams } } # Protected Domains $AllProtectedDomains = [System.Collections.ArrayList]::new() foreach ($Policy in $AntiPhishPolicies) { if ($Policy.TargetedDomainsToProtect -and $Policy.TargetedDomainsToProtect.Count -gt 0) { foreach ($Domain in $Policy.TargetedDomainsToProtect) { $null = $AllProtectedDomains.Add([pscustomobject]@{ 'Policy' = $Policy.Name 'Protected Domain' = $Domain }) } } } if ($AllProtectedDomains.Count -gt 0) { Section -Style Heading3 'Impersonation Protected Domains' { Paragraph "The following domains are configured for impersonation protection across all anti-phishing policies." BlankLine $PdTableParams = @{ Name = "Protected Domains - $TenantId"; List = $false; ColumnWidths = 40, 60 } if ($Report.ShowTableCaptions) { $PdTableParams['Caption'] = "- $($PdTableParams.Name)" } $AllProtectedDomains | Table @PdTableParams } } } #endregion #region Policy Assignments $PhishRules = Get-AntiPhishRule -ErrorAction SilentlyContinue | Sort-Object Priority if ($InfoLevel.AntiPhishing -ge 2 -and $PhishRules) { Section -Style Heading3 'Anti-Phishing Policy Assignments' { Paragraph "The following policy assignments determine which recipients are protected by each anti-phishing policy." BlankLine $RuleObj = [System.Collections.ArrayList]::new() foreach ($Rule in $PhishRules) { $ruleInObj = [ordered] @{ 'Rule Name' = $Rule.Name 'Priority' = $Rule.Priority 'State' = $Rule.State 'Policy' = $Rule.AntiPhishPolicy 'Applied To' = (@($Rule.SentTo) + @($Rule.SentToMemberOf) + @($Rule.RecipientDomainIs)) -join ', ' } $RuleObj.Add([pscustomobject]$ruleInObj) | Out-Null } $null = (& { if ($HealthCheck.ExchangeOnline.AntiPhishing) { $null = ($RuleObj | Where-Object { $_.State -eq 'Disabled' } | Set-Style -Style Warning | Out-Null) } }) $RuleTableParams = @{ Name = "Anti-Phishing Policy Assignments - $TenantId"; List = $false; ColumnWidths = 22, 8, 8, 22, 40 } if ($Report.ShowTableCaptions) { $RuleTableParams['Caption'] = "- $($RuleTableParams.Name)" } $RuleObj | Table @RuleTableParams } } #endregion } else { Paragraph "No anti-phishing policies found. EOP default policy may apply." } } catch { Write-ExoError 'AntiPhishing' "Unable to retrieve anti-phishing policies: $($_.Exception.Message)" Paragraph "Unable to retrieve anti-phishing policy data: $($_.Exception.Message)" } BlankLine Paragraph "ACSC Essential Eight Assessment" BlankLine $e8Vars = @{ AntiPhishPolicyCount = $AntiPhishPolicyCount ImpersonationProtectionEnabled = $ImpersonationProtectionEnabled MailboxIntelligenceEnabled = $MailboxIntelligenceEnabled SpoofIntelligenceEnabled = $SpoofIntelligenceEnabled DmarcRejectEnabled = $DmarcRejectEnabled FirstContactSafetyTip = $FirstContactSafetyTip } $e8Checks = Build-AbrExoComplianceChecks -Definitions (Get-AbrExoE8Checks 'AntiPhishing') -Framework 'E8' -CallerVariables $e8Vars New-AbrExoE8AssessmentTable -Checks $e8Checks -Name 'Anti-Phishing' -TenantId $TenantId if ($e8Checks) { foreach ($row in $e8Checks) { $null = $script:E8AllChecks.Add([pscustomobject]@{ Section = 'Anti-Phishing' ML = $row.ML Control = $row.Control Status = $row.Status Detail = $row.Detail }) } } BlankLine Paragraph "CIS Microsoft 365 Foundations Benchmark Assessment" BlankLine $cisVars = @{ ImpersonationProtectionEnabled = $ImpersonationProtectionEnabled SpoofIntelligenceEnabled = $SpoofIntelligenceEnabled MailboxIntelligenceEnabled = $MailboxIntelligenceEnabled } $cisChecks = Build-AbrExoComplianceChecks -Definitions (Get-AbrExoCISChecks 'AntiPhishing') -Framework 'CIS' -CallerVariables $cisVars New-AbrExoCISAssessmentTable -Checks $cisChecks -Name 'Anti-Phishing' -TenantId $TenantId if ($cisChecks) { foreach ($row in $cisChecks) { $null = $script:CISAllChecks.Add([pscustomobject]@{ Section = 'Anti-Phishing' CISControl = $row.CISControl Level = $row.Level Status = $row.Status Detail = $row.Detail }) } } } } end { Show-AbrDebugExecutionTime -End -TitleMessage 'AntiPhishing' } } |