Anavem
Languageen
Comment détecter et bloquer les attaques par force brute sur Windows Server avec PowerShell

Comment détecter et bloquer les attaques par force brute sur Windows Server avec PowerShell

Créez des scripts PowerShell automatisés pour détecter les attaques par force brute RDP via l'analyse des journaux d'événements Windows et bloquer automatiquement les IP malveillantes en utilisant les règles du pare-feu Windows Defender.

24 avril 2026 18 min
hardpowershell 7 étapes 18 min

Pourquoi mettre en œuvre une protection contre la force brute basée sur PowerShell sur Windows Server ?

Les serveurs Windows exécutant les services de bureau à distance font face à des attaques par force brute constantes de la part de bots automatisés recherchant des identifiants faibles. Les solutions traditionnelles nécessitent souvent des outils tiers coûteux ou des configurations complexes. PowerShell offre une approche native et économique pour détecter et bloquer automatiquement ces attaques en utilisant les fonctionnalités intégrées de Windows.

Comment l'analyse des journaux d'événements détecte-t-elle les attaques par force brute RDP ?

Le journal des événements de sécurité Windows capture chaque tentative d'authentification échouée sous l'ID d'événement 4625. En analysant ces événements avec PowerShell, vous pouvez identifier des schémas indiquant des attaques par force brute - généralement plusieurs tentatives échouées depuis la même adresse IP dans un court laps de temps. L'avantage clé est de tirer parti de l'infrastructure de journalisation Windows existante sans logiciel supplémentaire.

Qu'est-ce qui rend la gestion automatisée des règles de pare-feu efficace ?

Les attaquants modernes utilisent souvent des réseaux distribués, rendant le blocage individuel des IP moins efficace. Ce tutoriel met en œuvre un blocage au niveau du sous-réseau en convertissant les IP attaquantes en sous-réseaux /16, offrant une protection plus large tout en maintenant les performances. Le cycle de nettoyage automatisé de 24 heures empêche le blocage permanent des adresses IP dynamiques tout en garantissant que les attaquants persistants sont rapidement re-bloqués.

Vous construirez un système de protection complet en utilisant des scripts PowerShell qui surveillent l'ID d'événement 4625, identifient les schémas d'attaque, mettent à jour automatiquement les règles du pare-feu Windows Defender et maintiennent le système grâce à des tâches planifiées. Cette approche offre une protection de niveau entreprise en utilisant uniquement les capacités natives de Windows.

Guide de mise en oeuvre

Procédure complète

01

Activer la journalisation des événements de sécurité pour les tentatives de connexion échouées

Tout d'abord, assurez-vous que Windows enregistre les tentatives d'authentification échouées. Ouvrez la Console de gestion des stratégies de groupe et accédez aux paramètres de la stratégie d'audit.

gpedit.msc

Accédez à Configuration de l'ordinateur > Paramètres Windows > Paramètres de sécurité > Stratégies locales > Stratégie d'audit. Activez Audit des événements de connexion pour les réussites et les échecs.

Alternativement, configurez cela via PowerShell :

auditpol /set /category:"Logon/Logoff" /success:enable /failure:enable

Appliquez les modifications immédiatement :

gpupdate /force

Vérification : Vérifiez que l'ID d'événement 4625 apparaît dans le journal des événements de sécurité après une tentative RDP échouée :

Get-WinEvent -FilterHashtable @{LogName='Security'; ID=4625} -MaxEvents 5
Conseil pro : Activez la journalisation du pare-feu pour obtenir des données d'attaque supplémentaires. Exécutez netsh advfirewall set allprofiles logging filename C:\Windows\System32\LogFiles\Firewall\pfirewall.log
02

Créer la règle de pare-feu de base pour bloquer les attaquants

Créez une règle de pare-feu désactivée que votre script PowerShell remplira avec des adresses IP malveillantes. Cette approche empêche de bloquer accidentellement tout le trafic.

Ouvrez le Pare-feu Windows Defender avec sécurité avancée en tant qu'administrateur :

wf.msc

Créez une nouvelle règle entrante via PowerShell :

New-NetFirewallRule -DisplayName "BlockAttackers" -Direction Inbound -Protocol TCP -Action Block -Enabled False -RemoteAddress "127.0.0.1"

La règle commence désactivée avec une adresse IP de remplacement. Votre script mettra à jour le champ RemoteAddress avec les IP des attaquants réels.

Vérification : Confirmez que la règle existe mais est désactivée :

Get-NetFirewallRule -DisplayName "BlockAttackers" | Select-Object DisplayName, Enabled, Direction
Avertissement : Ne jamais activer une règle de pare-feu avec un champ RemoteAddress vide ou un caractère générique (*) - cela bloquera TOUT le trafic entrant et vous exclura du serveur.
03

Construire le script de détection de force brute

Créez le script PowerShell principal qui analyse les entrées Event ID 4625 et identifie les modèles de force brute. Enregistrez-le sous C:\Scripts\RDP_BruteForce_Detection.ps1 :

# Script de détection et de blocage de force brute RDP
param(
    [int]$Hours = 1,
    [int]$AttackThreshold = 5
)

# Obtenez les tentatives de connexion RDP échouées des dernières heures spécifiées
$FailedLogons = Get-WinEvent -FilterHashtable @{
    LogName='Security'
    ID=4625
    StartTime=(Get-Date).AddHours(-$Hours)
} -ErrorAction SilentlyContinue | ForEach-Object {
    $EventXml = ([xml]$_.ToXml()).Event
    [PSCustomObject]@{
        UserName = ($EventXml.EventData.Data | Where-Object { $_.Name -eq 'TargetUserName' }).'#text'
        IpAddress = ($EventXml.EventData.Data | Where-Object { $_.Name -eq 'IpAddress' }).'#text'
        EventDate = [DateTime]$EventXml.System.TimeCreated.SystemTime
        LogonType = ($EventXml.EventData.Data | Where-Object { $_.Name -eq 'LogonType' }).'#text'
    }
}

# Filtrer pour les tentatives RDP (LogonType 10) et regrouper par IP
$AttackerIPs = $FailedLogons | Where-Object { 
    $_.LogonType -eq '10' -and 
    $_.IpAddress -ne '-' -and 
    $_.IpAddress -ne '127.0.0.1' 
} | Group-Object IpAddress | Where-Object { $_.Count -ge $AttackThreshold }

if ($AttackerIPs) {
    Write-Host "Trouvé $($AttackerIPs.Count) adresses IP attaquantes :" -ForegroundColor Red
    $AttackerIPs | ForEach-Object {
        Write-Host "  $($_.Name): $($_.Count) tentatives échouées" -ForegroundColor Yellow
    }
    return $AttackerIPs.Name
} else {
    Write-Host "Aucune attaque de force brute détectée dans les dernières $Hours heure(s)" -ForegroundColor Green
    return @()
}

Créez d'abord le répertoire Scripts :

New-Item -Path "C:\Scripts" -ItemType Directory -Force

Vérification : Testez le script manuellement :

C:\Scripts\RDP_BruteForce_Detection.ps1 -Hours 24 -AttackThreshold 3
04

Créer la logique de blocage IP et de conversion de sous-réseau

Construisez le script qui convertit les IPs attaquantes individuelles en sous-réseaux /16 et met à jour la règle du pare-feu. Enregistrez sous C:\Scripts\Block_Attackers.ps1 :

# Script de blocage des attaquants avec conversion de sous-réseau
param(
    [string[]]$AttackerIPs,
    [string]$RuleName = "BlockAttackers"
)

if (-not $AttackerIPs -or $AttackerIPs.Count -eq 0) {
    Write-Host "Aucune IP à bloquer" -ForegroundColor Green
    return
}

# Convertir les IPs en sous-réseaux /16 pour une protection plus large
$Subnets = @()
foreach ($IP in $AttackerIPs) {
    if ($IP -match '^(\d+\.\d+)\.(\d+)\.(\d+)$') {
        $Subnet = "$($matches[1]).0.0/16"
        if ($Subnets -notcontains $Subnet) {
            $Subnets += $Subnet
            Write-Host "Conversion de $IP en sous-réseau $Subnet" -ForegroundColor Cyan
        }
    }
}

# Obtenir les adresses bloquées existantes de la règle du pare-feu
$ExistingRule = Get-NetFirewallRule -DisplayName $RuleName -ErrorAction SilentlyContinue
if ($ExistingRule) {
    $ExistingAddresses = (Get-NetFirewallAddressFilter -AssociatedNetFirewallRule $ExistingRule).RemoteAddress
    
    # Combiner les sous-réseaux existants et nouveaux, supprimer les doublons
    $AllSubnets = ($ExistingAddresses + $Subnets) | Where-Object { $_ -ne "127.0.0.1" } | Sort-Object -Unique
    
    # Mettre à jour la règle du pare-feu avec tous les sous-réseaux
    Set-NetFirewallRule -DisplayName $RuleName -RemoteAddress $AllSubnets
    
    # Activer la règle maintenant qu'elle a des adresses IP valides
    Set-NetFirewallRule -DisplayName $RuleName -Enabled True
    
    Write-Host "Règle du pare-feu mise à jour avec $($AllSubnets.Count) sous-réseaux bloqués" -ForegroundColor Green
    Write-Host "Sous-réseaux bloqués : $($AllSubnets -join ', ')" -ForegroundColor Yellow
    
    # Enregistrer l'action dans le journal des événements
    Write-EventLog -LogName Application -Source "RDC Brute Force Prevention Script" -EventId 1001 -EntryType Information -Message "Sous-réseaux bloqués : $($AllSubnets -join ', ')"
} else {
    Write-Host "Règle du pare-feu '$RuleName' non trouvée" -ForegroundColor Red
}

Enregistrez la source d'événements personnalisée pour la journalisation :

New-EventLog -LogName Application -Source "RDC Brute Force Prevention Script" -ErrorAction SilentlyContinue

Vérification : Testez le script de blocage avec une IP de test :

C:\Scripts\Block_Attackers.ps1 -AttackerIPs @("192.168.1.100")
05

Mettre en œuvre le nettoyage automatique des règles pour des cycles de 24 heures

Créez un script de nettoyage qui efface les IP bloquées toutes les 24 heures pour éviter le blocage permanent des adresses IP dynamiques. Enregistrez sous C:\Scripts\Clear_Blocked_IPs.ps1 :

# Script de nettoyage des IP bloquées - S'exécute quotidiennement à minuit
param(
    [string]$RuleName = "BlockAttackers"
)

# Réinitialiser la règle de pare-feu à une IP de remplacement et la désactiver
Set-NetFirewallRule -DisplayName $RuleName -RemoteAddress "127.0.0.1" -Enabled False

# Journaliser l'action de nettoyage
Write-EventLog -LogName Application -Source "RDC Brute Force Prevention Script" -EventId 1002 -EntryType Information -Message "Effacé toutes les IP bloquées de la règle de pare-feu à $(Get-Date)"

Write-Host "Effacé toutes les IP bloquées de la règle de pare-feu '$RuleName'" -ForegroundColor Green

Créez le script maître qui combine détection et blocage. Enregistrez sous C:\Scripts\RDP_Protection_Master.ps1 :

# Script maître de protection RDP
$AttackerIPs = & "C:\Scripts\RDP_BruteForce_Detection.ps1" -Hours 1 -AttackThreshold 5

if ($AttackerIPs -and $AttackerIPs.Count -gt 0) {
    & "C:\Scripts\Block_Attackers.ps1" -AttackerIPs $AttackerIPs
}

# Vérifier s'il est minuit (dans les 5 minutes) et effacer les règles
$CurrentTime = Get-Date
if ($CurrentTime.Hour -eq 0 -and $CurrentTime.Minute -lt 5) {
    & "C:\Scripts\Clear_Blocked_IPs.ps1"
}

Vérification : Testez le flux de travail complet :

C:\Scripts\RDP_Protection_Master.ps1
Astuce pro : Utilisez des cycles de nettoyage de 24 heures pour gérer les adresses IP dynamiques des utilisateurs légitimes qui pourraient être temporairement bloqués. Les attaquants persistants seront rapidement re-bloqués.
06

Configurer la tâche planifiée pour l'exécution automatisée

Configurez une tâche planifiée pour exécuter le script de protection toutes les 5 minutes. Utilisez PowerShell pour créer la tâche de manière programmatique :

# Créer une tâche planifiée pour la protection RDP
$TaskName = "RDP_BruteForce_Protection"
$ScriptPath = "C:\Scripts\RDP_Protection_Master.ps1"

# Définir l'action
$Action = New-ScheduledTaskAction -Execute "PowerShell.exe" -Argument "-WindowStyle Hidden -ExecutionPolicy Bypass -File `"$ScriptPath`""

# Définir le déclencheur (toutes les 5 minutes)
$Trigger = New-ScheduledTaskTrigger -Once -At (Get-Date) -RepetitionInterval (New-TimeSpan -Minutes 5) -RepetitionDuration (New-TimeSpan -Days 365)

# Définir les paramètres de la tâche
$Settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -StartWhenAvailable -RunOnlyIfNetworkAvailable

# Créer la tâche
Register-ScheduledTask -TaskName $TaskName -Action $Action -Trigger $Trigger -Settings $Settings -User "SYSTEM" -RunLevel Highest -Force

Vérifiez que la tâche a été créée et est en cours d'exécution :

Get-ScheduledTask -TaskName "RDP_BruteForce_Protection" | Select-Object TaskName, State, LastRunTime

Démarrez la tâche manuellement pour tester :

Start-ScheduledTask -TaskName "RDP_BruteForce_Protection"

Vérification : Vérifiez l'historique des tâches et les journaux d'événements :

# Vérifiez l'historique d'exécution des tâches
Get-WinEvent -FilterHashtable @{LogName='Microsoft-Windows-TaskScheduler/Operational'; ID=200} -MaxEvents 5

# Vérifiez nos entrées de journal d'événements personnalisées
Get-WinEvent -FilterHashtable @{LogName='Application'; ProviderName='RDC Brute Force Prevention Script'} -MaxEvents 10
07

Tester et valider le système de protection complet

Effectuez des tests complets pour vous assurer que le système fonctionne correctement sans bloquer le trafic légitime.

Tout d'abord, simulez une attaque par force brute en générant des événements de connexion échoués (utilisez un compte de test) :

# Générer des événements de connexion échoués pour le test (exécuter depuis une autre machine)
for ($i = 1; $i -le 10; $i++) {
    try {
        $cred = Get-Credential -UserName "testuser" -Message "Entrez un mauvais mot de passe"
        Enter-PSSession -ComputerName "YourServerIP" -Credential $cred
    } catch {
        Write-Host "Tentative échouée $i" -ForegroundColor Red
    }
    Start-Sleep -Seconds 2
}

Surveillez la détection en temps réel :

# Surveiller les nouvelles entrées Event ID 4625
Get-WinEvent -FilterHashtable @{LogName='Security'; ID=4625; StartTime=(Get-Date).AddMinutes(-10)} | 
    Select-Object TimeCreated, @{Name='SourceIP';Expression={([xml]$_.ToXml()).Event.EventData.Data | Where-Object {$_.Name -eq 'IpAddress'} | Select-Object -ExpandProperty '#text'}}

Vérifiez que la règle de pare-feu est remplie et activée :

# Vérifier l'état de la règle de pare-feu
$Rule = Get-NetFirewallRule -DisplayName "BlockAttackers"
$Addresses = Get-NetFirewallAddressFilter -AssociatedNetFirewallRule $Rule

Write-Host "Règle activée : $($Rule.Enabled)" -ForegroundColor $(if($Rule.Enabled){'Green'}else{'Red'})
Write-Host "Adresses bloquées : $($Addresses.RemoteAddress -join ', ')" -ForegroundColor Yellow

Testez la connectivité depuis une plage d'IP bloquée (si possible) :

# Depuis le serveur, tester si la règle bloque réellement
Test-NetConnection -ComputerName "localhost" -Port 3389 -InformationLevel Detailed

Vérification : Vérifiez l'état complet du système :

# Vérification complète de l'état du système
Write-Host "=== État de la protection contre la force brute RDP ===" -ForegroundColor Cyan
Write-Host "Tâche planifiée : $(if((Get-ScheduledTask -TaskName 'RDP_BruteForce_Protection').State -eq 'Ready'){'En cours'}else{'Non en cours'})" -ForegroundColor Green
Write-Host "Règle de pare-feu : $(if((Get-NetFirewallRule -DisplayName 'BlockAttackers').Enabled){'Activée'}else{'Désactivée'})" -ForegroundColor Green
Write-Host "Journalisation des événements : $(if((auditpol /get /category:'Logon/Logoff' | Select-String 'Failure.*Success').Count -gt 0){'Activée'}else{'Désactivée'})" -ForegroundColor Green
Write-Host "Blocages récents : $((Get-WinEvent -FilterHashtable @{LogName='Application'; ProviderName='RDC Brute Force Prevention Script'} -MaxEvents 5 -ErrorAction SilentlyContinue).Count)" -ForegroundColor Yellow
Avertissement : Testez toujours à partir d'une méthode de connexion secondaire (accès console, VPN ou IP différente) avant de déployer en production. Une règle mal configurée pourrait vous verrouiller hors de votre propre serveur.

Questions Fréquentes

Combien de tentatives RDP échouées devraient déclencher la protection contre la force brute ?+
Le seuil optimal est de 5 à 10 tentatives échouées en 3 à 5 minutes à partir de la même adresse IP. Cet équilibre empêche les faux positifs des utilisateurs légitimes faisant des fautes de frappe tout en détectant les attaques automatisées. Vous pouvez ajuster le paramètre AttackThreshold dans le script de détection en fonction des besoins de votre environnement et des comportements des utilisateurs.
Cette solution PowerShell bloquera-t-elle les utilisateurs légitimes qui se trompent de mot de passe ?+
Le cycle de compensation automatique de 24 heures empêche le blocage permanent des utilisateurs légitimes. Si un utilisateur est bloqué en raison de plusieurs tentatives échouées, il retrouvera l'accès dans les 24 heures. Pour un déblocage immédiat, les administrateurs peuvent manuellement retirer les IP de la règle du pare-feu ou la désactiver temporairement. La conversion de sous-réseau (/16) signifie que des plages entières d'IP sont bloquées, donc considérez la distribution des IP de votre base d'utilisateurs.
Ce script peut-il détecter des attaques par force brute sur des services autres que RDP ?+
Oui, mais nécessite une modification. Le script filtre actuellement pour LogonType 10 (RDP). Vous pouvez l'adapter pour d'autres services en changeant le filtre LogonType : LogonType 2 pour les connexions interactives à la console, LogonType 3 pour les connexions réseau (partages SMB/fichiers), ou LogonType 8 pour le texte clair réseau (IIS). Chaque service peut utiliser des ID d'événements différents et nécessiter une logique de filtrage spécifique.
Que se passe-t-il si le script PowerShell bloque ma propre adresse IP ?+
Toujours maintenir des méthodes d'accès alternatives avant le déploiement : accès console, connexion VPN ou réseau de gestion. En cas de verrouillage, accédez au serveur via ces alternatives et désactivez soit la règle de pare-feu 'BlockAttackers', soit retirez votre IP du champ RemoteAddress. Le script inclut des protections contre le blocage de localhost (127.0.0.1) mais ne peut pas empêcher le blocage de votre IP externe.
Quel est l'impact sur les performances du système de la surveillance continue des journaux d'événements ?+
Impact minimal lorsqu'il est correctement configuré. Le script s'exécute toutes les 5 minutes et ne requête que la dernière heure des entrées du journal des événements de sécurité avec un filtrage spécifique (ID d'événement 4625). Sur les serveurs occupés, envisagez d'augmenter l'intervalle à 10-15 minutes ou de mettre en œuvre un filtrage plus agressif. La cmdlet Get-WinEvent avec FilterHashtable est optimisée pour la performance par rapport aux anciennes méthodes Get-EventLog.

Discussion

Partagez vos réflexions et analyses

Connectez-vous pour participer