Checks/MDO/MET-MDO004-AntiSpoofing.ps1
|
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', 'METCheckInfo', Justification = 'Check metadata. Read from the AST by Get-METCheck and never executed.')] param() $METCheckInfo = @{ Name = 'Anti-Spoofing' Severity = 'High' Description = 'Checks AuthenticationFailAction, DMARC honor settings, and unauthenticated sender visual indicators on the anti-phish policy.' RequiresModule = @('ExchangeOnlineManagement') } try { $antiPhishRules = @(Get-AntiPhishRule -ErrorAction Stop | Sort-Object Priority) $antiPhishPolicies = @(Get-AntiPhishPolicy -ErrorAction Stop) } catch { New-METCheckResult -CheckId 'MET-MDO004' -Category MDO -Name 'Anti-Spoofing' ` -Result Fail -Severity High -AffectedObject 'Anti-Phish Policies' ` -Finding 'Unable to retrieve anti-phishing policies (anti-spoofing settings are part of these policies)' ` -Recommendation 'Ensure the account has Security Reader or higher permissions.' ` -ReferenceUrl 'https://aka.ms/mdo-antispoofing' -ErrorMessage $_.ToString() return } $ruleByPolicy = @{} foreach ($r in $antiPhishRules) { $ruleByPolicy[$r.AntiPhishPolicy] = $r } foreach ($policy in $antiPhishPolicies) { $isDefault = $policy.IsDefault -eq $true $rule = $ruleByPolicy[$policy.Name] if (-not $isDefault -and (-not $rule -or $rule.State -ne 'Enabled')) { continue } $scope = if ($isDefault) { 'catch-all (default - applies to all uncovered recipients)' } else { Get-METRuleScope -Rule $rule } $label = "$($policy.Name) [$scope]" $issues = [System.Collections.Generic.List[string]]::new() if ($null -eq $policy.PSObject.Properties['EnableSpoofIntelligence'] -or $null -eq $policy.EnableSpoofIntelligence) { $issues.Add('The EnableSpoofIntelligence property was not returned for this policy, so spoof intelligence was not established as enabled - reported as a gap rather than a pass, because a policy with it switched off returns nothing different here') } elseif (-not $policy.EnableSpoofIntelligence) { $issues.Add('Spoof intelligence is disabled') } if ($policy.AuthenticationFailAction -eq 'MoveToJmf') { $issues.Add("Authentication failure action is 'MoveToJmf' - consider 'Quarantine' for stronger enforcement") } elseif ($policy.AuthenticationFailAction -notin 'MoveToJmf','Quarantine') { $issues.Add("Authentication failure action is '$($policy.AuthenticationFailAction)' - should be 'Quarantine' or at minimum 'MoveToJmf'") } if (-not $policy.EnableUnauthenticatedSender) { $issues.Add('Unauthenticated sender indicators (? and via tags) are disabled') } if (-not $policy.HonorDmarcPolicy) { $issues.Add('DMARC policy enforcement is not honored') } if ($issues.Count -gt 0) { $result = if ($policy.EnableSpoofIntelligence -ne $true) { 'Fail' } else { 'Warning' } New-METCheckResult -CheckId 'MET-MDO004' -Category MDO -Name 'Anti-Spoofing' ` -Result $result -Severity High -AffectedObject $label ` -Finding ($issues -join '; ') ` -Recommendation "Enable spoof intelligence, set AuthenticationFailAction to 'Quarantine', enable unauthenticated sender indicators, and honor DMARC policy." ` -ReferenceUrl 'https://aka.ms/mdo-antispoofing' } else { New-METCheckResult -CheckId 'MET-MDO004' -Category MDO -Name 'Anti-Spoofing' ` -Result Pass -Severity High -AffectedObject $label ` -Finding 'Anti-spoofing controls are correctly configured' ` -ReferenceUrl 'https://aka.ms/mdo-antispoofing' } } |