Files
atap/ATAPAuditor/AuditGroups/SBD - Windows Base Security.ps1
2026-05-11 09:15:08 +02:00

623 lines
18 KiB
PowerShell

$RootPath = Split-Path $MyInvocation.MyCommand.Path -Parent
$RootPath = Split-Path $RootPath -Parent
. "$RootPath\Helpers\AuditGroupFunctions.ps1"
[AuditTest] @{
Id = "SBD-201"
Task = "Get License status."
Test = {
$lcStatus = Get-LicenseStatus $SkipLicenseCheck
if ($lcStatus -eq "Licensed") {
return @{
Message = "Compliant"
Status = "True"
}
}
if ($lcStatus -eq "License check has been skipped.") {
return @{
Message = $lcStatus
Status = "None"
}
}
return @{
Message = "System not licensed."
Status = "False"
}
}
}
[AuditTest] @{
Id = "SBD-202"
Task = "Get amount of active local users on system. (0 - 2: True; 3 - 5: Warning; 6 or higher: False)"
Constraints = @(
@{ "Property" = "DomainRole"; "Values" = "Standalone Workstation", "Member Workstation", "Standalone Server", "Member Server" }
)
Test = {
$users = Get-LocalUser;
$amountOfActiveUser = 0;
foreach ($user in $users) {
if ($user.Enabled -eq $True) {
$amountOfActiveUser ++;
}
}
$status = switch ((Get-LocalUser).Count) {
{ ($amountOfActiveUser -ge 0) -and ($amountOfActiveUser -le 2) } {
# 0, 1, 2
@{
Message = "Compliant"
Status = "True"
}
}
{ ($amountOfActiveUser -gt 2) -and ($amountOfActiveUser -le 5) } {
# 3, 4, 5
@{
Message = "System has $($amountOfActiveUser) local users."
Status = "Warning"
}
}
{ $amountOfActiveUser -gt 5 } {
# 6, ...
@{
Message = "System has 6 or more local users. (Currently $($amountOfActiveUser) users.)"
Status = "False"
}
}
Default {
@{
Message = "Cannot determine the count of local users"
Status = "Error"
}
}
}
return $status
}
}
[AuditTest] @{
Id = "SBD-203"
Task = "Get amount of users and groups in administrators group on system. (0 - 2: True; 3 - 5: Warning; 6 or higher: False)"
Constraints = @(
@{ "Property" = "DomainRole"; "Values" = "Standalone Workstation", "Member Workstation", "Standalone Server", "Member Server" }
)
Test = {
try {
#List all groups
function Get-ADAdminCount($groupname) {
try {
$domain = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()
$root = $domain.GetDirectoryEntry()
$searcher = New-Object System.DirectoryServices.DirectorySearcher($root)
$searcher.Filter = "(&(objectCategory=group)(cn=$groupName))"
$group = $searcher.FindOne()
$groupDN = $group.Properties["distinguishedname"][0]
$searcher.Filter = "(&(objectCategory=user)(memberOf=$groupDN))"
$members = $searcher.FindAll()
return ($members | ForEach-Object { $_.Properties["distinguishedname"] }).Count
}
catch {
return 1
}
}
$allgroups = Get-LocalGroup -SID "S-1-5-32-544" | Get-LocalGroupMember
[int]$ADCount = 0
[int]$localCount = 0
foreach ($entry in $allgroups) {
if ($entry.PrincipalSource -eq "ActiveDirectory") {
$group = $entry.Name -split '\\' | Select-Object -Last 1
$ADCount += Get-ADAdminCount $group
continue;
}
# only applies to Local Groups
$group = $entry.Name -split '\\' | Select-Object -Last 1
try {
$localCount += (Get-LocalGroupMember $group -ErrorAction Stop).Count
}
catch [Microsoft.PowerShell.Commands.NotFoundException] {
$localCount++;
}
}
[int]$amountOfUserAndGroups = $ADCount + $localCount
$status = switch ($amountOfUserAndGroups) {
{ ($amountOfUserAndGroups -ge 0) -and ($amountOfUserAndGroups -le 2) } {
# 0, 1, 2
@{
Message = "Total amount of users: $amountOfUserAndGroups <br/> Amount of local users: $localCount <br/> Amount of domain users: $ADCount <br/>"
Status = "True"
}
}
{ ($amountOfUserAndGroups -gt 2) -and ($amountOfUserAndGroups -le 5) } {
# 3, 4, 5
@{
Message = "Total amount of users: $amountOfUserAndGroups <br/> Amount of local users: $localCount <br/> Amount of domain users: $ADCount <br/>"
Status = "Warning"
}
}
{ $amountOfUserAndGroups -gt 5 } {
# 6, ...
@{
Message = "Total amount of users: $amountOfUserAndGroups <br/> Amount of local users: $localCount <br/> Amount of domain users: $ADCount <br/>"
Status = "False"
}
}
Default {
@{
Message = "Cannot determine the count of admin users. Please check manually."
Status = "Error"
}
}
}
return $status
}
catch {
@{
Message = "Cannot determine the count of admin users. Please check manually."
Status = "Error"
}
}
return $status
}
}
[AuditTest] @{
Id = "SBD-204"
Task = "Ensure the status of the Bitlocker service is 'Running'."
Test = {
if (isWindows8OrNewer) {
if ((Get-WindowsOptionalFeature -Online -FeatureName Bitlocker).State -eq 'Disabled') {
return @{
Message = "Bitlocker feature is not installed."
Status = "False"
}
}
}
$status = switch ((Get-Service BDESVC -ErrorAction SilentlyContinue).Status) {
"Running" {
@{
Message = "Compliant"
Status = "True"
}
}
Default {
@{
Message = "Bitlocker service is not 'Running'."
Status = "False"
}
}
}
return $status
}
}
[AuditTest] @{
Id = "SBD-205"
Task = "Ensure that Bitlocker is activated on all volumes."
Test = {
try {
if (isWindows8OrNewer) {
if ((Get-WindowsOptionalFeature -Online -FeatureName Bitlocker).State -eq 'Disabled') {
return @{
Message = "Bitlocker feature is not installed."
Status = "False"
}
}
$volumes = (Get-Bitlockervolume -ErrorAction Stop).Count
$volumes_fullenc = (Get-Bitlockervolume | Where-Object { $_.VolumeStatus -eq "FullyEncrypted" }).Count
}
else {
$volumes = (Get-CimInstance -Class Win32_EncryptableVolume -namespace Root\CIMV2\Security\MicrosoftVolumeEncryption | Measure-Object).Count
$volumes_fullenc = (Get-CimInstance -Class Win32_EncryptableVolume -namespace Root\CIMV2\Security\MicrosoftVolumeEncryption | Where-Object { $_.ProtectionStatus -eq 1 } | Measure-Object).Count
}
}
catch [System.Runtime.InteropServices.COMException] {
return @{
Message = "Bitlocker status is unknown."
Status = "Error"
}
}
if ($volumes -lt 1) {
return @{
Message = "Bitlocker status is unknown."
Status = "Error"
}
}
$enc_ratio = $volumes_fullenc / $volumes
$status = switch ($enc_ratio) {
{ $enc_ratio -ge 1 } {
@{
Message = "Compliant"
Status = "True"
}
}
{ $enc_ratio -lt 1 } {
@{
Message = "Bitlocker is not activated on all volumes."
Status = "False"
}
}
Default {
@{
Message = "Bitlocker status is unknown."
Status = "Error"
}
}
}
return $status
}
}
[AuditTest] @{
Id = "SBD-206"
Task = "Ensure the status of the Windows Defender service is 'Running'."
Test = {
try {
$status = switch ((Get-Service WinDefend -ErrorAction Stop).Status) {
"Running" {
@{
Message = "Compliant"
Status = "True"
}
}
default {
@{
Message = "Service is not 'Running'."
Status = "False"
}
}
}
return $status
}
catch [Microsoft.PowerShell.Commands.ServiceCommandException] {
return @{
Message = "Current version is not supported."
Status = "None"
}
}
}
}
[AuditTest] @{
Id = "SBD-207"
Task = "Ensure Windows Defender Application Guard is enabled."
Test = {
$isWindows10OrNewer = isWindows10OrNewer
if ($isWindows10OrNewer -eq $false) {
return @{
Message = "System does not support this feature (Windows 10 or newer required)."
Status = "None"
}
}
$state = (Get-WindowsOptionalFeature -Online -FeatureName Windows-Defender-ApplicationGuard).State
if ($state -eq 'Enabled') {
return @{
Message = "Compliant"
Status = "True"
}
}
else {
return @{
Message = "Windows Defender Application Guard is not enabled."
Status = "False"
}
}
}
}
[AuditTest] @{
Id = "SBD-208"
Task = "Ensure the Windows Firewall is enabled on all profiles."
Test = {
if (isWindows8OrNewer) {
if ((Get-NetFirewallProfile | Where-Object { $_.Enabled -eq 'False' } | Measure-Object).Count -gt 0) {
return @{
Message = "Firewall is not enabled on all profiles"
Status = "False"
}
}
else {
return @{
Message = "Compliant"
Status = "True"
}
}
}
else {
$fw = New-Object -ComObject hnetcfg.fwpolicy2
$domain = $fw.FireWallEnabled(1)
$private = $fw.FireWallEnabled(2)
$public = $fw.FireWallEnabled(4)
if ($domain -and $private -and $public) {
return @{
Message = "Compliant"
Status = "True"
}
}
else {
return @{
Message = "Firewall is not enabled on all profiles"
Status = "False"
}
}
}
}
}
[AuditTest] @{
Id = "SBD-209"
Task = "Check if the last successful search for updates was in the past 24 hours."
Test = {
try {
$startdate = (New-Object -com "Microsoft.Update.AutoUpdate").Results.LastSearchSuccessDate
if ($null -eq $startdate) {
return @{
Message = "There was no search found."
Status = "False"
}
}
$tdiff = New-TimeSpan -ErrorAction Stop -Start $startdate -End (Get-Date)
$status = switch ($tdiff.Hours) {
{ ($PSItem -ge 0) -and ($PSItem -le 24) } {
@{
Message = "Compliant"
Status = "True"
}
}
{ ($PSItem -gt 24) -and ($PSItem -le 24 * 5) } {
@{
Message = "Last search for updates was within 5 days."
Status = "Warning"
}
}
Default {
@{
Message = "Last search for updates was more than 5 days ago."
Status = "False"
}
}
}
return $status
}
catch {
return @{
Message = "Not supported on this system."
Status = "None"
}
}
}
}
[AuditTest] @{
Id = "SBD-210"
Task = "Check if the last successful installation of updates was in the past 5 days." # Windows defender definitions do count as updates
Test = {
try {
$startdateObjects = get-wmiobject -class win32_quickfixengineering | Sort-Object -Property InstalledOn -Descending -ErrorAction Stop
$startdate = $startdateObjects[0].InstalledOn
if ($null -eq $startdate) {
$startdate = (New-Object -com "Microsoft.Update.AutoUpdate").Results.LastInstallationSuccessDate
}
if ($null -eq $startdate) {
return @{
Message = "There was no date found."
Status = "False"
}
}
$tdiff = New-TimeSpan -Start $startdate -End (Get-Date)
if ($tdiff.Days -ge 5) {
return @{
Message = "Compliant"
Status = "True"
}
}
else {
$status = switch ($tdiff.Hours) {
{ ($PSItem -ge 0) -and ($PSItem -le 24 * 5) } {
return @{
Message = "Compliant"
Status = "True"
}
}
{ ($PSItem -gt 24 * 5) -and ($PSItem -le 24 * 31) } {
return @{
Message = "Last installation of updates was within the last month."
Status = "Warning"
}
}
Default {
return @{
Message = "Last installation of updates was more than a month ago."
Status = "False"
}
}
}
}
return $status
}
catch [System.Management.Automation.GetValueInvocationException] {
return @{
Message = "Your device needs to restart to install updates"
Status = "None"
}
}
catch {
return @{
Message = "Not supported on this system."
Status = "None"
}
}
}
}
### SBD - 211 Placeholder
### SBD - 212 Placeholder
### SBD - 213 Placeholder
[AuditTest] @{
Id = "SBD-214"
Task = "Ensure Attack Surface Reduction (ASR) rules are enabled."
Test = {
if (isWindows10OrNewer) {
$ruleids = (Get-MpPreference).AttackSurfaceReductionRules_Ids
$ruleactions = (Get-MpPreference).AttackSurfaceReductionRules_Actions
$RuleTable = for ($i = 0; $i -lt $ruleids.Count; $i++) {
[PSCustomObject]@{
RuleId = $ruleids[$i]
RuleAction = $ruleactions[$i]
}
}
$countEnabled = ($RuleTable | Where-Object { $_.RuleAction -eq 1 } | Measure-Object).Count
$status = switch ($countEnabled) {
{ $PSItem -ge 12 } {
@{
Message = "Compliant ($($countEnabled) rules enabled). For more information on ASR rules, check corresponding benchmarks."
Status = "True"
}
}
{ ($PSItem -ge 1) -and ($PSItem -lt 12) } {
@{
Message = "$($countEnabled) ASR rules are activated. For more information on ASR rules, check corresponding benchmarks."
Status = "Warning"
}
}
Default {
@{
Message = "ASR rules are not enabled."
Status = "False"
}
}
}
return $status
}
else {
$windefrunning = CheckWindefRunning
if ((-not $windefrunning)) {
return @{
Message = "This rule requires Windows Defender Antivirus to be enabled."
Status = "None"
}
}
$countEnabled = 0
$Rule1 = @{
Path1 = "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Defender\Windows Defender Exploit Guard\ASR"
Path2 = "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows Defender\Windows Defender Exploit Guard\ASR"
Value = "ExploitGuard_ASR_Rules"
};
$bool = $($Rule1.Path1), $($Rule1.Path2) | Test-MultiplePaths -Key $($Rule1.Value) -ExpectedValue 1
if ($bool.Status -eq "True") {
$countEnabled++;
}
$Rule2 = @{
Path1 = "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Defender\Windows Defender Exploit Guard\ASR\Rules"
Path2 = "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows Defender\Windows Defender Exploit Guard\ASR\Rules"
Value = "26190899-1602-49e8-8b27-eb1d0a1ce869"
};
$bool = $($Rule2.Path1), $($Rule2.Path2) | Test-MultiplePaths -Key $($Rule2.Value) -ExpectedValue 1
if ($bool.Status -eq "True") {
$countEnabled++;
}
$Rule3 = @{
Path1 = "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Defender\Windows Defender Exploit Guard\ASR\Rules"
Path2 = "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows Defender\Windows Defender Exploit Guard\ASR\Rules"
Value = "3b576869-a4ec-4529-8536-b80a7769e899"
};
$bool = $($Rule3.Path1), $($Rule3.Path2) | Test-MultiplePaths -Key $($Rule3.Value) -ExpectedValue 1
if ($bool.Status -eq "True") {
$countEnabled++;
}
$Rule4 = @{
Path1 = "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Defender\Windows Defender Exploit Guard\ASR\Rules"
Path2 = "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows Defender\Windows Defender Exploit Guard\ASR\Rules"
Value = "5beb7efe-fd9a-4556-801d-275e5ffc04cc"
};
$bool = $($Rule4.Path1), $($Rule4.Path2) | Test-MultiplePaths -Key $($Rule4.Value) -ExpectedValue 1
if ($bool.Status -eq "True") {
$countEnabled++;
}
$Rule5 = @{
Path1 = "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Defender\Windows Defender Exploit Guard\ASR\Rules"
Path2 = "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows Defender\Windows Defender Exploit Guard\ASR\Rules"
Value = "75668c1f-73b5-4cf0-bb93-3ecf5cb7cc84"
};
$bool = $($Rule5.Path1), $($Rule5.Path2) | Test-MultiplePaths -Key $($Rule5.Value) -ExpectedValue 1
if ($bool.Status -eq "True") {
$countEnabled++;
}
$Rule6 = @{
Path1 = "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Defender\Windows Defender Exploit Guard\ASR\Rules"
Path2 = "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows Defender\Windows Defender Exploit Guard\ASR\Rules"
Value = "7674ba52-37eb-4a4f-a9a1-f0f9a1619a2c"
};
$bool = $($Rule6.Path1), $($Rule6.Path2) | Test-MultiplePaths -Key $($Rule6.Value) -ExpectedValue 1
if ($bool.Status -eq "True") {
$countEnabled++;
}
$Rule7 = @{
Path1 = "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Defender\Windows Defender Exploit Guard\ASR\Rules"
Path2 = "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows Defender\Windows Defender Exploit Guard\ASR\Rules"
Value = "9e6c4e1f-7d60-472f-ba1a-a39ef669e4b2"
};
$bool = $($Rule7.Path1), $($Rule7.Path2) | Test-MultiplePaths -Key $($Rule7.Value) -ExpectedValue 1
if ($bool.Status -eq "True") {
$countEnabled++;
}
$Rule8 = @{
Path1 = "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Defender\Windows Defender Exploit Guard\ASR\Rules"
Path2 = "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows Defender\Windows Defender Exploit Guard\ASR\Rules"
Value = "b2b3f03d-6a65-4f7b-a9c7-1c7ef74a9ba4"
};
$bool = $($Rule8.Path1), $($Rule8.Path2) | Test-MultiplePaths -Key $($Rule8.Value) -ExpectedValue 1
if ($bool.Status -eq "True") {
$countEnabled++;
}
$Rule9 = @{
Path1 = "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Defender\Windows Defender Exploit Guard\ASR\Rules"
Path2 = "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows Defender\Windows Defender Exploit Guard\ASR\Rules"
Value = "be9ba2d9-53ea-4cdc-84e5-9b1eeee46550"
};
$bool = $($Rule9.Path1), $($Rule9.Path2) | Test-MultiplePaths -Key $($Rule9.Value) -ExpectedValue 1
if ($bool.Status -eq "True") {
$countEnabled++;
}
$Rule10 = @{
Path1 = "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Defender\Windows Defender Exploit Guard\ASR\Rules"
Path2 = "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows Defender\Windows Defender Exploit Guard\ASR\Rules"
Value = "56a863a9-875e-4185-98a7-b882c64b5ce5"
};
$bool = $($Rule10.Path1), $($Rule10.Path2) | Test-MultiplePaths -Key $($Rule10.Value) -ExpectedValue 1
if ($bool.Status -eq "True") {
$countEnabled++;
}
$status = switch ($countEnabled) {
{ $PSItem -ge 10 } {
@{
Message = "Compliant ($($countEnabled) rules enabled). For more information on ASR rules, check corresponding benchmarks."
Status = "True"
}
}
{ ($PSItem -ge 1) -and ($PSItem -lt 10) } {
@{
Message = "$($countEnabled) ASR rules are activated. For more information on ASR rules, check corresponding benchmarks."
Status = "Warning"
}
}
Default {
@{
Message = "ASR rules are not enabled."
Status = "False"
}
}
}
return $status
}
}
}
[AuditTest] @{
Id = "SBD-215"
Task = "Ensure system is on 64-bit version"
Test = {
$is64bit = [Environment]::Is64BitOperatingSystem
if ($is64bit -eq $True) {
return @{
Message = "Compliant"
Status = "True"
}
}
return @{
Message = "System not 64bit."
Status = "False"
}
}
}