mirror of
https://github.com/NexusOne23/noid-privacy.git
synced 2026-02-07 12:11:53 +01:00
134 lines
5.2 KiB
PowerShell
134 lines
5.2 KiB
PowerShell
function Test-RiskyPorts {
|
||
<#
|
||
.SYNOPSIS
|
||
Test risky firewall ports compliance
|
||
|
||
.DESCRIPTION
|
||
Checks if risky firewall ports (LLMNR, NetBIOS, UPnP/SSDP) are closed
|
||
|
||
.EXAMPLE
|
||
Test-RiskyPorts
|
||
#>
|
||
[CmdletBinding()]
|
||
param()
|
||
|
||
try {
|
||
$result = [PSCustomObject]@{
|
||
Feature = "Risky Firewall Ports"
|
||
Status = "Unknown"
|
||
Details = @()
|
||
OpenPorts = @()
|
||
DisabledRules = 0
|
||
EnabledRules = 0
|
||
Compliant = $false
|
||
}
|
||
|
||
$riskyPorts = @(5355, 137, 138, 139, 1900, 2869)
|
||
|
||
# Detect NoID SSDP firewall block rule for UDP 1900
|
||
$ssdpRuleName = "NoID Privacy - Block SSDP (UDP 1900)"
|
||
$ssdpBlockRule = Get-NetFirewallRule -DisplayName $ssdpRuleName -ErrorAction SilentlyContinue
|
||
$ssdpBlockActive = $false
|
||
if ($ssdpBlockRule -and $ssdpBlockRule.Enabled -eq 'True' -and $ssdpBlockRule.Action -eq 'Block') {
|
||
$ssdpBlockActive = $true
|
||
}
|
||
|
||
# PERFORMANCE FIX: Batch query instead of per-rule queries
|
||
# Old approach: Get-NetFirewallRule | ForEach { Get-NetFirewallPortFilter } = 300 queries × 200ms = 60s!
|
||
# New approach: Get all port filters once, then filter = 2-3s total
|
||
|
||
# Get all inbound firewall rules (pre-filter by direction)
|
||
$inboundRules = Get-NetFirewallRule -Direction Inbound -ErrorAction SilentlyContinue
|
||
|
||
# Get all port filters in one batch query
|
||
$allPortFilters = @{}
|
||
Get-NetFirewallPortFilter -ErrorAction SilentlyContinue | ForEach-Object {
|
||
$allPortFilters[$_.InstanceID] = $_
|
||
}
|
||
|
||
# Now filter rules by risky ports (fast lookup)
|
||
$riskyRules = $inboundRules | Where-Object {
|
||
$portFilter = $allPortFilters[$_.InstanceID]
|
||
if ($portFilter) {
|
||
($portFilter.LocalPort -in $riskyPorts) -or ($portFilter.RemotePort -in $riskyPorts)
|
||
}
|
||
else {
|
||
$false
|
||
}
|
||
}
|
||
|
||
foreach ($rule in $riskyRules) {
|
||
if ($rule.Enabled -eq $true) {
|
||
$portFilter = $allPortFilters[$rule.InstanceID]
|
||
|
||
if ($rule.Action -eq 'Allow') {
|
||
$result.EnabledRules++
|
||
$result.Details += "WARNING: Allow rule '$($rule.DisplayName)' is ENABLED (Port: $($portFilter.LocalPort))"
|
||
}
|
||
else {
|
||
$result.Details += "INFO: Block rule '$($rule.DisplayName)' is ENABLED (Port: $($portFilter.LocalPort))"
|
||
}
|
||
}
|
||
else {
|
||
$result.DisabledRules++
|
||
}
|
||
}
|
||
|
||
# Check actual port listeners
|
||
foreach ($port in $riskyPorts) {
|
||
if ($port -in @(137, 138, 139, 2869)) {
|
||
# TCP ports
|
||
$listener = Get-NetTCPConnection -LocalPort $port -State Listen -ErrorAction SilentlyContinue
|
||
if ($listener) {
|
||
$result.OpenPorts += "TCP $port"
|
||
$result.Details += "OPEN: TCP port $port is LISTENING!"
|
||
}
|
||
}
|
||
else {
|
||
# UDP ports (5355, 1900)
|
||
$listener = Get-NetUDPEndpoint -LocalPort $port -ErrorAction SilentlyContinue
|
||
if ($listener) {
|
||
$result.OpenPorts += "UDP $port"
|
||
$result.Details += "OPEN: UDP port $port is LISTENING!"
|
||
}
|
||
}
|
||
}
|
||
|
||
# Determine compliance
|
||
$udp1900Open = $result.OpenPorts -contains "UDP 1900"
|
||
$otherOpenPorts = $result.OpenPorts | Where-Object { $_ -ne "UDP 1900" }
|
||
|
||
if ($result.OpenPorts.Count -eq 0 -and $result.EnabledRules -eq 0) {
|
||
# Ideal case: no listeners and no allow rules
|
||
$result.Status = "Secure"
|
||
$result.Compliant = $true
|
||
$result.Details += "All risky ports closed and firewall rules disabled"
|
||
}
|
||
elseif ($udp1900Open -and -not $otherOpenPorts -and $result.EnabledRules -eq 0 -and $ssdpBlockActive) {
|
||
# Only open endpoint is UDP 1900, but protected by NoID block rule (inbound)
|
||
$result.Status = "Secure (blocked by firewall)"
|
||
$result.Compliant = $true
|
||
$result.Details += "UDP 1900 is listening locally but inbound traffic is blocked by '$ssdpRuleName'"
|
||
}
|
||
elseif ($result.OpenPorts.Count -eq 0 -and $result.EnabledRules -gt 0) {
|
||
$result.Status = "Partially Secure"
|
||
$result.Compliant = $false
|
||
$result.Details += "Ports closed but $($result.EnabledRules) firewall rules still enabled"
|
||
}
|
||
else {
|
||
$result.Status = "Insecure"
|
||
$result.Compliant = $false
|
||
}
|
||
|
||
return $result
|
||
}
|
||
catch {
|
||
Write-Log -Level ERROR -Message "Failed to test risky ports: $_" -Module "AdvancedSecurity" -Exception $_.Exception
|
||
return [PSCustomObject]@{
|
||
Feature = "Risky Firewall Ports"
|
||
Status = "Error"
|
||
Details = @("Failed to test: $_")
|
||
Compliant = $false
|
||
}
|
||
}
|
||
}
|