Błąd RDP: odblokowanie zablokowanego konta Windows (PowerShell)

Opublikowano Zaktualizowano 6 min czytania

Zablokowane konto Windows przy logowaniu RDP to zwykle skutek zautomatyzowanych ataków. Ten skrypt PowerShell odblokuje konto, pokaże źródłowe adresy IP i dostosuje zasady blokady.

Twoje logowanie przez Pulpit zdalny nagle przestaje działać, a Windows wyświetla mniej więcej taki komunikat: „Ze względów bezpieczeństwa konto użytkownika zostało zablokowane, ponieważ podjęto zbyt wiele prób logowania lub prób zmiany hasła.” Zadziałały wtedy zasady blokady konta systemu Windows. Przyczyna jest prawie zawsze ta sama: ktoś albo coś bombarduje twój dostęp RDP próbami logowania z internetu.

W tym poradniku pokazujemy, jak odblokować konto, jak ustalić, które adresy IP wywołują blokady, oraz jak zmienić albo całkiem wyłączyć zasady blokady. Wszystko to załatwia jeden skrypt PowerShell, bez klikania w edytorze zasad grupy.

Dlaczego konto Windows zostaje zablokowane przy logowaniu RDP?

Windows liczy nieudane próby logowania i blokuje konto, gdy tylko zostanie osiągnięty ustawiony próg. Ta funkcja ochronna ma sens, ale staje się problemem w chwili, gdy port RDP jest wystawiony na internet: zautomatyzowane boty przez całą dobę próbują wtedy kolejnych haseł i blokują przy okazji dokładnie to konto, na którym chcesz pracować.

Zachowanie blokady określają trzy wartości:

  • Próg blokady: liczba nieudanych prób, po której konto zostaje zablokowane
  • Czas trwania blokady: liczba minut, przez które konto pozostaje zablokowane
  • Okno obserwacji: liczba minut, w ciągu których nieudane próby są sumowane

Otwórz PowerShell jako administrator

Otwórz Windows PowerShell jako administrator. Kliknij w menu Start prawym przyciskiem myszy pozycję „Windows PowerShell” i wybierz „Uruchom jako administrator”. Bez podwyższonych uprawnień skrypt nie odblokuje konta ani nie zmieni zasad.

Skrypt: odblokowanie konta i namierzenie atakujących

W sekcji „Ustawienia” dopasuj nazwę konta oraz wybrane wartości, a następnie wklej skrypt do PowerShella:

#Requires -RunAsAdministrator

# KernelHost: odblokowanie zablokowanego konta Windows RDP i znalezienie przyczyny
# Uruchamiaj w Windows PowerShell jako administrator.

# ----------------------------------------------------------------------------
#  Ustawienia: dopasuj do swojego środowiska
# ----------------------------------------------------------------------------
$Username = 'Administrator'   # konto lokalne, które ma zostać odblokowane

$ApplyPolicy      = $true     # $false, jeśli zasady blokady mają pozostać bez zmian
$LockoutThreshold = 0         # nieudane próby do blokady (0 = blokada WYŁĄCZONA, patrz tekst)
$LockoutDuration  = 15        # minuty, przez które konto pozostaje zablokowane
$LockoutWindow    = 15        # minuty, w ciągu których liczone są nieudane próby
# ----------------------------------------------------------------------------

# 1) Pokaż aktualne zasady blokady
Write-Host "`n=== 1) Aktualne zasady blokady ===" -ForegroundColor Cyan
net accounts | Select-String 'Lockout|Sperr'

# 2) Odblokuj konto
Write-Host "`n=== 2) Odblokowanie konta '$Username' ===" -ForegroundColor Cyan
try {
    $user = [ADSI]"WinNT://$env:COMPUTERNAME/$Username,user"
    if ($user.InvokeGet('IsAccountLocked')) {
        $user.InvokeSet('IsAccountLocked', $false)
        $user.SetInfo()
        Write-Host "  Konto '$Username' było zablokowane i jest teraz ODBLOKOWANE." -ForegroundColor Green
    } else {
        Write-Host "  Konto '$Username' nie jest zablokowane." -ForegroundColor Yellow
    }
} catch {
    Write-Warning "  Nie udało się odblokować konta '$Username': $($_.Exception.Message)"
}

# 3) Opcjonalnie: dostosuj lub wyłącz zasady blokady
if ($ApplyPolicy) {
    Write-Host "`n=== 3) Ustawianie zasad blokady ===" -ForegroundColor Cyan
    if ($LockoutThreshold -eq 0) {
        net accounts /lockoutthreshold:0 | Out-Null
        Write-Host "  Blokada konta WYŁĄCZONA (próg 0)." -ForegroundColor Yellow
        Write-Host "  Ogranicz teraz RDP na firewallu do własnego adresu IP." -ForegroundColor Yellow
    } else {
        net accounts /lockoutthreshold:$LockoutThreshold /lockoutduration:$LockoutDuration /lockoutwindow:$LockoutWindow | Out-Null
        Write-Host "  Próg=$LockoutThreshold  Czas=$LockoutDuration min  Okno=$LockoutWindow min" -ForegroundColor Green
    }
}

# 4) Kto wywołuje blokady? (źródła ataków na RDP)
Write-Host "`n=== 4a) Ostatnie zdarzenia blokady (Security-ID 4740) ===" -ForegroundColor Cyan
Get-WinEvent -FilterHashtable @{LogName='Security'; Id=4740} -MaxEvents 10 -ErrorAction SilentlyContinue |
    ForEach-Object {
        $x = [xml]$_.ToXml()
        [pscustomobject]@{
            Czas             = $_.TimeCreated
            ZablokowaneKonto = ($x.Event.EventData.Data | Where-Object { $_.Name -eq 'TargetUserName' }).'#text'
            Źródło           = ($x.Event.EventData.Data | Where-Object { $_.Name -eq 'TargetDomainName' }).'#text'
        }
    } | Format-Table -AutoSize

Write-Host "=== 4b) Najczęstsze źródłowe adresy IP nieudanych logowań, ostatnie 24 h (Security-ID 4625) ===" -ForegroundColor Cyan
$since = (Get-Date).AddHours(-24)
Get-WinEvent -FilterHashtable @{LogName='Security'; Id=4625; StartTime=$since} -ErrorAction SilentlyContinue |
    ForEach-Object {
        ([xml]$_.ToXml()).Event.EventData.Data |
            Where-Object { $_.Name -eq 'IpAddress' } | Select-Object -ExpandProperty '#text'
    } |
    Where-Object { $_ -and $_ -ne '-' } |
    Group-Object | Sort-Object Count -Descending | Select-Object -First 10 |
    Format-Table Count, @{N='IP źródłowe'; E={$_.Name}} -AutoSize

Co dokładnie robi ten skrypt

  1. Pokazuje poleceniem net accounts aktualne zasady blokady konta, czyli próg, czas trwania blokady i okno obserwacji.
  2. Odblokowuje konto wpisane w $Username, korzystając z dostawcy katalogu WinNT. To odpowiednik polecenia Unlock-ADAccount dla kont lokalnych.
  3. Dostosowuje zasady, o ile $ApplyPolicy ma wartość $true. Przy wartościach domyślnych blokada staje się mniej agresywna, a przy $LockoutThreshold = 0 wyłączasz ją całkowicie.
  4. Wypisuje ostatnie zdarzenia blokady (identyfikator zdarzenia 4740) oraz najczęstsze źródłowe adresy IP nieudanych logowań z ostatnich 24 godzin (identyfikator zdarzenia 4625). To adresy, z których atakowany jest twój dostęp RDP.

Uwaga o języku: w zlokalizowanej wersji systemu Windows polecenie net accounts wypisuje wartości pod przetłumaczonymi etykietami. Dlatego skrypt powyżej filtruje zarówno po „Lockout”, jak i po „Sperr”. W polskiej wersji dopisz do wzorca wyszukiwania jeszcze „blokad”.

Konto lokalne czy konto domenowe?

Skrypt obsługuje konto lokalne, czyli typowy przypadek na pojedynczym serwerze VPS albo serwerze root. Jeśli masz do czynienia z kontem domenowym albo pracujesz na kontrolerze domeny, odblokuj je zamiast tego poleceniem:

Unlock-ADAccount -Identity <nazwa_użytkownika>

Dostosowanie lub wyłączenie progu blokady

Skrypt domyślnie ustawia próg na 0 i tym samym wyłącza blokadę konta. Na pierwszy rzut oka brzmi to jak błąd, ale przy dostępie RDP otwartym na internet jest to lepszy wybór. Powód: atakujący wcale nie musi odgadnąć twojego hasła. Wystarczy, że co kilka minut wyśle kilka błędnych prób, a konto pozostanie zablokowane na stałe. Blokada uderza wtedy nie w niego, tylko wyłącznie w ciebie. Z funkcji ochronnej robi się wygodne narzędzie do trzymania cię z dala od własnego serwera.

Ważne: wyłączenie blokady nie zastępuje ochrony, usuwa tylko tę niewłaściwą. Ochrona przed masowym testowaniem haseł należy o poziom niżej, czyli do firewalla: jeśli RDP jest osiągalne wyłącznie z twojego własnego adresu IP, żaden atakujący nie dojdzie już do ekranu logowania i nie będzie czego liczyć. Wykonaj więc kroki z następnego rozdziału, zanim wyłączysz blokadę, a nie po fakcie.

Jeśli ze względów operacyjnych musisz zostawić RDP otwarte dla zmieniających się adresów, ustaw zamiast tego wysoki próg i krótki czas blokady, na przykład $LockoutThreshold = 50$LockoutDuration = 5. Zostaje dzięki temu trochę efektu hamującego, a przy każdym skanowaniu nie odcinasz sobie dostępu do serwera. W domenie z wewnętrznym RDP nadal obowiązuje klasyczne zalecenie niskiego progu, bo tam dostęp i tak nie jest osiągalny z internetu.

Usuń przyczynę: trwałe zabezpieczenie RDP

Zablokowane konto to tylko objaw. Właściwą przyczyną jest dostęp RDP otwarty dla całego internetu. Te cztery działania usuwają problem u źródła.

Ogranicz RDP do własnego adresu IP

To zdecydowanie najskuteczniejsze działanie. Jeśli RDP jest osiągalne tylko z twojego adresu, wszystkie zautomatyzowane ataki trafiają w próżnię:

# Zezwól na przychodzące RDP tylko z własnego adresu IP
Set-NetFirewallRule -DisplayName 'Remote Desktop - User Mode (TCP-In)' -RemoteAddress '203.0.113.5'

Podana nazwa wyświetlana obowiązuje w anglojęzycznym systemie Windows. W systemie zlokalizowanym, po polsku tak samo jak po niemiecku, brzmi ona inaczej. Istniejące reguły i ich dokładne nazwy wypiszesz poleceniem Get-NetFirewallRule -DisplayGroup 'Pulpit zdalny'.

Zablokuj pojedynczy adres IP atakującego

Dla adresów, które wypisuje krok 4b skryptu, utwórz osobną regułę blokującą:

New-NetFirewallRule -DisplayName 'Block RDP attacker 203.0.113.9' -Direction Inbound -Action Block -RemoteAddress '203.0.113.9'

Pomaga to na pojedyncze, uparte źródła, ale nie zastępuje ograniczenia do własnego adresu IP, bo atakujący cały czas używają nowych adresów.

Zmień port RDP

Jeśli RDP nie nasłuchuje już na domyślnym porcie 3389, typowe masowe skany w ogóle nie znajdą twojej usługi. Jak przestawić port bez restartu serwera, pokazuje nasz poradnik Zmiana portu RDP w systemie Windows bez restartu.

Silne hasło i Network Level Authentication

Używaj długiego, losowego hasła i zostaw włączone Network Level Authentication (NLA). NLA wymaga uwierzytelnienia, zanim w ogóle powstanie sesja, i odsiewa dzięki temu dużą część zautomatyzowanych prób już na wstępie.

Najczęstsze pytania

Dlaczego moje konto Windows zostaje zablokowane przy logowaniu RDP?
Windows blokuje konto, gdy tylko zostanie osiągnięta liczba nieudanych prób logowania ustalona w zasadach blokady. Na serwerze z portem RDP otwartym na internet blokadę wywołują prawie zawsze zautomatyzowane ataki.
Jak długo zablokowane konto pozostaje zablokowane?
Tak długo, jak wynika to z ustawionego czasu trwania blokady, często 15 albo 30 minut. Potem logowanie jest znowu możliwe. Skryptem z tego poradnika zdejmiesz blokadę także od razu.
Czy powinienem całkiem wyłączyć blokadę konta?
Przy dostępie RDP otwartym na internet tak. Atakujący nie musi odgadnąć twojego hasła, wystarczy, że regularnie wysyła błędne próby i utrzymuje konto zablokowane na stałe. Blokada uderza wtedy tylko w ciebie. Wyłącz ją, ale w tym samym ruchu ogranicz RDP na firewallu do własnego adresu IP, inaczej wymienisz jeden problem na drugi. Jeśli musisz zostawić RDP otwarte dla zmieniających się adresów, zamiast 0 wybierz wysoki próg z krótkim czasem blokady.
Jak sprawdzić, które adresy IP blokują moje konto?
Identyfikator zdarzenia 4740 w logu zabezpieczeń dokumentuje same blokady, a identyfikator 4625 nieudane logowania wraz ze źródłowym adresem IP. Skrypt z tego poradnika analizuje oba automatycznie.
Skrypt nie odblokowuje mojego konta, z czego to wynika?
Skrypt działa na koncie lokalnym. Przy koncie domenowym albo na kontrolerze domeny odblokuj je poleceniem Unlock-ADAccount. Sprawdź poza tym, czy PowerShell naprawdę działa jako administrator.

Windows Server Windows RDP Remote Desktop PowerShell Blokada konta Brute force Bezpieczeństwo serwera