Poniższy poradnik opisuje krok po kroku, jak wygląda implementacja web application firewalla opartego na ModSecurity, który od pewnego czasu jest dostępny dla Nginx. Należy pamiętać, iż opisana tutaj procedura działa dla Nginx zainstalowanego bezpośrednio z repozytoriów systemu Ubuntu 20.04.6 LTS. Większość poradników opartych jest na Nginx Plus, skompilowanym Nginx lub Nginx dostępnym z oficjalnych repozytoriów nginx (nie mylić z oficjalnymi repozytoriami systemu).
Poradnik omawia poniższe kwestie:
- Wdrożenie Web Application Firewall w oparciu o moduł Modsecurity do Nginx instalowany z repozytoriów systemowych.
- Omówienie kilku przykładowych reguł.
- Aktualizowanie modułu Modsecurity.
Implementacja Web Application Firewalla – wdrożenie
Zakładam, iż do maszyny, na której jest przeprowadzane wdrożenie, logujemy się na konto użytkownika root.
1. Instalacja wymaganych pakietów:
2. Klonowanie repozytorium Modsecurity do katalogu domowego użytkownika root:
3. Kompilowanie kodu źródłowego z poziomu katalogu Modsecurity (ten krok zajmuje około 20 minut):
Należy zignorować pojawiające się ostrzeżenia:
fatal: No names found, cannot describe anything
We wcześniejszym punkcie jest wykonywane tzw. płytkie klonowanie (shallow clone), które pobiera tylko ostatni commit z wybranej gałęzi i nie pobiera pełnej historii i tagów repozytorium. Polecenie “git describe” używane w jednym ze skryptów uruchamianych podczas kompilacji działa na podstawie tagów i historii commitów. W tym wypadku brakuje tych danych, co skutkuje powyższymi ostrzeżeniami.
4. Klonowanie repozytorium ModSecurity Nginx Connector, który będzie użyty jako dynamiczny moduł do Nginxa:
5. Weryfikacja wersji aktualnie zainstalowanego Nginxa:
W opisywanym przypadku zwrócona wartość jest następująca:
6. Pobieranie stąd i wypakowywanie wersji Nginx — odpowiedniej dla zainstalowanej na serwerze:
7. Wejście do folderu z wypakowanym archiwum i kompilacja dynamicznego modułu:
8. Po zakończeniu procesu kompilacji, w folderze nginx-1.18.0/objs pojawi się następujący plik z rozszerzeniem “.so” → ngx_http_modsecurity_module.so.
9. Kopiowanie pliku ngx_http_modsecurity_module.so do ścieżki /usr/lib/nginx/modules i zmiana jego uprawnień z domyślnych 755 na 644:
10. Utworzenie w ścieżce /usr/share/nginx/modules-available pliku mod-http-modsecurity.conf z odpowiednią zawartością:
11. Utworzenie w ścieżce /etc/nginx/modules-enabled linku symbolicznego do pliku konfiguracyjnego dostępnego w /usr/share/nginx/modules-available:
12. Utworzenie katalogu modsec w ścieżce /etc/nginx/conf.d i umiejscowienie w nim pliku konfiguracyjnego znajdującego się w repozytorium Modsecurity:
13. Zmiana nazwy pobranego we wcześniejszym punkcie pliku poprzez usunięcie przyrostka “-recommended”:
14. Kopiowanie pliku unicode.mapping do wcześniej utworzonego katalogu modsec. Plik unicode.mapping w ModSecurity pomaga w wykrywaniu podejrzanych działań przez ujednolicenie znaków z różnych alfabetów i sposobów kodowania. “a” z alfabetu łacińskiego (U+0061) i “а” z cyrylicy (U+0430). Wizualnie są prawie identyczne, ale technicznie to różne znaki.
15. Zmiana domyślnego trybu wykrywania na tryb blokowania:
16. Użycie zestawu reguł OWASP Coreruleset. Na czas pisania poradnika najnowsza stabilna wersja to 3.3.2. Pobranie i wypakowanie:
17. Przeniesienie katalogu z regułami do głównego katalogu Modsecurity oraz utworzenie pliku crs-setup.conf z domyślnego crs-setup.conf.example:
18. Wejście do ścieżki /etc/nginx/conf.d/modsec/coreruleset-3.3.2/rules i włączenie dwóch reguł poprzez usunięcie przyrostka “.example”:
19. Dodanie poniższych reguł w pliku /etc/nginx/conf.d/modsec/main.conf. Są to domyślne – wszystkie – reguły przygotowane przez OWASP, które w razie potrzeby należy zmodyfikować. Jest to opisywane na przykładach w dalszej części tekstu.
20. Utworzenie snippeta w ścieżce /etc/nginx/snippets/waf.conf z zawartością:
21. Dołączenie utworzonego snippeta w bloku http {} pliku /etc/nginx/nginx.conf:
22. Sprawdzenie konfiguracji i przeładowanie nginxa:
23. W pliku loga pojawi się linia podobna do poniższego fragmentu:
24. Usunięcie repozytoriów i pobranych plików:
Omówienie reguł
Powyższy krok jest ostatnim w kontekście generalnego wdrożenia. Natomiast z pewnością pojawi się wymóg dostosowania reguł web application firewalla do serwera, na którym został wdrożony. Reguły, które mają być brane pod uwagę przed sprawdzaniem poszczególnych zapytań należy umieszczać w pliku REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf. Znajduje się on w ścieżce /etc/nginx/conf.d/modsec/coreruleset-3.3.2/rules. Poniżej kilka przykładów reguł wraz z opisami:
Każda reguła zaczyna się od słowa “SecRule”. Reguły można łączyć w łańcuchy reguł zależnych od siebie. Większość atrybutów w definicjach wspomnianych reguł jest dość prosta do zrozumienia, dlatego skupię się na wyjaśnieniu niuansów:
1. Dlaczego w jednej regule jest “allow”, a w innej “pass”?
Po skonfigurowaniu “allow” ModSecurity zakończy przetwarzanie bieżącego zapytania bez dalszego stosowania reguł, co oznacza, iż zostanie ono przepuszczone i wszelkie kolejne reguły zostaną pominięte.
Typowo “allow” stosuje się w regułach dla białych list lub wyjątków, gdzie chcemy upewnić się, iż konkretne zapytania będą automatycznie akceptowane bez dodatkowych kontroli.
Z kolei skonfigurowanie “pass” określa, iż dane zapytanie nie będzie sprawdzane przez reguły określone w “ctl:ruleRemoveById”. Natomiast przez cały czas weryfikacja przez wszystkie pozostałe reguły będzie miała miejsce.
2. Co oznacza “phase”?
Dyrektywa “phase” określa, w którym etapie przetwarzania zapytania HTTP ma zostać wykonana dana reguła. ModSecurity definiuje kilka faz, które pozwalają kontrolować przepływ przetwarzania zapytania od momentu jego odebrania do wysłania odpowiedzi. Poszczególne fazy pozwalają na wykonywanie różnych typów analiz i kontroli na różnych etapach przetwarzania zapytania:
– phase:1 (Request Headers Phase):
Jest to faza analizowania nagłówków zapytania. Reguły w tej fazie mogą sprawdzać nagłówki HTTP jeszcze przed przetworzeniem ciała zapytania. Typowe zastosowanie: filtrowanie na podstawie adresów IP, metod HTTP (np. GET, POST), nagłówków zapytania itp.
– phase:2 (Request Body Phase):
W tej fazie analizowana jest treść (body) zapytania, jeżeli jest dostępna (np. dla żądań POST z danymi formularza lub JSON). Typowe zastosowanie: analiza zawartości formularzy, danych przesyłanych w zapytaniu lub analizy SQL injection, XSS itp.
– phase:3 (Response Headers Phase):
ModSecurity przetwarza nagłówki odpowiedzi serwera, zanim jeszcze zostanie przesłana pełna treść odpowiedzi.Typowe zastosowanie: sprawdzanie nagłówków odpowiedzi, np. Content-Type, aby upewnić się, iż serwer nie wysyła niechcianych treści lub by egzekwować polityki bezpieczeństwa.
– phase:4 (Response Body Phase):
W tej fazie analizowana jest treść odpowiedzi serwera. Typowe zastosowanie: inspekcja zawartości odpowiedzi w celu wykrycia wycieków danych, takich jak numery kart kredytowych, dane osobowe, czy niepożądane treści.
– phase:5 (Logging Phase):
Faza końcowa przeznaczona do logowania. Wszystkie dane są już przetworzone, a celem jest zapisanie logów.
Zazwyczaj nie stosuje się reguł do filtrowania w tej fazie, ponieważ służy ona wyłącznie do rejestracji zdarzeń.
3. Dlaczego raz użyte jest “ctl:ruleRemoveById”, a innym razem “ctl:ruleEngine”?
ctl:ruleRemoveById – usuwa konkretne reguły na podstawie ich ID, umożliwiając bardziej precyzyjne kontrolowanie, które reguły mają być pominięte. W opisywanym przypadku ten atrybut wykluczy stosowne reguły zawarte w silniku web application firewalla dla zapytań mających określone parametry.
ctl:ruleEngine – kontroluje działanie całego silnika reguł ModSecurity, pozwalając na pełne włączenie, wyłączenie lub ograniczenie tylko do detekcji w danym kontekście. Dwie z podanych wyżej przykładowych reguł stosują tę dyrektywę. W jednym przypadku chodzi o białą listę adresów ip wczytywaną z pliku. Natomiast w drugim jest zezwolenie na dostęp do panelu logowania dostępnego pod adresem “/admin/index.php” tylko dla zapytań z adresu IP 1.2.3.4.
Aktualizacja
Co jakiś czas każdy administrator staje przed wymogiem aktualizacji systemu zainstalowanego na danej maszynie. Nie inaczej jest z Nginx. Natomiast, aby nie przerwać przetwarzania przez niego zapytań z powodu błędu niekompatybilności wersji modułu Modsecurity z nową wersją Nginxa, należy najpierw wykonać poniższe kroki:
1. Wykomentowanie zawartości pliku /etc/nginx/snippets/waf.conf. Po skompilowaniu nowej wersji modułu oraz przeprowadzeniu aktualizacji Nginxa należy ponownie odkomentować zawartość wspomnianego pliku.
2. Usunięcie istniejącego pliku modułu ngx_http_modsecurity_module.so ze ścieżki /usr/share/nginx/modules:
3. Usunięcie linku symbolicznego 50-mod-http-modsecurity.conf znajdującego się w ścieżce /etc/nginx/modules-enabled:
4. W tym momencie należy wykonać kroki 1-11 z pierwszej sekcji niniejszego poradnika.
Podsumowanie i wnioski – Implementacja Web Application Firewalla w oparciu o Modsecurity dla Nginx
Internet jest miejscem, w którym istnieje znaczna ilość złośliwego ruchu. Serwery, będące podstawą niejednego biznesu, muszą być odpowiednio chronione. Jednym z narzędzi, które zapewniają skuteczną ochronę jest Web Application Firewall, który skutecznie został wdrożony dzięki niniejszemu poradnikowi. Oczywiście należy pamiętać, iż reguł może być znacznie więcej. Ruch do danej maszyny musi być analizowany, a reguły dostosowywane w taki sposób by eliminować false positives, czyli przypadki ruchu prawidłowego, ale z pewnych powodów zakwalifikowane jako złośliwe.
By jeszcze skuteczniej zadziałać, można skorzystać z narzędzia fail2ban, które po odpowiedniej konfiguracji filtrów będzie banować na zdefiniowany okres wszystkie wystąpienia blokad przeprowadzonych przez WAF.
Autor
Piotr Bracha — pracuje jako administrator systemów. Karierę zaczynał jako młodszy administrator systemów w call center, gdzie miał m.in. możliwość poznania administrowania systemem CentOS i centralą telefoniczną Asterisk. w tej chwili rozwija się w technologiach kontenerowych i chmurowych. Fan automatyzacji i porządku – w kodzie, ale też w środowisku pracy. Artykuły autorstwa Piotra w języku angielskim znajdziesz w serwisie medium.com.