diff --git a/powershell/Maester.psd1 b/powershell/Maester.psd1 index 6191011e..0eee986c 100644 --- a/powershell/Maester.psd1 +++ b/powershell/Maester.psd1 @@ -144,6 +144,7 @@ FunctionsToExport = 'Add-MtTestResultDetail', 'Clear-MtGraphCache', 'Connect-Mae 'Test-MtCisSafeAttachment', 'Test-MtCisSafeAttachmentsAtpPolicy', "Test-MtCisOutboundSpamFilterPolicy", + "Test-MtCisSafeAntiPhishingPolicy", 'Test-MtConditionalAccessWhatIf', 'Test-MtConnection', 'Test-MtEidscaControl', diff --git a/powershell/public/cis/Test-MtCisSafeAntiPhishingPolicy.md b/powershell/public/cis/Test-MtCisSafeAntiPhishingPolicy.md new file mode 100644 index 00000000..7981b968 --- /dev/null +++ b/powershell/public/cis/Test-MtCisSafeAntiPhishingPolicy.md @@ -0,0 +1,22 @@ +2.1.7 (L1) Ensure that an anti-phishing policy has been created + +Description: Set up anti-phishing polices to increase this protection, for example by refining +settings to better detect and prevent impersonation and spoofing attacks. + +#### Remediation action: + +To enable Safe Attachments for SharePoint, OneDrive, and Microsoft Teams: + +1. Navigate to Microsoft 365 Defender [https://security.microsoft.com](https://security.microsoft.com) +2. Under **Email & collaboration** select **Policies & rules** +3. Select **Threat policies** then **Anti-Phishing** +4. Select the **Office365 AntiPhish Default (Default)** policy and click **Edit protection settings** +5. Set the **Phishing email threshold** to at least **2 - Aggressive**. + +#### Related links + +* [Microsoft 365 Defender](https://security.microsoft.com) +* [CIS Microsoft 365 Foundations Benchmark v3.1.0 - Page 80](https://www.cisecurity.org/benchmark/microsoft_365) + + +%TestResult% \ No newline at end of file diff --git a/powershell/public/cis/Test-MtCisSafeAntiPhishingPolicy.ps1 b/powershell/public/cis/Test-MtCisSafeAntiPhishingPolicy.ps1 new file mode 100644 index 00000000..5ad47ad7 --- /dev/null +++ b/powershell/public/cis/Test-MtCisSafeAntiPhishingPolicy.ps1 @@ -0,0 +1,118 @@ +<# +.SYNOPSIS +Checks if the anti-phishing policy matches CIS recommendations + +.DESCRIPTION +The anti-phishing policy should be enabled, and the settings for PhishThresholdLevel, EnableMailboxIntelligenceProtection, EnableMailboxIntelligence, EnableSpoofIntelligence controls match CIS recommendations + +.EXAMPLE +Test-MtCisSafeAntiPhishingPolicy + +Returns true if the default anti-phishing policy matches CIS recommendations + +.LINK +https://maester.dev/docs/commands/Test-MtCisSafeAntiPhishingPolicy +#> +function Test-MtCisSafeAntiPhishingPolicy { + [CmdletBinding()] + [OutputType([bool])] + param() + + if (!(Test-MtConnection ExchangeOnline)) { + Add-MtTestResultDetail -SkippedBecause NotConnectedExchange + return $null + } + elseif (!(Test-MtConnection SecurityCompliance)) { + Add-MtTestResultDetail -SkippedBecause NotConnectedSecurityCompliance + return $null + } + elseif ($null -eq (Get-MtLicenseInformation -Product Mdo)) { + Add-MtTestResultDetail -SkippedBecause NotLicensedMdo + return $null + } + + Write-Verbose "Getting Anti Phishing Policy..." + $policies = Get-MtExo -Request AntiPhishPolicy + + # We grab the default policy as that is what CIS checks + $policy = $policies | Where-Object { $_.Name -eq 'Office365 AntiPhish Default' } + + $antiPhishingPolicyCheckList = @() + + # Enabled should be True + $antiPhishingPolicyCheckList += [pscustomobject] @{ + "CheckName" = "Enabled" + "Value" = "True" + } + + # EnableMailboxIntelligenceProtection should be True + $antiPhishingPolicyCheckList += [pscustomobject] @{ + "CheckName" = "EnableMailboxIntelligenceProtection" + "Value" = "True" + } + + # EnableMailboxIntelligence should be True + $antiPhishingPolicyCheckList += [pscustomobject] @{ + "CheckName" = "EnableMailboxIntelligence" + "Value" = "True" + } + + # EnableSpoofIntelligence should be True + $antiPhishingPolicyCheckList += [pscustomobject] @{ + "CheckName" = "EnableSpoofIntelligence" + "Value" = "True" + } + + Write-Verbose "Executing checks" + $failedCheckList = @() + foreach ($check in $antiPhishingPolicyCheckList) { + + $checkResult = $policy | Where-Object { $_.($check.CheckName) -notmatch $check.Value } + + if ($checkResult) { + #If the check fails, add it to the list so we can report on it later + $failedCheckList += $check.CheckName + } + + } + + # Custom check for PhishThresholdLevel + # Because it is not exact match, the above logic won't work. Manual check to see if PhishThresholdLevel is 2 or greater + if ($policy | Where-Object { $_.PhishThresholdLevel -le 1 }) { + #If the check fails, add it to the list so we can report on it later + $failedCheckList += "PhishThresholdLevel" + } + + # We didn't use this in the foreach loop above, but we need to add it now so we get results in the output for the separate check + $antiPhishingPolicyCheckList += [pscustomobject] @{ + "CheckName" = "PhishThresholdLevel" + } + + $testResult = ($failedCheckList | Measure-Object).Count -eq 0 + + $portalLink = "https://security.microsoft.com/antiphishing" + + if ($testResult) { + $testResultMarkdown = "Well done. Your tenants default anti-phishing policy matches CIS recommendations($portalLink).`n`n%TestResult%" + } + else { + $testResultMarkdown = "Your tenants default anti-phishing policy does not match CIS recommendations ($portalLink).`n`n%TestResult%" + } + + + $resultMd = "| Check Name | Result |`n" + $resultMd += "| --- | --- |`n" + foreach ($item in $antiPhishingPolicyCheckList) { + $itemResult = "❌ Fail" + if ($item.CheckName -notin $failedCheckList) { + $itemResult = "✅ Pass" + } + $resultMd += "| $($item.CheckName) | $($itemResult) |`n" + } + + $testResultMarkdown = $testResultMarkdown -replace "%TestResult%", $resultMd + + Add-MtTestResultDetail -Result $testResultMarkdown + + return $testResult +} \ No newline at end of file diff --git a/tests/cis/Test-MtCisSafeAntiPhishingPolicy.Tests.ps1 b/tests/cis/Test-MtCisSafeAntiPhishingPolicy.Tests.ps1 new file mode 100644 index 00000000..e6293af0 --- /dev/null +++ b/tests/cis/Test-MtCisSafeAntiPhishingPolicy.Tests.ps1 @@ -0,0 +1,10 @@ +Describe "CIS" -Tag "CIS 2.1.7", "L1", "CIS E5 Level 1", "CIS E5", "CIS", "Security", "All", "CIS M365 v3.1.0" { + It "2.1.7 (L1) Ensure that an anti-phishing policy has been created (Only Checks Default Policy)" { + + $result = Test-MtCisSafeAntiPhishingPolicy + + if ($null -ne $result) { + $result | Should -Be $true -Because "the default anti-phishing policy is enabled." + } + } +} \ No newline at end of file diff --git a/website/docs/tests/cis/readme.md b/website/docs/tests/cis/readme.md index ba2a8a1b..5fc25b1d 100644 --- a/website/docs/tests/cis/readme.md +++ b/website/docs/tests/cis/readme.md @@ -45,5 +45,6 @@ It is important to note that a number of the policy checks ONLY check the defaul | Test-MtCisSafeAttachment | 2.1.4 (L2) Ensure Safe Attachments policy is enabled | | Test-MtCisSafeAttachmentsAtpPolicy | 2.1.5 (L2) Ensure Safe Attachments for SharePoint, OneDrive, and Microsoft Teams is Enabled | | Test-MtCisOutboundSpamFilterPolicy | 2.1.6 (L1) Ensure Exchange Online Spam Policies are set to notify administrators | +| Test-MtCisSafeAntiPhishingPolicy | 2.1.7 (L1) Ensure that an anti-phishing policy has been created | TBD in this case refers to CIS "manual" checks. It might be possible to automate these, but skipping for now to focus on automated checks. \ No newline at end of file