fail2ban: Blokowanie ataków brute force na WordPress od strony administratora serwera

Każdy posiadacz strony opartej na popularnych systemach zarządzania treścią (CMS) powinien wiedzieć jak ważne są aktualizacje, a również spotkał się wiele razy z atakami typu brute force na swoją stronę. Praktycznie nie ma dnia by nie odbyła się seria takich ataków przez automaty próbujące zalogować się na konto administratora. Przeważnie odbywa się to popularną metodą słownikową i jeżeli zachowane są podstawowe zasady bezpieczeństwa to atak taki nie powinien się zakończyć sukcesem.
Problemem jest jednak duże obciążenie jakie generują takie ataki – automaty potrafią wywoływać plik logowania wp-login.php po kilka – kilkanaście razy na sekundę. O ile dla użytkownika strony mało istotne jest obciążenie serwera – w końcu to administrator ma zadbać by maszyna była wystarczająco wydajna, to dla nas takie ataki mogą stanowić spore utrapienie. Wystarczy kilka stron, które poddane są takim atakom jednocześnie by skutecznie zwiększyć obciążenie bazy danych do niebezpiecznego poziomu – zauważalnego przez wszystkich użytkowników serwera.

Istnieją gotowe wtyczki mające na celu odparcie takich ataków, ale również jedną z prostszych metod może być dodanie przez użytkownika strony dodatkowego wpisu do pliku .htaccess

<files wp-login.php>
order deny,allow
deny from all
allow from 1.2.3.4
</files>

Gdzie umieszczamy nasz adres (lub więcej adresów), z którego ma być dostęp do logowania.

Nie zda to jednak egzaminu na stronach gdzie rejestracja i logowanie jest dostępne dla wszystkich. Poza tym nie oszukujmy się – w większości przypadków właściciele stron posiadają prawie zerową wiedzę informatyczną i (poniekąd słusznie) chcą się tylko zalogować, a następnie dodawać nowe wpisy na swoich blogach czy stronach firmowych. Kontakt osoby posiadającej jako taką wiedzę kończy się w momencie instalacji i konfiguracji strony. Bardzo często strona “wisi” potem zdana sama na siebie przez parę lat do momentu pierwszego włamania.

Instalacja fail2ban

Stosując zasadę ograniczonego zaufania powinniśmy zastosować mechanizm automatycznie wyłapujący serię takich logowań i odpowiednio wcześniej blokujący takie ataki. Tu z pomocą może przyjść popularne narzędzie – fail2ban.

Jako przykładu użyjemy dystrybucji Debian, jednak poza sposobem instalacji zasada działania będzie taka sama w każdej innej.

Na początek warto zainstalować nasze oprogramowanie, w tym celu z poziomu roota wydajmy polecenia:

apt-get update
apt-get install fail2ban

Następnie do czasu skończenia konfiguracji zatrzymamy działanie programu:

service fail2ban stop

Przygotowanie logu

Kolejna sprawa to przygotowanie logu dla fail2ban. Owszem można skanować ogólny plik access.log, jednak często każda strona posiada swój osobny zestaw logów, poza tym fail2ban potrafi być bardzo zasobożerny przy naprawdę dużych plikach – przy sporej ilości odwiedzin strona może wygnerować nawet 1GB lub większy plik loga.

W tym celu będziemy generować plik zawierający tylko interesujące nas odwołania do plików wp-login.php oraz xmlrpc.php.

Z pomocą przyjdzie nam cron oraz polecenie cat i grep. W przypadku osobnych logów dla każdej strony taki plik wygenerujemy poleceniem:

cat /var/log/apache/domeny/*.log | grep POST | grep 'wp-login.php\|xmlrpc.php' | sort -k4 > /var/log/wordpress.log

W typ przykładzie zakładamy, że w katalogu /var/log/apache/domeny/ znajdują się pliki dla poszczególnych stron w formacie np. linux.pl.log (poleceniem sort -k4 sortujemy wyniki według 4 kolumny z datą). Jeżeli posiadamy jeden wspólny access.log to polecenie będzie analogiczne, z tym że wskazujemy konkretny plik loga:

cat /var/log/apache/access.log | grep POST | grep 'wp-login.php\|xmlrpc.php' > /var/log/wordpress.log

Jak widać interesują nas wywołania strony metodą POST oraz zawierające w treści nazwy plików, które są celem ataków – wp-login.php i xmlrpc.php.

W przypadku ataku w pliku /var/log/wordpress.log znajdziemy wpisy podobne do poniższych:

1.2.3.4 - - [11/Feb/2016:01:08:11 +0100] "POST /xmlrpc.php HTTP/1.0" 200 86217 "-" "-"
1.2.3.4 - - [11/Feb/2016:01:08:11 +0100] "POST /xmlrpc.php HTTP/1.0" 200 86217 "-" "-"
1.2.3.4 - - [11/Feb/2016:01:08:12 +0100] "POST /xmlrpc.php HTTP/1.0" 200 86217 "-" "-"
1.2.3.4 - - [11/Feb/2016:01:08:12 +0100] "POST /xmlrpc.php HTTP/1.0" 200 86217 "-" "-"
1.2.3.4 - - [11/Feb/2016:01:08:12 +0100] "POST /xmlrpc.php HTTP/1.0" 200 86217 "-" "-"

lub

1.2.3.4 - - [11/Feb/2016:13:11:52 +0100] "POST /wp-login.php HTTP/1.1" 200 3914 "-" "-"
1.2.3.4 - - [11/Feb/2016:13:11:52 +0100] "POST /wp-login.php HTTP/1.1" 200 3914 "-" "-"
1.2.3.4 - - [11/Feb/2016:13:11:55 +0100] "POST /wp-login.php HTTP/1.1" 200 3914 "-" "-"
1.2.3.4 - - [11/Feb/2016:13:11:56 +0100] "POST /wp-login.php HTTP/1.1" 200 3914 "-" "-"
1.2.3.4 - - [11/Feb/2016:13:11:58 +0100] "POST /wp-login.php HTTP/1.1" 200 3914 "-" "-"

Działanie polecenia jest szybkie, więc dodajmy (poleceniem crontab -e) do crona polecenie generujące plik co minutę:

* * * * * cat /var/log/apache/access.log | grep POST | grep 'wp-login.php\|xmlrpc.php' > /var/log/wordpress.log

Konfiguracja fail2ban

Kolejnym krokiem będzie konfiguracja fail2ban. Celem jest skanowanie pliku /var/log/wordpress.log oraz blokada atakującego adresu ip po założnej przez nas ilości odwołań do plików wp-login.php lub xmlrpc.php w określonym okresie czasu.

Zacznijmy konfigurację od umieszczenia odpowiednich wpisów w pliku /etc/fail2ban/jail.conf:

W sekcji [DEFAULT] ustawiamy domyślne ustawienia działania programu, warto umieścić tam nasze adresy ip, które mają być ignorowane. Robimy to przypisując je do zmiennej ignoreip, wiele adresów oddzielamy spacją, np:

ignoreip = 127.0.0.1/8 1.2.3.4 11.22.33.44

Kolejna interesująca nas zmienna to bantime, określa ona czas w sekundach na jaki założona ma być blokada na adres ip – jeżeli ban ma być stały dodajemy wartość ujemną, np:

bantime  = -1

Zmienną tę można użyć w konfiguracji poniższych sekcji – jeżeli chcemy by czas blokady był inny dla każdej z nich.

Następnie tworzymy dwie sekcje odpowiedzialne za blokowanie ataków:

[wordpress] enabled = true
filter = wordpress
action = csf-ip-deny[name=wordpress] sendmail-whois[name=wordpress, dest=admin@nasza-domena.pl, sender=fail2ban@nasza-domena.pl] logpath = /var/log/wordpress.log
findtime = 600
maxretry = 25

[xmlrpc] enabled = true
filter = xmlrpc
action = csf-ip-deny[name=xmlrpc] sendmail-whois[name=xmlrpc, dest=admin@nasza-domena.pl, sender=fail2ban@nasza-domena.pl] logpath = /var/log/wordpress.log
findtime = 600
maxretry = 25

Krótkie wyjaśnienie składni:

  • enabled: true oznacza włączenie sekcji
  • filter: nazwa filtra, który umieścimy w katalogu /etc/fail2ban/filter.d/ w postaci plików tekstowych z rozszerzeniem conf
  • action: w tym przypadku do blokowania używamy firewalla CSF (http://configserver.com/cp/csf.html) jednak równie dobrze możemy użyć dowolnego innego naszego skryptu, lub gotowych przykładów, które znajdziemy w katalogu /etc/fail2ban/action.d/
  • druga linijka odpowiedzialna jest za wysłanie powiadomienia mailem
  • logpath: plik loga, który ma być obserwowany
  • findtime: czas w sekundach jaki ma być wzięty pod uwagę
  • maxretry: ilość wystąpień w określonym wyżej czasie, który ma spowodować zablokowanie adresu ip atakującego

Założona wyżej konfiguracja oznacza blokadę w przypadku wystąpienia 25 odwołań z jednego adresu ip w ciągu 600 sekund. Można to dostosować dowolnie dla swoich potrzeb, na przykład skrócić ten czas do 2-3 minut – w większości przypadków automaty generują 25 odwołań w ciągu maksymalnie minuty, czyli 60 sekund.

Kolejnym etapem będzie utworzenie pliku odpowiedzialnego za wywołanie bana na adres ip – jeżeli wykorzystamy jeden z istniejących to pomijamy ten krok, lub dostosowujemy go do naszych celów. W naszym przypadku musimy utworzyć plik: /etc/fail2ban/action.d/csf-ip-deny.conf

Umieszczamy w nim wpis:

[Definition]
actionstart =
actionstop =
actioncheck =
actionban = csf -d <ip> Dodane przez Fail2Ban dla <name>
actionunban = csf -dr <ip>
[Init]
name = default

Jak widać składnia jest prosta i możemy podstawić tam dowolne polecenie blokady adresu ip atakującego. Jeżeli zakładamy, że blokada będzie nałożona na określony czas to możemy dodać również polecenie odblokowujące.

Przechodzimy teraz do utworzenia filtrów, w tym celu tworzymy dwa pliki: /etc/fail2ban/filter.d/wordpress.conf/etc/fail2ban/filter.d/xmlrpc.conf

Zawartość plików:

/etc/fail2ban/filter.d/wordpress.conf

[INCLUDES]
before = common.conf

[Definition]
_daemon = wordpress
failregex = ^<HOST> .* "POST .*wp-login.php HTTP/.*" 200
ignoreregex =

/etc/fail2ban/filter.d/xmlrpc.conf

[INCLUDES]
before = common.conf

[Definition]
_daemon = xmlrpc
failregex = ^<HOST> .* "POST .*xmlrpc.php HTTP/.*" 200
ignoreregex =

Zmienna failregex zawiera wyrażenie regularne wyłapujące nam linie zawierające odpowiedni wpis ataku, dodatkowo możemy umieścić wyrażenie w zmiennej ignoreregex, które spowoduje, że linia zostanie zignorowana.

Po zakończeniu edycji tych plików wystarczy uruchomić fail2ban i obserwować jego działanie – domyślny log pomocny do obserwacji znajduje się w pliku /var/log/fail2ban.log

Możemy znaleźć tam wpisy podobne do poniższych – oznaczają one uruchomienie fail2ban oraz stworzonych przez nas “jaili”:

2016-02-11 13:10:46,443 fail2ban.server : INFO Changed logging target to /var/log/fail2ban.log for Fail2ban v0.8.6
2016-02-11 13:10:46,443 fail2ban.jail : INFO Creating new jail 'wordpress'
2016-02-11 13:10:46,443 fail2ban.jail : INFO Jail 'wordpress' uses Gamin
2016-02-11 13:10:46,450 fail2ban.filter : INFO Added logfile = /var/log/wordpress.log
2016-02-11 13:10:46,469 fail2ban.filter : INFO Set maxRetry = 25
2016-02-11 13:10:46,474 fail2ban.filter : INFO Set findtime = 600
2016-02-11 13:10:46,474 fail2ban.actions: INFO Set banTime = -1
2016-02-11 13:10:46,480 fail2ban.jail : INFO Creating new jail 'xmlrpc'
2016-02-11 13:10:46,481 fail2ban.jail : INFO Jail 'xmlrpc' uses Gamin
2016-02-11 13:10:46,481 fail2ban.filter : INFO Added logfile = /var/log/wordpress.log
2016-02-11 13:10:46,481 fail2ban.filter : INFO Set maxRetry = 25
2016-02-11 13:10:46,484 fail2ban.filter : INFO Set findtime = 600
2016-02-11 13:10:46,484 fail2ban.actions: INFO Set banTime = -1
2016-02-11 13:10:46,489 fail2ban.jail : INFO Jail 'wordpress' started
2016-02-11 13:10:46,490 fail2ban.jail : INFO Jail 'xmlrpc' started

Po wystąpieniu ataku pojawi się wpis podobny do tego:

2016-02-11 13:12:03,731 fail2ban.actions: WARNING [wordpress] Ban 1.2.3.4
2016-02-11 13:13:02,059 fail2ban.actions: WARNING [xmlrpc] Ban 1.2.3.4

Dodatkowo po każdym restarcie usługi oraz nałożeniu blokady powinniśmy otrzymać maila z informacją na ten temat.

Opisany sposób jest sprawdzony i działa z powodzeniem na paru serwerach – w różnej konfiguracji jeżeli chodzi o zastosowane firewalle czy oprogramowanie do zarządzania usługami hostingowymi. W przypadku pytań lub poprawek zapraszam do kontaktu 🙂

2 komentarze
  1. RE: fail2ban: Blokowanie ataków brute force na WordPress od strony administratora serwera
    [quote name=”dafr”]Na ubuntu server 14.4 fail2ban nie startuje po dodaniu tych filtrów[/quote]

    A jakie błędy się logach pojawiają? To są działające skrypty więc sprawdzone 🙂

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *

Poprzedni post

Google Chrome kończy wsparcie dla starszych i 32-bitowych dystrybucji Linuksa

Następny post

Pierwszy Informatyczny Puchar Beskidów zakończony – podsumowanie

Powiązane posty

Biblioteka popt

Chodzi tu o rozwiązanie problemów, jakie może sprawić brak tej biblioteki.

Jesli chodzi o system opensuse biblioteka ta pochodząca z pakietu popt, a własciwie jej brak blokuje uruchamianie poszczególnych modułów yast co objawia się komunikatem:

Error while creating client module sw_single.
Więcej...

BIND – konfiguracja serwera DNS

BIND jest jednym z najpopularniejszych serwerów DNS wykorzystywanym w systemach Linux i Unix. Stanowi on niezmiernie ważny składnik zapewniający poprawne działanie systemu nazw w Internecie. Wielu użytkowników globalnej sieci bezwiednie korzysta z serwera BIND, kiedy ich przeglądarka WWW odpytuje go o adres IP komputera udostępniającego interesującą ich stronę.
Nowa wersja BIND 9 została napisana od zera, aby rozwiązać część problemów z architekturą poprzednich wydań tego programu. Dlatego też warto byłoby nauczyć się go konfigurować dla swoich potrzeb. Artykuł ten będzie opisem konfiguracji serwera DNS pod kontrola systemu operacyjnego Linux Debian, jednak w rzeczywistości jedyne różnice jakie mogą wystąpić to inne ścieżki do plików konfiguracyjnych.

Więcej...