RDP Angriffe automatisch mit Hilfe von PowerShell in der Windows Firewall blockieren

Ich habe durch Zufall festgestellt, dass im Eventlog unter “Anwendungs- und Dienstprotokolle\Microsoft\Windows\RemoteDesktopServices-RdpCoreTS\Betriebsbereit” bzw. auf Englisch “Applications and Services Logs\Microsoft\Windows\RemoteDesktopServices-RdpCoreTS\Operational” diverse Einträge mit der ID 140 vorhanden sind, welche Vorfälle dokumentieren bei denen jemand sich versucht hat via RDP anzumelden und dabei einen falschen Benutzernamen und/oder ein falsches Passwort verwendet hat.

Zu allererst habe ich geprüft, ob mein lokaler Administrator-Account (bzw. der Domain-Administrator-Account) deaktiviert ist. Dieser wird für diese Arten von Angriffen in der Regel verwendet. Der Benutzer wird dabei nicht automatisch gesperrt, weil zwischen den Anmeldeversuchen ausreichend Zeit liegt.

Der Text dieser Anmeldeversuche lautet “Fehler einer Verbindung vom Clientcomputer mit der IP-Adresse “xxx.xxx.xxx.xxx”, da der Benutzername oder das Kennwort falsch ist.” bzw. auf Englisch “A connection from the client computer with an IP address of xxx.xxx.xxx.xxx failed because the user name or password is not correct.”.

Ich habe mir ein PowerShell Script geschrieben, was diese Meldungen ausliest und die IP-Adresse zur Blockliste in der Windows Firewall hinzufügt.
Voraussetzung ist, dass diese Regel bereits besteht und mindestens 2 IP-Adressen bereits blockiert sind (ja, auch das ließe sich optimieren, aber es reicht auch so). Um dies zu erstellen einmal die Windows Firewall-Einstellungen öffnen und unter “Eingehende Regeln” eine neue Regel erstellen.

Nun “Benutzerdefiniert” auswählen. Dann “Alle Programme” stehen lassen (einfach auf “weiter“). Anschließend Alle Protokolltypen und Ports stehen lassen (einfach auf “weiter“). Bei “Bereich” dann unter “Für welche Remote-IP-Adressen gilt diese Regel?” die Option “Diese IP-Adressen:” auswählen und z.B. die IPs 1.2.3.4 und 1.2.3.5 hinzufügen. Dies sind Dummyadressen, aber hier müssen für das Skript mindestens 2 IPs eingetragen sein. Dann wieder auf “weiter“.

Nun “Verbindung blockieren” auswählen.

Unter “Profil” alle Profile ausgewählt lassen. Zuletzt noch einen treffenden Namen vergeben. Dieser wird gleich im Script ebenfalls benötigt. Fertig. Nun existiert eine neue eingehende Firewallregel, welche wir gleich weiterverwenden werden.

 

Nun zum Skript. Dies ist der Code, welcher sicherlich optimiert werden kann aber mit den gegebenen Voraussetzungen gut funktioniert. Kopiert es in eine Datei mit der Dateiendung .ps1.

### Variables ###
# The name of the firewall rule in Windows Firewall
$firewallRuleName = "RDP-Angreifer blocken"

# IPs that will not be blacklisted. i.e. your home IP if you are using Dyndns or any other static IP
$whiteList = @(
   [System.Net.Dns]::GetHostAddresses("myhome.dyndns.org").IPAddressToString, #Example for DNS entry
   "89.20.58.68" #Example for IP
   )


### Script ###
Write-Host "Running at $(Get-Date)"
$regExIp = "\d\d?\d?.\d\d?\d?.\d\d?\d?.\d\d?\d?"

# Get the current Eventlogs with the 140 event
$currentAttackers = Get-Winevent Microsoft-Windows-RemoteDesktopServices-RdpCoreTS/Operational | Where-Object {$_.Id -eq 140} | Select Message -ExpandProperty Message

# If there is no response, there are no attacks
if ($currentAttackers -eq $null) {
   Write-Host "No current attackers"
   return
}

# Get each attackermessage and filter the IP from it using the regex above
for ($i = 0; $i -lt $currentAttackers.Count; $i++) {
   if ($currentAttackers[$i] -match $regExIp){
      $currentAttackers[$i] = $Matches[0]
   } 
}

# Get the already known attackers from the firewall rule
$knownAttackers = (Get-NetFirewallRule -DisplayName $firewallRuleName | Get-NetFirewallAddressFilter).RemoteAddress
if ($knownAttackers -eq $null){
   $knownAttackers = @()
}
$knownAttackers = $knownAttackers | Sort-Object -Unique

# Check each logged attacker and check if it is already known
foreach($newAttacker in $currentAttackers) {
   if ($knownAttackers.Contains($newAttacker)) { #If it is known, don't do anything
      continue
   }
   elseif ($whiteList -contains $newAttacker) { #If it is whitelisted, don't do anything
      Write-Host "$newAttacker is dynamically whitelisted"
      continue
   }
   else{ #otherwise it is a new attacker and add it to the blacklist
      $knownAttackers += $newAttacker
      Write-Host "Added $newAttacker"
   }
}

# remove dublicates (should not be there, but anyway...)
$knownAttackers = $knownAttackers | Sort-Object -Unique
Write-Host "$($knownAttackers.Count) IPs on blacklist"

# Setting Firwall rules with all known and all new attackers
Set-NetFirewallRule -DisplayName $firewallRuleName -RemoteAddress $knownAttackers
Write-Host ""

Wenn ihr einen anderen Namen als “RDP-Angreifer blocken” für die Firewallregel gewählt habt, dann muss nun noch die Zeile “$firewallRuleName = “RDP-Angreifer blocken”” entsprechend anpassen.

Wenn ihr nun das Script “als Administrator” ausführt, werden alle IPs, welche im entsprechenden Eventlog mit der ID 140 auftauchen, in der Firewall zu der entsprechenden Regel hinzugefügt und somit weitere Versuche blockiert.

Ich selbst lasse dieses Skript alle paar Minuten via geplanten Task durchlaufen. Innerhalb weniger Stunden sind bereits ca. 600 IP-Adressen zusammengekommen. Bei der Konfiguration des geplanten Tasks darauf achten, dass dieser “mit höchsten Berechtigungen ausführen” konfiguriert ist. Ansonsten kann die Firewallregeln nicht angepasst werden.