Skip to content

Commit

Permalink
Merge pull request #417 from Snozzberries/cisaExo
Browse files Browse the repository at this point in the history
CISA EXO Adds
  • Loading branch information
merill authored Aug 25, 2024
2 parents 3ff6457 + e4b0509 commit cd63d3c
Show file tree
Hide file tree
Showing 68 changed files with 1,320 additions and 62 deletions.
4 changes: 4 additions & 0 deletions powershell/Maester.psd1
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,10 @@ FunctionsToExport = 'Add-MtTestResultDetail', 'Clear-MtGraphCache', 'Connect-Mae
'Test-MtCisaAttachmentFileType', 'Test-MtCisaEmailFilterAlternative',
'Test-MtCisaBlockExecutable', 'Test-MtCisaMalwareAction', 'Test-MtCisaMalwareZap',
'Test-MtCisaImpersonation', 'Test-MtCisaImpersonationTip', 'Test-MtCisaMailboxIntelligence',
'Test-MtCisaSpamFilter', 'Test-MtCisaSpamAction', 'Test-MtCisaSpamBypass',
'Test-MtCisaSpamAlternative', 'Test-MtCisaSafeLink', 'Test-MtCisaSafeLinkDownloadScan',
'Test-MtCisaSafeLinkClickTracking', 'Test-MtCisaExoAlert', 'Test-MtCisaExoAlertSiem',
'Test-MtCisaAuditLog', 'Test-MtCisaAuditLogPremium', 'Test-MtCisaAuditLogRetention',
'Get-MtExo', 'Clear-MtExoCache',
'Test-MtConditionalAccessWhatIf',
'Test-MtConnection',
Expand Down
1 change: 1 addition & 0 deletions powershell/internal/Get-MtSkippedReason.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ function Get-MtSkippedReason {
"NotLicensedEntraWorkloadID" { "This test is for tenants that are licensed for Entra Workload ID. See [Entra Workload ID licensing](https://learn.microsoft.com/entra/workload-id/workload-identities-faqs)"; break}
"NotLicensedExoDlp" { "This test is for tenants that are licensed for Exchange Online DLP. See [Microsoft Purview Data Loss Prevention: Data Loss Prevention (DLP) for Exchange Online, SharePoint Online, and OneDrive for Business](https://learn.microsoft.com/en-us/office365/servicedescriptions/microsoft-365-service-descriptions/microsoft-365-tenantlevel-services-licensing-guidance/microsoft-365-security-compliance-licensing-guidance#which-licenses-provide-the-rights-for-a-user-to-benefit-from-the-service-7)"; break}
"NotLicensedMdo" { "This test is for tenants that are licensed for Defender for Office 365 Plan 2. See [Microsoft Defender for Office 365 service description](https://learn.microsoft.com/en-us/office365/servicedescriptions/office-365-advanced-threat-protection-service-description)"; break}
"AdvAudit" { "This test is for tenants that are licensed for Advanced Audit. See [Learn about auditing solutions in Microsoft Purview](https://learn.microsoft.com/en-us/purview/audit-solutions-overview#licensing-requirements)"; break}
"LicensedEntraIDPremium" { "This test is for tenants that are not licensed for any Entra ID Premium license. See [Entra ID licensing](https://learn.microsoft.com/entra/fundamentals/licensing)"; break}
"NotSupported" { "This test relies on capabilities not currently available (e.g., cmdlets that are not available on all platforms, Resolve-DnsName)"; break}
default { $SkippedBecause; break}
Expand Down
2 changes: 1 addition & 1 deletion powershell/public/Add-MtTestResultDetail.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ function Add-MtTestResultDetail {
[Parameter(Mandatory = $false)]
[ValidateSet('NotConnectedAzure', 'NotConnectedExchange', 'NotDotGovDomain', 'NotLicensedEntraIDP1', 'NotConnectedSecurityCompliance',
'NotLicensedEntraIDP2', 'NotLicensedEntraIDGovernance', 'NotLicensedEntraWorkloadID', 'NotLicensedExoDlp', "LicensedEntraIDPremium", 'NotSupported', 'Custom',
'NotLicensedMdo'
'NotLicensedMdo', 'AdvAudit'
)]
# Common reasons for why the test was skipped.
[string] $SkippedBecause,
Expand Down
23 changes: 21 additions & 2 deletions powershell/public/Get-MtLicenseInformation.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ function Get-MtLicenseInformation {
[CmdletBinding()]
param (
[Parameter(ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, Position = 0, Mandatory)]
[ValidateSet('EntraID', 'EntraWorkloadID', 'ExoDlp', 'Mdo')]
[ValidateSet('EntraID', 'EntraWorkloadID', 'ExoDlp', 'Mdo', 'AdvAudit')]
[string] $Product
)

Expand Down Expand Up @@ -78,7 +78,7 @@ function Get-MtLicenseInformation {
Break
}
"Mdo" {
Write-Verbose "Retrieving license SKU for ExoDlp"
Write-Verbose "Retrieving license SKU for Mdo"
$skus = Invoke-MtGraphRequest -RelativeUri "subscribedSkus"
$requiredSkus = @(
#servicePlanId
Expand All @@ -96,6 +96,25 @@ function Get-MtLicenseInformation {
return $LicenseType
Break
}
"AdvAudit" {
Write-Verbose "Retrieving license SKU for AdvAudit"
$skus = Invoke-MtGraphRequest -RelativeUri "subscribedSkus"
$requiredSkus = @(
#servicePlanId
"2f442157-a11c-46b9-ae5b-6e39ff4e5849" #Microsoft 365 Advanced Auditing
)
$LicenseType = $null
foreach($sku in $requiredSkus){
$skuId = $sku -in $skus.skuId
$servicePlanId = $sku -in $skus.servicePlans.servicePlanId
if($skuId -or $servicePlanId){
$LicenseType = "AdvAudit"
}
}
Write-Information "The license type for Advanced Audit is $LicenseType"
return $LicenseType
Break
}

Default {}
}
Expand Down
23 changes: 1 addition & 22 deletions powershell/public/cisa/exchange/Get-MtExo.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -23,35 +23,14 @@
#>
function Get-MtExo {
[Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingInvokeExpression","")]
[Alias(
"Get-MtAcceptedDomain",
"Get-MtRemoteDomain",
"Get-MtTransportConfig",
"Get-MtTransportRule",
"Get-MtOrganizationConfig",
"Get-MtDkimSigningConfig",
"Get-MtSharingPolicy",
"Get-MtDlpComplianceRule",
"Get-MtDlpCompliancePolicy",
"Get-MtMalwareFilterPolicy",
"Get-MtHostedContentFilterPolicy",
"Get-MtAntiPhishPolicy",
"Get-MtSafeAttachmentPolicy",
"Get-MtSafeLinksPolicy",
"Get-MtATPBuiltInProtectionRule",
"Get-MtEOPProtectionPolicyRule",
"Get-MtATPProtectionPolicyRule"
)]
[CmdletBinding()]
[OutputType([string],[object[]],[psobject])]
param(
[string] $Request = ($MyInvocation.InvocationName).Substring(6)
)
<#
$policies = @{
"HostedContentFilterPolicy" = Get-HostedContentFilterPolicy #RecommendedPolicyType -eq "Standard", "Strict"
"SafeAttachmentPolicy" = Get-SafeAttachmentPolicy #RecommendedPolicyType -eq "Standard", "Strict"
"SafeLinksPolicy" = Get-SafeLinksPolicy #RecommendedPolicyType -eq "Standard", "Strict"
"ATPBuiltInProtectionRule" = Get-ATPBuiltInProtectionRule
"EOPProtectionPolicyRule" = Get-EOPProtectionPolicyRule #-Identity "*Preset Security Policy" #IsBuiltInProtection
"ATPProtectionPolicyRule" = Get-ATPProtectionPolicyRule #-Identity "*Preset Security Policy" #IsBuiltInProtection
Expand All @@ -60,7 +39,6 @@ function Get-MtExo {

### To add new commands
### - add them to the hashtable below
### - add them as an alias
### - confirm the command's return type is in OutputType (e.g. (Get-AcceptedDomain).GetType().Name)
$commands = @{
"AcceptedDomain" = "Get-AcceptedDomain"
Expand All @@ -80,6 +58,7 @@ function Get-MtExo {
"ATPBuiltInProtectionRule" = "Get-ATPBuiltInProtectionRule"
"EOPProtectionPolicyRule" = "Get-EOPProtectionPolicyRule"
"ATPProtectionPolicyRule" = "Get-ATPProtectionPolicyRule"
"ProtectionAlert" = "Get-ProtectionAlert"
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ function Test-MtCisaAntiSpamAllowList {
return $null
}

$policy = Get-MtHostedConnectionFilterPolicy
$policy = Get-MtExo -Request HostedConnectionFilterPolicy

$resultPolicy = $policy | Where-Object {`
($_.IPAllowList | Measure-Object).Count -gt 0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ function Test-MtCisaAntiSpamSafeList {
return $null
}

$policy = Get-MtHostedConnectionFilterPolicy
$policy = Get-MtExo -Request HostedConnectionFilterPolicy

$resultPolicy = $policy | Where-Object {`
-not $_.EnableSafeList
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ function Test-MtCisaAttachmentFileType {
return $null
}

$policies = Get-MtMalwareFilterPolicy
$policies = Get-MtExo -Request MalwareFilterPolicy

$fileFilter = $policies | Where-Object { `
$_.EnableFileFilter
Expand Down Expand Up @@ -63,7 +63,7 @@ function Test-MtCisaAttachmentFileType {
$result += "| Standard | $failResult |`n"
}
if ($strict) {
$result += "| Strict | $passResult |`n"
$result += "| Strict | $passResult |`n`n"
} else {
$result += "| Strict | $failResult |`n`n"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ function Test-MtCisaAttachmentFilter {
return $null
}

$policies = Get-MtMalwareFilterPolicy
$policies = Get-MtExo -Request MalwareFilterPolicy

$fileFilter = $policies | Where-Object { `
$_.EnableFileFilter
Expand Down Expand Up @@ -64,7 +64,7 @@ function Test-MtCisaAttachmentFilter {
$result += "| Standard | $failResult |`n"
}
if ($strict) {
$result += "| Strict | $passResult |`n"
$result += "| Strict | $passResult |`n`n"
} else {
$result += "| Strict | $failResult |`n`n"
}
Expand Down
20 changes: 20 additions & 0 deletions powershell/public/cisa/exchange/Test-MtCisaAuditLog.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
Microsoft Purview Audit (Standard) logging SHALL be enabled.

Rationale: Responding to incidents without detailed information about activities that took place slows response actions. Enabling Microsoft Purview Audit (Standard) helps ensure agencies have visibility into user actions. Furthermore, Microsoft Purview Audit (Standard) is required for government agencies by OMB M-21-31 (referred to therein by its former name, Unified Audit Logs).

#### Remediation action:

To enable auditing via the Microsoft Purview compliance portal:
1. Sign in to the **Microsoft Purview compliance portal**.
2. Under **Solutions**, select [**Audit**](https://purview.microsoft.com/audit/auditsearch).
3. If auditing is not enabled, a banner is displayed to notify the administrator to start recording user and admin activity.
4. Click the **Start recording user and admin activity**.

#### Related links

* [Purview portal - Audit search](https://purview.microsoft.com/audit/auditsearch)
* [CISA 17 Audit Logging - MS.EXO.17.1](https://github.com/cisagov/ScubaGear/blob/main/PowerShell/ScubaGear/baselines/exo.md#msexo171v1)
* [CISA ScubaGear Rego Reference](https://github.com/cisagov/ScubaGear/blob/main/PowerShell/ScubaGear/Rego/EXOConfig.rego#L898)

<!--- Results --->
%TestResult%
44 changes: 44 additions & 0 deletions powershell/public/cisa/exchange/Test-MtCisaAuditLog.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<#
.SYNOPSIS
Checks state of purview
.DESCRIPTION
Microsoft Purview Audit (Standard) logging SHALL be enabled.
.EXAMPLE
Test-MtCisaAuditLog
Returns true if audit log enabled
.LINK
https://maester.dev/docs/commands/Test-MtCisaAuditLog
#>
function Test-MtCisaAuditLog {
[CmdletBinding()]
[OutputType([bool])]
param()

if(!(Test-MtConnection ExchangeOnline)){
Add-MtTestResultDetail -SkippedBecause NotConnectedExchange
return $null
}elseif(!(Test-MtConnection SecurityCompliance)){
Add-MtTestResultDetail -SkippedBecause NotConnectedSecurityCompliance
return $null
}

$config = Get-AdminAuditLogConfig

$testResult = $config.UnifiedAuditLogIngestionEnabled

$portalLink = "https://purview.microsoft.com/audit/auditsearch"

if ($testResult) {
$testResultMarkdown = "Well done. Your tenant has [unified audit log enabled]($portalLink).`n`n%TestResult%"
} else {
$testResultMarkdown = "Your tenant does not have [unified audit log enabled]($portalLink).`n`n%TestResult%"
}

Add-MtTestResultDetail -Result $testResultMarkdown

return $testResult
}
16 changes: 16 additions & 0 deletions powershell/public/cisa/exchange/Test-MtCisaAuditLogPremium.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
Microsoft Purview Audit (Premium) logging SHALL be enabled.

Rationale: Standard logging may not include relevant details necessary for visibility into user actions during an incident. Enabling Microsoft Purview Audit (Premium) captures additional event types not included with Standard. Furthermore, it is required for government agencies by OMB M-21-13 (referred to therein by its former name, Unified Audit Logs w/Advanced Features).

#### Remediation action:

To set up Microsoft Purview Audit (Premium), see [Set up Microsoft Purview Audit (Premium) | Microsoft Learn](https://learn.microsoft.com/en-us/purview/audit-premium-setup?view=o365-worldwide).

#### Related links

* [Purview portal - Audit search](https://purview.microsoft.com/audit/auditsearch)
* [CISA 17 Audit Logging - MS.EXO.17.2](https://github.com/cisagov/ScubaGear/blob/main/PowerShell/ScubaGear/baselines/exo.md#msexo172v1)
* [CISA ScubaGear Rego Reference](https://github.com/cisagov/ScubaGear/blob/main/PowerShell/ScubaGear/Rego/EXOConfig.rego#L913)

<!--- Results --->
%TestResult%
66 changes: 66 additions & 0 deletions powershell/public/cisa/exchange/Test-MtCisaAuditLogPremium.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<#
.SYNOPSIS
Checks state of purview
.DESCRIPTION
Microsoft Purview Audit (Premium) logging SHALL be enabled.
.EXAMPLE
Test-MtCisaAuditLogPremium
Returns true if audit log enabled
.LINK
https://maester.dev/docs/commands/Test-MtCisaAuditLogPremium
#>
function Test-MtCisaAuditLogPremium {
[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 AdvAudit)){
Add-MtTestResultDetail -SkippedBecause NotLicensedAdvAudit
return $null
}

Write-Warning "In tenants with a substantial number of mailboxes this test may take time"
$mailboxes = Get-EXOMailbox -Properties AuditOwner

$resultMailboxes = $mailboxes | Where-Object { `
$_.AuditOwner -notcontains "SearchQueryInitiated"
}

$testResult = ($resultMailboxes|Measure-Object).Count -ge 1

$portalLink = "https://purview.microsoft.com/audit/auditsearch"
$passResult = "✅ Pass"
$failResult = "❌ Fail"

if ($testResult) {
$testResultMarkdown = "Well done. Your tenant has [SearchQueryInitiated audit log enabled]($portalLink).`n`n%TestResult%"
} else {
$testResultMarkdown = "Your tenant does not have [SearchQueryInitiated audit log enabled]($portalLink).`n`n%TestResult%"
}

$result = "| Mailbox | SearchQueryInitiated |`n"
$result += "| --- | --- |`n"
foreach($item in $mailboxes | Sort-Object -Property UserPrincipalName){
if($item.Guid -notin $resultMailboxes.Guid){
$result += "| $($item.UserPrincipalName) | $($passResult) |`n"
}else{
$result += "| $($item.UserPrincipalName) | $($failResult) |`n"
}
}

$testResultMarkdown = $testResultMarkdown -replace "%TestResult%", $result

Add-MtTestResultDetail -Result $testResultMarkdown

return $testResult
}
16 changes: 16 additions & 0 deletions powershell/public/cisa/exchange/Test-MtCisaAuditLogRetention.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
Audit logs SHALL be maintained for at least the minimum duration dictated by OMB M-21-31 (Appendix C).

Rationale: Audit logs may no longer be available when needed if they are not retained for a sufficient time. Increased log retention time gives an agency the necessary visibility to investigate incidents that occurred some time ago. OMB M-21-13, Appendix C, Table 5 specifically calls out Unified Audit Logs in the Cloud Azure log category.

#### Remediation action:

To create one or more custom audit retention policies, if the default retention policy is not sufficient for agency needs, follow [Create an audit log retention policy](https://learn.microsoft.com/en-us/purview/audit-log-retention-policies?view=o365-worldwide&tabs=microsoft-purview-portal#create-an-audit-log-retention-policy) instructions. Ensure the duration selected in the retention policies is at least one year, in accordance with OMB M-21-31.

#### Related links

* [Purview portal - Audit policies](https://purview.microsoft.com/audit/auditpolicies)
* [CISA 17 Audit Logging - MS.EXO.17.3](https://github.com/cisagov/ScubaGear/blob/main/PowerShell/ScubaGear/baselines/exo.md#msexo173v1)
* [CISA ScubaGear Rego Reference](https://github.com/cisagov/ScubaGear/blob/main/PowerShell/ScubaGear/Rego/EXOConfig.rego#L928)

<!--- Results --->
%TestResult%
Loading

0 comments on commit cd63d3c

Please sign in to comment.