noid-privacy/Modules/ASR/Private/Test-ASRCompliance.ps1

117 lines
4.4 KiB
PowerShell

<#
.SYNOPSIS
Verify ASR rules are correctly applied
.DESCRIPTION
Uses Get-MpPreference to verify all ASR rules are active with correct actions
.PARAMETER ExpectedRules
Array of rule objects with GUID and Action properties
.OUTPUTS
PSCustomObject with verification results
#>
function Test-ASRCompliance {
[CmdletBinding()]
param(
[Parameter(Mandatory = $true)]
[Array]$ExpectedRules
)
$result = [PSCustomObject]@{
Passed = $true
CheckedCount = 0
FailedCount = 0
FailedRules = @()
}
try {
# Get current ASR configuration from Defender
$mpPref = Get-MpPreference -ErrorAction Stop
# Get configured ASR rule IDs and actions
$configuredIds = $mpPref.AttackSurfaceReductionRules_Ids
$configuredActions = $mpPref.AttackSurfaceReductionRules_Actions
if (-not $configuredIds -or $configuredIds.Count -eq 0) {
$result.Passed = $false
$result.FailedCount = $ExpectedRules.Count
Write-Log -Level WARNING -Message "No ASR rules found in Defender configuration" -Module "ASR"
return $result
}
# Create hashtable for quick lookup
$configuredRules = @{}
for ($i = 0; $i -lt $configuredIds.Count; $i++) {
$configuredRules[$configuredIds[$i]] = $configuredActions[$i]
}
# Rules where both BLOCK (1) and AUDIT (2) are considered "Pass"
# These are user-configurable rules where either mode is valid
$flexibleRules = @(
"d1e49aac-8f56-4280-b9ba-993a6d77406c", # PSExec/WMI (Management Tools)
"01443614-cd74-433a-b99e-2ecdc07bfc25" # Prevalence (New/Unknown Software)
)
# Verify each expected rule
foreach ($rule in $ExpectedRules) {
$result.CheckedCount++
if ($configuredRules.ContainsKey($rule.GUID)) {
$actualAction = $configuredRules[$rule.GUID]
# Check if this is a flexible rule (Block or Audit both count as Pass)
$isFlexibleRule = $flexibleRules -contains $rule.GUID
$isActiveMode = $actualAction -in @(1, 2) # Block or Audit
# For flexible rules: Pass if Block OR Audit
# For other rules: Pass only if exact match
$rulePassed = if ($isFlexibleRule) { $isActiveMode } else { $actualAction -eq $rule.Action }
if (-not $rulePassed) {
$result.FailedCount++
$result.Passed = $false
$result.FailedRules += $rule.GUID
$actionName = switch ($actualAction) {
0 { "Disabled" }
1 { "Block" }
2 { "Audit" }
6 { "Warn" }
default { "Unknown($actualAction)" }
}
$expectedName = switch ($rule.Action) {
0 { "Disabled" }
1 { "Block" }
2 { "Audit" }
6 { "Warn" }
default { "Unknown($($rule.Action))" }
}
Write-Log -Level WARNING -Message "Rule '$($rule.Name)' has action $actionName, expected $expectedName" -Module "ASR"
}
}
else {
$result.FailedCount++
$result.Passed = $false
$result.FailedRules += $rule.GUID
Write-Log -Level WARNING -Message "Rule '$($rule.Name)' not found in Defender configuration" -Module "ASR"
}
}
if ($result.Passed) {
Write-Log -Level INFO -Message "ASR compliance check passed - all $($result.CheckedCount) rules verified" -Module "ASR"
}
else {
Write-Log -Level WARNING -Message "ASR compliance check found $($result.FailedCount) issues out of $($result.CheckedCount) rules" -Module "ASR"
}
}
catch {
$result.Passed = $false
$result.FailedCount = $ExpectedRules.Count
Write-Log -Level ERROR -Message "Compliance check failed: $($_.Exception.Message)" -Module "ASR"
}
return $result
}