Skip to content

Commit

Permalink
Added 4.4
Browse files Browse the repository at this point in the history
  • Loading branch information
soulemike committed Jun 28, 2024
1 parent 9169783 commit 3dac2b4
Show file tree
Hide file tree
Showing 5 changed files with 146 additions and 1 deletion.
2 changes: 1 addition & 1 deletion powershell/Maester.psd1
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ FunctionsToExport = 'Add-MtTestResultDetail', 'Clear-MtGraphCache', 'Connect-Mae
'Test-MtCisaAntiSpamSafeList', 'Test-MtCisaMailboxAuditing',
'Test-MtCisaSpfRestriction', 'Test-MtCisaSpfDirective', 'Test-MtCisaDkim',
'Test-MtCisaDmarcRecordExist', 'Test-MtCisaDmarcRecordReject',
'Test-MtCisaDmarcAggregateCisa',
'Test-MtCisaDmarcAggregateCisa', 'Test-MtCisaDmarcReport',
'Test-MtConditionalAccessWhatIf',
'Test-MtConnection',
'Test-MtEidscaAF01',
Expand Down
20 changes: 20 additions & 0 deletions powershell/public/CISA/exchange/Test-MtCisaDmarcReport.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
An agency point of contact SHOULD be included for aggregate and failure reports.

Rationale: Email spoofing attempts are not inherently visible to domain owners. DMARC provides a mechanism to receive reports of spoofing attempts. Including an agency point of contact gives the agency insight into attempts to spoof their domains.

#### Remediation action:

See MS.EXO.4.1v1 Instructions for an overview of how to publish and check a DMARC record. Ensure the record published includes:

* A point of contact specific to your agency in the RUA field.
* reports@dmarc.cyber.dhs.gov as one of the emails in the RUA field.
* One or more agency-defined points of contact in the RUF field.

#### Related links

* [Exchange admin center - Accepted domains](https://admin.exchange.microsoft.com/#/accepteddomains)
* [CISA 4 Domain-Based Message Authentication, Reporting, and Conformance (DMARC) - MS.EXO.4.4v1](https://github.com/cisagov/ScubaGear/blob/main/PowerShell/ScubaGear/baselines/exo.md#msexo44v1)
* [CISA ScubaGear Rego Reference](https://github.com/cisagov/ScubaGear/blob/main/PowerShell/ScubaGear/Rego/EXOConfig.rego#L252)

<!--- Results --->
%TestResult%
115 changes: 115 additions & 0 deletions powershell/public/CISA/exchange/Test-MtCisaDmarcReport.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
<#
.SYNOPSIS
Checks state of DMARC records for all exo domains
.DESCRIPTION
An agency point of contact SHOULD be included for aggregate and failure reports.
.EXAMPLE
Test-MtCisaDmarcReport
Returns true if DMARC record inlcudes report targets within same domain
#>

Function Test-MtCisaDmarcReport {
[CmdletBinding()]
[OutputType([bool])]
param()

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

$acceptedDomains = Get-AcceptedDomain
<# Parked domains should have DMARC with reject policy
$sendingDomains = $acceptedDomains | Where-Object {`
-not $_.SendingFromDomainDisabled
}
#>
$expandedDomains = @()
foreach($domain in $acceptedDomains){
#This regex does NOT capture for third level domain scenarios
#e.g., example.co.uk; example.ny.us;
$matchDomain = "(?:^|\.)(?'second'\w+.\w+$)"
$dmarcMatch = $domain.domainname -match $matchDomain
if($dmarcMatch){
$expandedDomains += $Matches.second
if($domain.domainname -ne $Matches.second){
$expandedDomains += $domain.domainname
}
}else{
$expandedDomains += $domain.domainname
}
}

$dmarcRecords = @()
foreach($domain in $expandedDomains){
$dmarcRecord = Get-MailAuthenticationRecord -DomainName $domainName -Records DMARC
$dmarcRecord | Add-Member -MemberType NoteProperty -Name "pass" -Value "Failed"
$dmarcRecord | Add-Member -MemberType NoteProperty -Name "reason" -Value ""

$checkType = $dmarcRecord.dmarcRecord.GetType().Name -eq "DMARCRecord"
$hostsAggregate = $dmarcRecord.dmarcRecord.reportAggregate.mailAddress.Host
$hostsForensic = $dmarcRecord.dmarcRecord.reportForensic.mailAddress.Host

if($checkType -and $domain -in $hostsAggregate -and $domain -in $hostsForensic){
$dmarcRecord.pass = "Passed"
}elseif($checkType){
$dmarcRecord.reason = "No target in domain"
}else{
$dmarcRecord.reason = $dmarcRecord.dmarcRecord
}

$dmarcRecords += $dmarcRecord
}

if("Failed" -in $dmarcRecords.pass){
$testResult = $false
}else{
$testResult = $true
}

if($testResult){
$testResultMarkdown = "Well done. Your tenant's domains have in domain report targets. Review report targets.`n`n%TestResult%"
}else{
$testResultMarkdown = "Your tenant's second level domains do not have in domain report targets.`n`n%TestResult%"
}

$passResult = "✅ Pass"
$failResult = "❌ Fail"
$result = "| Domain | Result | Reason | Targets |`n"
$result += "| --- | --- | --- | --- |`n"
foreach ($item in $dmarcRecords | Sort-Object -Property domain) {
switch($item.pass){
"Passed" {$itemResult = $passResult}
"Failed" {$itemResult = $failResult}
}
$aggregates = $item.dmarcRecord.reportForensic.mailAddress
$aggregatesCount = ($aggregates|Measure-Object).Count
if($aggregatesCount -ge 3){
$aggregates = "$($aggregates[0])<br>$($aggregates[1])<br>"
$aggregates += "...$aggregatesCount targets"
}elseif(aggregatesCount -gt 1){
$aggregates = $aggregates -join "<br>"
}
$forensics = $item.dmarcRecord.reportForensic.mailAddress
$forensicsCount = ($forensics|Measure-Object).Count
if($forensicsCount -ge 3){
$forensics = "$($forensics[0])<br>$($forensics[1])<br>"
$forensics += "...$forensicsCount targets"
}elseif(aggregatesCount -gt 1){
$forensics = $forensics -join "<br>"
}

$result += "| $($item.domain) | $($itemResult) | $($item.reason) | Aggregate Reports: $($aggregates) |`n"
$result += "| $($item.domain) | $($itemResult) | $($item.reason) | Forensic Reports: $($forensics) |`n"
}

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

Add-MtTestResultDetail -Result $testResultMarkdown

return $testResult
}
9 changes: 9 additions & 0 deletions tests/CISA/exchange/Test-MtCisaDmarcReport.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Describe "CISA SCuBA" -Tag "MS.EXO", "MS.EXO.4.4", "CISA", "Security", "All" {
It "MS.EXO.4.4: An agency point of contact SHOULD be included for aggregate and failure reports." {
$cisaDmarcReport = Test-MtCisaDmarcReport

if ($null -ne $cisaDmarcReport) {
$cisaDmarcReport | Should -Be $true -Because "DMARC report targets should exist."
}
}
}
1 change: 1 addition & 0 deletions website/docs/tests/cisa/exo.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ See the [Installation guide](/docs/installation#optional-modules-and-permissions
| Test-MtCisaDmarcRecordExist | [MS.EXO.4.1v1](https://github.com/cisagov/ScubaGear/blob/main/PowerShell/ScubaGear/baselines/exo.md#msexo41v1) |
| Test-MtCisaDmarcRecordReject | [MS.EXO.4.2v1](https://github.com/cisagov/ScubaGear/blob/main/PowerShell/ScubaGear/baselines/exo.md#msexo42v1) |
| Test-MtCisaDmarcAggregateCisa | [MS.EXO.4.3v1](https://github.com/cisagov/ScubaGear/blob/main/PowerShell/ScubaGear/baselines/exo.md#msexo43v1) |
| Test-MtCisaDmarcReport | [MS.EXO.4.4v1](https://github.com/cisagov/ScubaGear/blob/main/PowerShell/ScubaGear/baselines/exo.md#msexo44v1) |
| Test-MtCisaSmtpAuthentication | [MS.EXO.5.1v1](https://github.com/cisagov/ScubaGear/blob/main/PowerShell/ScubaGear/baselines/exo.md#msexo51v1) |
| Test-MtCisaContactSharing | [MS.EXO.6.1v1](https://github.com/cisagov/ScubaGear/blob/main/PowerShell/ScubaGear/baselines/exo.md#msexo61v1) |
| Test-MtCisaCalendarSharing | [MS.EXO.6.2v1](https://github.com/cisagov/ScubaGear/blob/main/PowerShell/ScubaGear/baselines/exo.md#msexo62v1) |
Expand Down

0 comments on commit 3dac2b4

Please sign in to comment.