</> Damian Pawela TECH // CYBERSECURITY

[ NOTATKI EKSPERCKIE ]

Cyberbezpieczeństwo

← BACK TO ALL ARTICLES

2,35 miliona żądań HTTP. Czego boty szukały na serwerze i co zmienił Fail2ban?

Techniczne case study niemal 11 miesięcy ruchu Apache2: od skanowania .env i webshelli, przez sygnatury znanych CVE, po zabezpieczenia i pomiar ich skuteczności.

Każdy serwer wystawiony do Internetu jest prędzej czy później skanowany. Boty nie muszą wiedzieć, jaka aplikacja działa na porcie 443. Wysyłają serie żądań, sprawdzają typowe ścieżki, szukają ujawnionych plików i testują znane podatności. Wystarczy analiza pliku access.log, aby zobaczyć, jak automatyczne i masowe jest to zjawisko.

Jak wygląda rzeczywiste skanowanie publicznego serwera WWW, czego szukają automatyczne boty i jak ograniczyć takie ataki za pomocą Apache2, Fail2ban oraz iptables? Niżej zamieszczone informacje i wnioski oparłem na analizie logów produkcyjnego serwera z niemal 11 miesięcy.

Żądania HTTP
2 357 178
Podejrzane
570 527
Udział procentowy
24,2%

Co naprawdę mówią odpowiedzi serwera?

Aplikacje webowe i strony internetowe działają na zasadzie przyjęcia żądania z przeglądarki internetowej klienta oraz obsłużenia przez serwer tego żądania i zwrócenia odpowiedzi. W analizie cyberbezpieczeństwa musimy zwrócić uwagę na to jakie żądania trafiają do serwera i jak serwer na nie reaguje i co zwraca jako odpowiedź.

Odpowiedzi są podzielone na kilka kategorii:
- informacyjne (100 – 199)
- zakończone sukcesem (200 – 299)
- przekierowania (300 – 399)
- błędy po stronie klienta (400 – 499)
- błędy po stronie serwera (500 – 599)

Całą specyfikację można przeczytać na stronie: https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status

W czasie od grudnia 2025 do października 2026 serwer zwrócił ponad 1,45 mln odpowiedzi 404, czyli zwrócił błąd w przypadku próby otworzenia adresu URL, który nie jest poprawny. Część z tych odpowiedzi może być z punktu widzenia bezpieczeństwa poprawna bo np. przeglądarka próbowała otworzyć brakujący plik favicon.ico czy jakiś brakujący plik css/js. Takie sytuacje przeważnie nie są incydentem.

Ale gdy jedno źródło (adres IP) w krótkim czasie sprawdza ścieżki do /.env, /.git/config, plików PHP typowych dla webshelli i endpointy PHPUnit, mamy do czynienia z potencjalnym atakiem.

Najczęściej poszukiwane słabe punkty

W analizowanym logu dominowały dwie grupy ataków: szukanie haseł i innych danych dostępowych oraz skanowanie WordPressa.
Poniższe kategorie nakładają się na siebie, dlatego nie możemy ich sumować, gdyż wprowadzało by to w błąd.

Pliki .env i ujawnione sekrety

Najpopularniejsze było sprawdzanie ścieżek, które w błędnie skonfigurowanym wdrożeniu mogą ujawniać hasła do baz danych, klucze API, konfigurację poczty czy dane do chmury. W samym pełnym zbiorze /.env pojawiło się 16 545 razy.
Inne przykładowe pliki przedstawiam poniżej.

/.env
/.env.local
/.env.production
/.env.bak
/api/.env
/backend/.env
/.aws/credentials
/secrets.json
/terraform.tfstate

Mechanizm nie wymaga zaawansowanego exploita: czasem wystarcza nieprawidłowy DocumentRoot, pozostawiona kopia zapasowa lub źle skonfigurowane uprawnienia. Najlepszą ochroną jest umieszczenie haseł/tokenów poza publicznym drzewem plików bądź w zmiennych środowiskowych serwera oraz ograniczenie dostępu na poziomie aplikacji oraz serwera WWW.

WordPress i zapomniane instalacje

W statystykach było 227 852 żądań rozpoznanych jako związane z WordPressem. Boty wyszukiwały instalatorów, logowania, XML-RPC, plików konfiguracyjnych i katalogów wtyczek. Nie ograniczały się do głównego katalogu domeny, skanowały też /old/, /blog/, /wordpress/ czy /test/.
Najczęściej sprawdzane ścieżki przedstawiam poniżej.

/wp-admin/install.php
/wp-login.php
/xmlrpc.php
/wp-config.php.bak
/wp-content/plugins/hellopress/wp_filemanager.php
/wordpress/wp-includes/wlwmanifest.xml

W pełnym zbiorze pod adresem /wp-admin/install.php odnotowano aż 6 323 żądania, a pod /xmlrpc.php 3 902.

Poszukiwanie istniejących webshelli

W logach zarejestrowano 27 167 dopasowań do wzorców nazw backdoorów i webshelli. Niektóre boty nie szukają luk w oprogramowaniu ale także śladów czy już ktoś wcześniej się nie włamał i nie zostawił narzędzi do zdalnego dostępu np.

/shell.php
/wso.php
/alfa.php
/alfashell.php
/ioxi-o.php
/adminfuns.php

Sama nazwa pliku nie oznacza obecności malware; zwłaszcza gdy log pokazuje 404. Jednak jeżeli któryś z podobnych plików istnieje, należy przeprowadzić weryfikację zawartości, historii modyfikacji i zgodności z wdrożeniem. Może to być bowiem pozostałość po udanym ataku.

Ujawnione repozytoria Git

20 413 żądań zakwalifikowałem jako próby dostępu do zasobów Git. Pliki takie jak /.git/config czy /.git/HEAD nie powinny być osiągalne publicznie. Przy nieprawidłowej konfiguracji np. mechanizmów CI/CD mogą ułatwić odtworzenie kodu i poznanie struktury aplikacji oraz jej zabezpieczeń.

Sygnatury konkretnych podatności

Nie każdy skan można przypisać do numeru CVE. Niektóre żądania jednak odpowiadają charakterystycznym próbom wykorzystania historycznych podatności.

Sygnatura / CVE Co jest sprawdzane? Interpretacja
CVE-2017-9841 eval-stdin.php w PHPUnit Ryzyko wykonania kodu, jeśli podatny plik jest publiczny.
CVE-2024-4577 auto_prepend_file=php://input Wzorzec PHP-CGI; konkretny CVE dotyczy określonych konfiguracji Windows.
CVE-2021-3129 /_ignition/execute-solution Rozpoznawanie podatnych konfiguracji Laravel Ignition.
CVE-2022-22947 /actuator/gateway/routes Rozpoznawanie Spring Cloud Gateway, nie dowód kompletnej eksploatacji.

W ramach analizy sklasyfikowałem 16 989 żądań w związku z PHPUnit i 1 843 z PHP-CGI.

Co z tego wynika? Publiczne usługi są skanowane również pod kątem technologii, których na nich nie zainstalowano. Rzeczywiste ryzyko trzeba zawsze oceniać w odniesieniu do wykorzystywanych technologii, sposobu wdrożenia i wersji komponentów.

Praktyczna analiza logów Apache2

W standardowym formacie logowania Apache combined możemy szybko wyciągnąć żądania, metody i kody HTTP. Przykładowy wpis (syntetyczny, z IP dokumentacyjnym):

xxx.xxx.xxx.xxx - - [19/May/2026:10:15:21 +0200] "GET /.env HTTP/1.1" 404 285 "-" "curl/8.0"

Najbardziej aktywne miesiące

Po wdrożeniu Fail2ban w lipcu 2026 liczba podejrzanych żądań docierających do Apache istotnie spadła. Poniżej pełne dane miesięczne.

Miesiąc HTTP ogółem Podejrzane Udział
2025-12* 110 583 43 590 39,4%
2026-01 163 915 57 917 35,3%
2026-02 409 056 62 573 15,3%
2026-03 322 254 84 460 26,2%
2026-04 273 416 73 828 27,0%
2026-05 261 759 85 796 32,8%
2026-06 370 994 80 880 21,8%
2026-07 / instalacja i konfiguracja FAIL2BAN 109 697 18 827 17,2%
2026-08 105 620 17 832 16,9%
2026-09 126 257 26 228 20,8%
2026-10* 103 627 18 596 17,9%
* Grudzień od 11.12, październik do 25.10.

Średnia miesięczna w marcu–czerwcu wynosiła ok. 81,2 tys. podejrzanych żądań. W lipcu i sierpniu wartości spadły do ok. 18 tys. Jest to spójne z działaniem blokad na poziomie firewalla: zablokowane połączenia nie pojawiają się później w logach Apache.

Ochrona: Fail2ban, Apache2 i iptables

Fail2ban to przydatna warstwa zabezpieczeń która analizuje logi, rozpoznaje wzorce i może czasowo bądź bezterminowo blokować źródła ruchu.

Przykładowy filtr dla plików wrażliwych

Plik apache-sensitive-data.conf:

[Definition]
failregex = ^<HOST> \S+ \S+ \[[^\]]+\] "(?:GET|POST|HEAD) /(?:\.env(?:[.? /]|$)|\.git/(?:config|HEAD)(?:[? ]|$))[^\"]*" (?:200|403|404) \d+ .*$
ignoreregex =

To przykład wąskiego filtra dla standardowego formatu combined.

Przykładowy plik jail iptables

Plik /apache-sensitive-data.local:

[apache-sensitive-probes]
enabled = true
filter = apache-sensitive-probes
logpath = /var/log/apache2/access.log
backend = auto
port = http,https
banaction = iptables-multiport
maxretry = 2
findtime = 600
bantime = 86400

Dwa dopasowania w ciągu 10 minut mogą spowodować blokadę na 24 godziny. Progi oczywiście należy dobrać na podstawie ruchu, źródeł monitorujących, reverse proxy oraz akceptowalnego ryzyka fałszywych alarmów.

Wnioski z analizy

Co warto wdrożyć poza Fail2ban?

  • Trzymać hasła i inne dane dostępowe poza DocumentRoot. Zablokować publiczny dostęp do .env, kopii zapasowych, repozytoriów i plików kluczy.
  • Nie publikować narzędzi testowych. Produkcyjny serwer nie powinien udostępniać niepotrzebnego PHPUnit, debuggerów czy profilerów.
  • Regularnie aktualizować zależności. Zwłaszcza PHP, CMS, wtyczki oraz biblioteki Composer i npm.
  • Wyłączyć listowanie katalogów. W Apache użyć Options -Indexes we właściwym kontekście.
  • Ograniczyć endpointy administracyjne i diagnostyczne. VPN, allowlists, uwierzytelnianie i separacja środowisk.
  • Zebrać telemetrykę z kilku warstw. Apache, Fail2ban, iptables, aplikacja, reverse proxy/WAF.
  • Monitorować fałszywe alarmy. Nie banować użytkowników za pojedyncze żądania np. /robots.txt, /favicon.ico czy standardowe 404.

Jak mierzyć skuteczność ochrony?

Metryka Co nam mówi
Podejrzane żądania dziennie Natężenie ruchu docierającego do Apache.
Unikalne źródła Czy ruch pochodzi od kilku skanerów, czy wielu adresów.
Bany i ponowne bany Fail2ban Czy reguły się uruchamiają i czy źródła wracają.
Odpowiedzi 200 dla czułych ścieżek Które zdarzenia wymagają ręcznej weryfikacji.
Odsetek false positive Czy ochrona nie szkodzi normalnym użytkownikom.
KLUCZOWY WNIOSEK

Serwer nie musi być celem konkretnego atakującego, aby każdego dnia otrzymywać próby wykorzystania znanych błędów. Ochrona zaczyna się od obserwowania: trzeba wiedzieć, co jest skanowane, co serwer odpowiada i które blokady rzeczywiście działają.