Wstęp
Wiele firm i instytucji ocenia bezpieczeństwo strony internetowej na podstawie prostego wskaźnika: witryna działa, formularz zapisuje dane, a panel logowania jest dostępny. Taki obraz bywa jednak mylący.
Podczas rutynowego audytu lokalnej instytucji trafiłem na system, który dobrze pokazuje problem rozproszonej odpowiedzialności. Warstwa aplikacyjna została wdrożona przez zewnętrzny podmiot, natomiast część treści i formularzy była rozwijana już operacyjnie, bez spójnego procesu bezpieczeństwa.
To studium przypadku pokazuje, jak pozornie działający system może jednocześnie zawierać szereg błędów konstrukcyjnych zwiększających ryzyko incydentu.
Część I: Błędy utrzymaniowe po stronie wykonawcy
Badany system opierał się na zewnętrznym CMS-ie rozwijanym wiele lat temu. Sam wybór gotowego rozwiązania nie jest jeszcze problemem. Ryzyko pojawia się wtedy, gdy po wdrożeniu projekt przestaje być aktualizowany, a jego komponenty pozostają w produkcji mimo publicznie opisanych podatności.
- Przestarzałe komponenty: W systemie znajdowały się biblioteki i dodatki pochodzące z około 2015 roku, dla których od dawna istnieje publiczna dokumentacja podatności oraz znane scenariusze exploitacji.
- Pozorny mechanizm ograniczania prób logowania:: Blokada logowania działała wyłącznie w oparciu o ciasteczko sesyjne po stronie klienta. W praktyce oznaczało to, że reset sesji, np. w trybie incognito, przywracał pełną liczbę prób.
- Brak nagłówków bezpieczeństwa: Serwer nie zwracał podstawowych nagłówków ochronnych, takich jak
Content-Security-PolicyczyStrict-Transport-Security, a jednocześnie ujawniał informacje o stosie technologicznym.
Część II: Formularz zbierający dane wrażliwe
W takim środowisku pojawił się dodatkowy element: formularz udostępniony na serwerze poza głównym procesem wytwórczym. Służył on do zbierania danych o podwyższonej wrażliwości, w tym numerów PESEL, informacji o dochodach oraz pełnych danych adresowych.
Sam formularz był poprawny wizualnie, ale konstrukcyjnie nie spełniał podstawowych wymagań bezpieczeństwa dla tego typu procesu.
- Walidacja wyłącznie po stronie klienta: Obowiązkowość pól oparto na atrybutach HTML, bez potwierdzonej rygorystycznej walidacji po stronie serwera. Taka kontrola nie stanowi realnego zabezpieczenia, ponieważ może zostać całkowicie pominięta przez własny skrypt wysyłający żądanie HTTP.
- Brak ochrony przed automatyzacją: Formularz nie wykorzystywał tokenów CSRF, mechanizmów typu honeypot ani skutecznego ograniczania liczby zgłoszeń. Umożliwiało to masowe wysyłanie fałszywych rekordów i potencjalne zakłócenie pracy systemu.
- Obsługa danych wrażliwych bez potwierdzonego modelu backendowego: Przyjmowanie takiego zakresu danych wymaga pełnej kontroli nad sanitizacją wejścia, logowaniem zdarzeń, polityką retencji oraz uprawnieniami dostępu. W badanym przypadku nie było podstaw, aby założyć, że te warstwy zostały zaprojektowane poprawnie.
Problem odpowiedzialności
Najważniejszy wniosek z tego przypadku dotyczy nie pojedynczego błędu programistycznego, lecz modelu pracy. System został wdrożony przez jeden podmiot, później rozwijany operacyjnie przez kolejne osoby, a całość funkcjonowała bez spójnych procedur aktualizacji i okresowego audytu.
W praktyce oznacza to rozproszenie odpowiedzialności technicznej przy jednoczesnym zachowaniu pełnej odpowiedzialności formalnej po stronie administratora danych, czyli instytucji lub firmy korzystającej z systemu.
Wnioski
Bezpieczeństwo systemu WWW nie powinno być oceniane po warstwie wizualnej ani po tym, że formularz „działa”. O realnym poziomie ochrony decydują mechanizmy wdrożone po stronie serwera: aktualność komponentów, walidacja backendowa, ograniczanie prób nadużyć, polityka nagłówków bezpieczeństwa oraz kontrola nad całym przepływem danych.
W praktyce oznacza to konieczność projektowania systemów zgodnie z podejściem Secure by Design. Frontend pełni rolę interfejsu użytkownika, natomiast krytyczne zabezpieczenia muszą być implementowane w logice aplikacyjnej i infrastrukturze serwera.
Jeżeli witryna przetwarza dane osobowe lub dane o podwyższonej wrażliwości, okresowy audyt kodu i architektury nie jest dodatkiem, lecz elementem podstawowego utrzymania systemu.