Skrypt remuda , edytowany przez kevinmicke (7 lutego o 21:59), nie sprawdził kanału kontrolnego FTP, który ma własny folder w moim systemie (Windows Server 2008 R2). Ponadto 530 11001
nie rozpoznano zdarzeń, które wydają się pojawiać, gdy haker próbuje jedynie uzyskać dostęp do kanału kontrolnego. Dołączyłem więc kilka wierszy w skrypcie, aby sprawdzić drugi folder dziennika FTP:
# Ten skrypt Windows PowerShell automatycznie blokuje adresy IP, które próbują zalogować się do systemu
# i nie uda się ustawić liczby razy poniżej przy pomocy zmiennej $ int_block_limit lub więcej. Skanuje zarówno zabezpieczenia
# log, który obejmuje Pulpit zdalny i inne próby, a także dziennik FTP z bieżącego dnia. Jeśli $ int_block_limit
# limit zostanie osiągnięty w jednym z tych dzienników (osobno, nie połączone), następnie adres IP zostanie dodany do
# reguła zapory.
#
# Skrypt automatycznie utworzy regułę zapory o nazwie „BlockAttackers (Utworzono rrrr-MM-dd GG: mm: ss UTC)” przy użyciu
# bieżący czas, jeśli taki o nazwie zawierającej „BlockAttackers” jeszcze nie istnieje. Ponieważ jest trudny
# limit 1000 wpisów (adresów IP), które można zablokować dla każdej reguły, spowoduje to również utworzenie reguł o podobnych nazwach
Limit został osiągnięty dla najnowszego.
#
# Polecam ustawienie skryptu, aby działał jako zaplanowane zadanie wywołane niepowodzeniem kontroli logowania zdarzenia 4625 z poziomu
# Dziennik bezpieczeństwa lub możesz ustawić, aby działał po pewnym czasie (tj. Co 10 minut).
#
# Autorzy:
# Większość skryptów napisanych przez użytkownika serverfault.com kevinmicke
# Część dziennika bezpieczeństwa systemu Windows napisana przez remunda serverfault.com, która stanowiła punkt wyjścia dla kevinmicke
# Sprawdzanie kanału kontrolnego FTP dodane przez użytkownika serverfault.com Uwe Martens
#
# Szczegóły: https://serverfault.com/questions/233222/ban-ip-address-based-on-x-number-of-unsuccessful-login-attempts
# Ustaw liczbę nieudanych prób logowania, po których adres IP zostanie zablokowany
$ int_block_limit = 3
# Okno czasu, w którym można sprawdzić dziennik zabezpieczeń, który jest obecnie ustawiony tak, aby sprawdzał tylko ostatnie 24 godziny
$ dat_time_window = [DateTime] :: Now.AddDays (-1)
# Wybierz z dziennika zabezpieczeń wszystkie adresy IP, które zawierają więcej niż $ niepowodzeń kontroli int_block_limit (zdarzenie 4625) w obrębie $ dat_time_window
$ arr_new_bad_ips_security_log = @ ()
$ arr_new_bad_ips_security_log = Get-EventLog -LogName 'Security' -InstanceId 4625 -Po $ dat_time_window |
Select-Object @ {n = 'IpAddress'; e = {$ _. ReplacementStrings [-2]}} |
Grupa-obiekt-właściwość IpAddress |
Gdzie {$ _. Count -ge $ int_block_limit} |
Wybierz -property Nazwa
# Uzyskaj aktualny czas UTC, aby ustalić nazwę pliku dla bieżącego dziennika FTP
$ current_date_utc = (Get-Date) .ToUniversalTime ()
# Ustaw ścieżkę do dzisiejszego pliku dziennika kanału kontrolnego FTP
$ str_log_file_file_name_control_channel = "C: \ inetpub \ logs \ LogFiles \ FTPSVC \ u_ex" + $ current_date_utc.ToString ("yyMMdd") + ".log"
# Wyszukaj w pliku dziennika kanału kontroli FTP „530 1”, aby znaleźć linie zawierające adresy IP systemów, które się nie zalogowały,
# pobierz tylko adres IP z każdej linii, pogrupuj adresy IP według adresów IP, aby policzyć próby z każdej z nich, i wybierz tylko
# Adresy IP, które mają $ int_block_limit lub więcej złych logowań dzisiaj
$ arr_new_bad_ips_ftp_control_channel = @ ()
$ arr_new_bad_ips_ftp_control_channel = Wybierz łańcuch $ str_log_file_file_nazwa_kontrolny_kanału - wzór „530 1” |
ForEach-Object {$ _. Line.Substring (20,15) -replace ". *", ""} |
Grupa |
Gdzie {$ _. Count -ge $ int_block_limit} |
Wybierz -property Nazwa
# Ustaw ścieżkę do dzisiejszego pliku dziennika FTP
$ str_log_file_name = "C: \ inetpub \ logs \ LogFiles \ FTPSVC * \ u_ex" + $ current_date_utc.ToString ("yyMMdd") + ".log"
# Wyszukaj w dzisiejszym pliku dziennika FTP wartość „530 1”, aby znaleźć linie zawierające adresy IP systemów, które się nie zalogowały,
# pobierz tylko adres IP z każdej linii, pogrupuj adresy IP według adresów IP, aby policzyć próby z każdej z nich, i wybierz tylko
# Adresy IP, które mają $ int_block_limit lub więcej złych logowań dzisiaj
# W FTPSVC * należy dodać identyfikator serwera FTP zamiast *, lub po prostu weź odpowiedni folder dziennika
$ arr_new_bad_ips_ftp = @ ()
$ arr_new_bad_ips_ftp = Wybierz łańcuch $ str_log_file_name -pattern "530 1" |
ForEach-Object {$ _. Line.Substring (20,15) -replace ". *", ""} |
Grupa |
Gdzie {$ _. Count -ge $ int_block_limit} |
Wybierz -property Nazwa
# Połącz dwie tablice adresów IP (jedną z dziennika bezpieczeństwa, drugą z dziennika FTP)
$ arr_new_bad_ips_all = @ ()
# $ arr_new_bad_ips_all = @ ($ arr_new_bad_ips_security_log) + @ ($ arr_new_bad_ips_ftp_over_limit)
$ arr_new_bad_ips_all = @ ($ arr_new_bad_ips_security_log) + @ ($ arr_new_bad_ips_ftp_control_channel) + @ ($ arr_new_bad_ips_ftp)
# Sortuj tablicę, wybierając tylko unikalne adresy IP (w przypadku gdy jeden adres IP pojawia się zarówno w dziennikach zabezpieczeń, jak i FTP)
$ arr_new_bad_ips_all_sorted = @ ()
$ arr_new_bad_ips_all_sorted = $ arr_new_bad_ips_all |
Foreach-Object {[ciąg] $ _. Nazwa} |
Select-Object -unique
# Uzyskaj obiekt zapory ogniowej
$ firewall = New-Object -comobject hnetcfg.fwpolicy2
# Pobierz wszystkie reguły zapory pasujące do „BlockAttackers *”
$ arr_firewall_rules = $ firewall.Rules | Gdzie {$ _. Podobne do nazwy „BlockAttackers *”}
# Jeśli nie istnieje jeszcze reguła zapory „BlockAttackers *”, utwórz ją i ustaw na zmienną
if ($ arr_firewall_rules -eq $ null) {
$ str_new_rule_name = "BlockAttackers (Utworzono" + $ current_date_utc.ToString ("rrrr-MM-dd GG: mm: ss") + „UTC)"
netsh advfirewall firewall dodaj regułę katalog = w akcji = nazwa bloku = $ str_new_rule_name description = "Reguła automatycznie utworzona." enable = tak remoteip = "0.0.0.0" | Out-Null
$ arr_firewall_rules = $ firewall.Rules | Gdzie {$ _. Podobne do nazwy „BlockAttackers *”}
}
# Podziel istniejące adresy IP z obecnych reguł zapory „BlockAttackers *” na tablicę, abyśmy mogli je łatwo wyszukać
$ arr_existing_bad_ips = @ ()
foreach ($ reguła w $ arr_firewall_rules) {
$ arr_existing_bad_ips + = $ rules.RemoteAddresses -split (',')
}
# Wyczyść maski podsieci z adresów IP, które są obecnie blokowane przez reguły zapory
$ arr_existing_bad_ips_without_masks = @ ()
$ arr_existing_bad_ips_without_masks = $ arr_existing_bad_ips | ForEach-Object {$ _ -replace "/.*", ""}
# Wprowadź adres IP swojego serwera (IPv4 i IPv6) w wierszach 115 i 116.
# Wybierz adresy IP, które chcesz dodać do zapory, ale tylko te, które ...
$ arr_new_bad_ips_for_firewall = @ ()
$ arr_new_bad_ips_for_firewall = $ arr_new_bad_ips_all_sorted | Gdzie {
# zawierają adres IP (tzn. nie są puste ani myślnik, który ma dziennik zabezpieczeń dla systemów, w których logowanie się nie powiodło)
$ _. Długość -gt 6 -i
# nie ma jeszcze w regułach zapory
! ($ arr_existing_bad_ips_without_masks -contains $ _) -i
# nie są lokalnymi pętlami zwrotnymi
! ($ _. StartsWith ('127.0.0.1')) - i
# nie są częścią lokalnej podsieci
! ($ _. StartsWith ('192.168.')) -I
! ($ _. StartsWith ('0.0.')) - i
! ($ _. StartsWith ('10 .0. ')) -I
! ($ _. StartsWith ('*. *. *. *')) - i
! ($ _. StartsWith ('*: *: *: *: *: *'))
}
# Jeśli istnieją adresy IP do zablokowania, wykonaj następujące czynności ...
if ($ arr_new_bad_ips_for_firewall -ne $ null) {
# Wpisz datę i godzinę do pliku dziennika specyficznego dla skryptu
[DateTime] :: Teraz | Plik wyjściowy -Załóż -Encoding utf8 C: \ inetpub \ logs \ LogFiles \ blockattackers.txt
# Napisz nowo zablokowane adresy IP do pliku dziennika
$ arr_new_bad_ips_for_firewall | Plik wyjściowy -Załóż -Encoding utf8 C: \ inetpub \ logs \ LogFiles \ blockattackers.txt
# Boolean, aby upewnić się, że nowe adresy IP są dodawane tylko do jednej reguły
$ bln_added_to_rule = 0
# Tablica do przechowywania złych adresów IP z każdej reguły pojedynczo, więc możemy liczyć, aby upewnić się, że dodanie nowych nie przekroczy 1000 adresów IP
$ arr_existing_bad_ips_current_rule = @ ()
# Dla każdej reguły „BlockAttackers *” w zaporze wykonaj następujące czynności ...
foreach ($ reguła w $ arr_firewall_rules) {
if ($ bln_added_to_rule -ne 1) {
# Podziel istniejące adresy IP z bieżącej reguły na tablicę, abyśmy mogli je łatwo policzyć
$ arr_existing_bad_ips_current_rule = $ rules.RemoteAddresses -split (',')
# Jeśli liczba adresów IP do dodania jest mniejsza niż 1000 minus bieżąca liczba adresów IP w regule, dodaj je do tej reguły
if ($ arr_new_bad_ips_for_firewall.Count -le (1000 - $ arr_existing_bad_ips_current_rule.Count)) {
# Dodaj nowe adresy IP do reguły zapory
$ arr_new_bad_ips_for_firewall | % {$ rules.RemoteAddresses + = ',' + $ _}
# Napisz, która reguła została dodana do pliku dziennika
echo "Nowe adresy IP powyżej dodane do reguły Zapory systemu Windows:" $ rules.Name | Plik wyjściowy -Załóż -Encoding utf8 C: \ inetpub \ logs \ LogFiles \ blockattackers.txt
# Ustaw wartość logiczną, aby wszelkie inne reguły były pomijane podczas dodawania adresów IP
$ bln_added_to_rule = 1
}
}
}
# Jeśli w żadnej innej zaporze „BlockAttackers *” nie ma miejsca, utwórz nową i dodaj do niej adresy IP
if ($ bln_added_to_rule -ne 1) {
$ str_new_rule_name = "BlockAttackers (Utworzono" + $ current_date_utc.ToString ("rrrr-MM-dd GG: mm: ss") + „UTC)"
netsh advfirewall firewall dodaj regułę katalog = w akcji = nazwa bloku = $ str_new_rule_name description = "Reguła automatycznie utworzona." enable = tak remoteip = "0.0.0.0" | Out-Null
$ new_rule = $ firewall.rules | Gdzie {$ _. Nazwa -eq $ str_new_rule_name}
# Dodaj nowe adresy IP do reguły zapory
$ arr_new_bad_ips_for_firewall | % {$ new_rule.RemoteAddresses + = ',' + $ _}
# Napisz, która reguła została dodana do pliku dziennika
echo "Dodano nowe adresy IP powyżej do nowo utworzonej reguły Zapory systemu Windows:" $ new_rule.Name | Plik wyjściowy -Załóż -Encoding utf8 C: \ inetpub \ logs \ LogFiles \ blockattackers.txt
}
}
Nazwa folderu dziennika FTP w FTPSVC*
linii 54 musi zostać wypełniona z przyczyny. W wierszach 115 i 116 należy wprowadzić adres IP twojego serwera (IPv4 i IPv6), w przeciwnym razie adres IP własnego serwera może zostać dodany do reguły zapory sto razy. Zmienną $int_block_limit
ustawiam na 1 na moim serwerze, więc skrypt blokuje atak hakerów powodujący zdarzenie 4625 w ciągu dwóch sekund. Nadal zastanawiam się nad uruchomieniem skryptu oprócz wystąpienia 4625 zdarzeń w ciągu kilku minut. Oczywiście możliwe byłoby również oddzielenie skryptów i pozwolenie, by jeden skrypt sprawdzał zdarzenia 4625 wywołane przez zdarzenie 4625, a drugi sprawdzał foldery dziennika FTP co 5 lub 10 minut, nawet przy oddzielnej regule zapory i plik dziennika.