Najważniejsze zasady bezpieczeństwa w aplikacjach webowych – praktyczne wskazówki dla programistów
W branży developmentu oprogramowania panuje pewna niewygodna i często pomijana prawda - 90% poważnych incydentów bezpieczeństwa to bezpośredni efekt błędów programistycznych. Nie są to zatem skutki działania mitycznych, genialnych hakerów w kapturach, którzy łamią szyfry w kilka sekund. Najczęściej są to natomiast proste przeoczenia w kodzie, brak odpowiedniej walidacji danych, czy też pozostawienie domyślnej, niezabezpieczonej konfiguracji serwera.
W obliczu rosnącej liczby ataków i wycieków danych, bezpieczeństwo aplikacji webowych przestało być jedynie "dodatkiem" czy opcjonalnym "ficzerem". Stało się obecnie fundamentem, na którym musi być budowany każdy nowoczesny projekt internetowy. Zaniedbanie tego aspektu już na etapie tworzenia kodu to z kolei prosta droga do katastrofy – nie tylko wizerunkowej, ale i finansowej.
Dlatego też, dbając o najwyższe standardy w naszych projektach, nasz główny programista wziął udział w jednym z najbardziej kompleksowych szkoleń z zakresu bezpieczeństwa webowego w Polsce – Websecurity Master, organizowanym przez Securitum. Kurs ten, oparty na 15-letnim doświadczeniu i tysiącach testów penetracyjnych, stanowi kompendium wiedzy o tym, jak atakujący myślą, jakich narzędzi używają i – co najważniejsze – jak skutecznie się przed nimi bronić.

Kontrola dostępu – najczęściej łamana zasada
Błędy kontroli dostępu (Broken Access Control) zajmują obecnie niechlubne pierwsze miejsce w zestawieniu OWASP Top 10. To właśnie one są najczęstszą przyczyną poważnych incydentów, takich jak nieuprawnione przejęcie danych, podgląd cudzych plików czy eskalacja uprawnień.
Klasycznym przykładem jest IDOR (Insecure Direct Object Reference). Wyobraź sobie, że URL do twojego profilu wygląda tak: /profil?id=123. Co się stanie, jeśli zmienisz 123 na 124? Jeśli aplikacja nie weryfikuje, czy zalogowany użytkownik ma prawo dostępu do profilu o ID 124, właśnie uzyskałeś dostęp do cudzych danych.
Najważniejsze zalecenia:
- Autoryzuj każde żądanie: Nie ufaj, że użytkownik, który zalogował się poprawnie, ma prawo do wykonania każdej akcji.
- Unikaj IDOR: Nigdy nie ufaj parametrom takim jak id przesyłanym przez klienta. Zawsze weryfikuj po stronie serwera, czy użytkownik jest właścicielem zasobu, do którego próbuje uzyskać dostęp.
- Blokuj ukryte ścieżki: Upewnij się, że zasoby, które nie powinny być publicznie dostępne (np. pliki PDF z umowami, endpointy administracyjne).
Sztuka ukrywania tajemnic: Kryptografia i hasła
Kolejnym krytycznym obszarem są błędy kryptograficzne. W 2024 roku wydawałoby się to oczywiste, ale wciąż zdarzają się aplikacje, które nie wymuszają szyfrowania ruchu (TLS minimum 1.2), co oznacza, że wszystkie dane przesyłane między przeglądarką a serwerem mogą zostać podsłuchane.
Jeszcze większym grzechem jest niewłaściwe przechowywanie haseł. Baza danych zawierająca hasła zapisane otwartym tekstem lub – co gorsza – zahaszowane przestarzałymi algorytmami jak MD5 czy SHA1 bez "soli", w przypadku wycieku staje się dla atakującego prezentem na tacy. Nowoczesne podejście wymaga użycia algorytmów, które są z natury "wolne" i trudne do złamania metodą brute-force. Standardem branżowym są obecnie bcrypt, scrypt oraz Argon2. Wykorzystują one mechanizm "soli" (dodatkowej losowej wartości) oraz parametr kosztu, co sprawia, że odzyskanie oryginalnego hasła z jego skrótu jest obliczeniowo nieopłacalne.
Równie ważne jest, aby wszelkie tokeny sesyjne, tokeny resetu hasła czy ciasteczka były generowane w sposób w pełni losowy, przy użyciu bezpiecznych generatorów (CSPRNG), tak aby nie dało się ich przewidzieć i przejąć sesji innego użytkownika.

Kiedy dane wejściowe stają się bronią
Największym błędem, jaki może popełnić programista, jest założenie, że dane przychodzące od użytkownika są bezpieczne. To właśnie brak odpowiedniej walidacji i sanityzacji danych wejściowych otwiera drzwi do całej klasy ataków typu "Injection" (Wstrzyknięcia).
Najbardziej znanym jest SQL Injection, gdzie złośliwie spreparowane dane wpisane w formularz mogą zmodyfikować zapytanie do bazy danych, pozwalając na kradzież lub usunięcie informacji. Jeszcze groźniejsze jest Command Injection, które może prowadzić do zdalnego wykonania kodu (RCE) na serwerze i pełnego przejęcia nad nim kontroli.
Jedyną skuteczną linią obrony jest wówczas stosowanie zapytań parametryzowanych (Prepared Statements) w komunikacji z bazą danych. Dzięki temu dane od użytkownika są zawsze traktowane jako tylko i wyłącznie dane, a nigdy jako część wykonywalnego kodu. Dodatkowo, wszelkie dane wejściowe powinny być filtrowane w oparciu o białą listę (whitelisting) – czyli definiujemy to, co jest dozwolone, a wszystko inne odrzucamy.
Szczególnym przypadkiem, o którym warto wspomnieć, jest funkcjonalność uploadu plików. To mały formularz, który generuje wielkie ryzyko. Jeśli serwer pozwoli na wgranie pliku z rozszerzeniem .php (np. udającego zdjęcie) i jego późniejsze uruchomienie, atakujący w kilka sekund zyskuje dostęp do powłoki systemowej. Dlatego tak ważne jest, aby stosować ścisłą białą listę dozwolonych rozszerzeń i typów plików, a wgrane pliki przechowywać poza głównym katalogiem serwera WWW (webrootem), by nie dało się ich bezpośrednio wywołać z przeglądarki.
Uwierzytelnienie, brute force i błędy w 2FA
Błędy identyfikacji i uwierzytelnienia (Identification and Authentication Failures) pozwalają na przejmowanie kont użytkowników. Jakie są najczęstsze błędy w tym obszarze? Przede wszystkim nieskończone próby logowania, czyli brak ograniczenia liczby prób logowania, co w efekcie pozwala na przeprowadzenie ataku brute-force. Inną zła praktyką są różne komunikaty dla błędnego loginu i hasła. Aplikacja nie powinna bowiem zdradzać, czy podany login istnieje w bazie, a często widujemy komunikaty typu „Błędne hasło dla użytkownika X" vs "Użytkownik nie istnieje" pozwalając tym samym hakerom na stworzenie listy aktywnych kont. Na koniec kilka słów o 2FA, ponieważ nawet wdrożenie 2FA nie gwarantuje bezpieczeństwa, jeśli jest zrobione źle. Typowe błędy to możliwość brute-force'owania krótkich kodów 2FA (np. 4-cyfrowych) lub sytuacja, w której tymczasowy token po pierwszym kroku logowania daje zbyt duże uprawnienia, pozwalając ominąć drugi krok.
Jakie są zalecenia w takich sytuacjach? Przede wszystkim:
- Rate limiting + CAPTCHA: Wdróż mechanizm blokujący użytkownika lub adres IP po kilku nieudanych próbach (Rate Limiting) oraz stosuj CAPTCHA, aby utrudnić automatyczne ataki.
- Ogólne komunikaty logowania: Stosuj ogólne komunikaty błędów, np. "Błędny login lub hasło", aby nie zdradzać, czy użytkownik istnieje w systemie.
- Poprawna implementacja 2FA: Upewnij się, że kody 2FA są odporne na brute-force, wygasają po krótkim czasie, nie można ich użyć ponownie i że tymczasowy token po pierwszym kroku logowania nie daje pełnych uprawnień.
Ukryte zagrożenia - gdy aplikacja atakuje samą siebie
Programiści często zapominają o podatnościach, które nie są widoczne na pierwszy rzut oka. Jednym z takich zagrożeń jest SSRF, czyli Server-Side Request Forgery. Istota tego ataku polega na tym, że atakujący zmusza aplikację do wykonania żądania do zasobów, które normalnie nie są dostępne z zewnątrz, na przykład do wewnętrznej sieci firmy.
Aby temu zapobiec, należy blokować możliwość wykonywania zapytań do adresów wewnętrznych. Innym przykładem jest XXE, czyli atak wykorzystujący zewnętrzne encje XML, który może prowadzić do odczytu lokalnych plików na serwerze. Obrona polega na wyłączeniu obsługi zewnętrznych encji w parserach XML. Z kolei Path Traversal to technika, która pozwala atakującemu na dostęp do plików poza dozwolonym katalogiem poprzez manipulację ścieżkami dostępu. Podstawową zasadą obrony jest brak zaufania do ścieżek plików otrzymywanych od użytkownika.

Nieaktualne komponenty – najłatwiejsza podatność do uniknięcia
Współczesne aplikacje w ogromnym stopniu polegają na gotowych bibliotekach, frameworkach i zewnętrznych komponentach. To naturalne i przyspiesza development. Problemem jest jednak to, że każdy taki element może zawierać błędy bezpieczeństwa, które są sukcesywnie odkrywane i publicznie ogłaszane (np. w bazach CVE).
Używanie przestarzałej wersji biblioteki, o której wiadomo, że posiada krytyczną lukę, to dla hakera zaproszenie do ataku z gotowym "przepisem" w ręku. To najłatwiejsza do uniknięcia, a zarazem jedna z najczęstszych podatności w OWASP Top 10. Co wówczas powinniśmy zrobić? Stosujmy:
- Aktualizacje cykliczne: Zdefiniuj i wdróż proces regularnych przeglądów i aktualizacji wszystkich komponentów aplikacji, w tym bibliotek zależnych, frameworków, a nawet systemu operacyjnego serwera.
- Automatyzacje monitorowania: Nie rób tego ręcznie. Korzystaj z narzędzi takich jak Snyk, Dependabot czy npm audit, które automatycznie skanują zależności twojego projektu, informują o znalezionych podatnościach i często same proponują gotowe pull requesty z aktualizacjami.
Logowanie i monitorowanie – bez tego nie zobaczysz ataku
Wyobraź sobie, że ktoś włamuje się do twojego domu, ale kamery są wyłączone, a alarm nie działa. Tak właśnie wygląda aplikacja bez odpowiedniego logowania i monitorowania. Niewystarczające logowanie (Security Logging and Monitoring Failures) sprawia, że ataki mogą trwać miesiącami, pozostając całkowicie niezauważone. Co gorsza, w przypadku wykrycia incydentu, brak logów uniemożliwia przeprowadzenie analizy powłamaniowej, ustalenie skali szkód i znalezienie luki, która została wykorzystana. Dlatego też zalecamy, by:
- Logować kluczowe zdarzenia: Aplikacja musi rejestrować wszystkie istotne akcje z punktu widzenia bezpieczeństwa, takie jak udane i nieudane próby logowania, błędy walidacji danych, zmiany uprawnień czy dostęp do wrażliwych zasobów. Logi powinny zawierać datę, adres IP, identyfikator użytkownika i opis zdarzenia, ale nigdy nie powinny zawierać wrażliwych danych, takich jak hasła w postaci jawnej czy tokeny sesyjne.
- Centralizować logi: Logi rozproszone na wielu serwerach są bezużyteczne. Należy je gromadzić w centralnym systemie, co umożliwia ich łatwe przeszukiwanie, korelację i analizę w czasie rzeczywistym.
- Tworzyć alerty dla nietypowych zdarzeń: Samo zbieranie logów to za mało. Skonfiguruj system monitorowania tak, aby automatycznie wysyłał powiadomienia w przypadku wykrycia podejrzanych wzorców, np. dużej liczby błędnych logowań z jednego adresu IP w krótkim czasie.

Podsumowanie - kilka zasad, ogromna różnica
Jak zatem widzimy, większość udanych włamań to wynik w głównej mierze łatwych do uniknięcia błędów programistycznych i konfiguracyjnych. Bezpieczeństwo nie jest jednorazowym zadaniem, ale ciągłym procesem, który musi być integralną częścią wytwarzania oprogramowania (S-SDLC).
Przestrzeganie przedstawionych zasad – od walidacji danych i bezpiecznego uwierzytelniania, przez regularne aktualizacje, aż po skuteczne monitorowanie – może diametralnie podnieść poziom bezpieczeństwa Twojej aplikacji. Dlatego też zachęcamy do wdrożenia krótkiej checklisty bezpieczeństwa i regularnego weryfikowania, czy Twój projekt spełnia te kluczowe wymagania. Pamiętaj, że bezpieczny kod to nie tylko ochrona danych, ale także budowanie zaufania użytkowników i klientów.
Najlepsze historie
-
Najlepsze narzędzia do promocji firmy w Internecie
15.09.2023Jak dotrzeć do większej liczby odbiorców i wypromować swoją firmę w Internecie? Odpowiedź na to pytanie kryje się pod dwoma słowami — odpowiedni marketing. Zobacz, z jakich narzędzi Twoja firma może skorzystać, aby zwiększyć swoją rozpoznawalność.
Skutecznych narzędzi do promowania marki osobistej jest bardzo wiele. Na pewno o kliku z nich już słyszałeś lub jesteś w trakcie użytkowania. Z całą pewnością możemy powiedzieć, że reklama w sieci jest ważnym elementem funkcjonowania firmy. Wymagający klienci oraz większa konkurencja sprawiają, że bez względu na to, czy Twoja marka dopiero raczkuje, czy świadczy usługi od dłuższego czasu, powinna promować się w sieci.
-
Jak zoptymalizować stronę internetową pod konkretne wskaźniki Core Web Vitals? Praktyczny poradnik
12.05.2021Google wciąż zmienia swoje algorytmy, ostatnio skupiając się na aspekcie związanym z user experience, czyli doświadczeniami użytkowników stron internetowych. Już w połowie 2021 roku rozpocznie się jedna z największych aktualizacji algorytmu ostatnich lat, wprowadzająca wskaźniki Core Web Vitals, dokładnie oceniające zadowolenie i komfort odbiorców konkretnych witryn. Więcej o tym, czym są Core Web Vitals pisaliśmy TUTAJ. Zmiana ta z pewnością pokazuje nam, w jakim kierunku zmierzają kolejne kroki Google i jak istotne będzie skupienie się na użytkowniku i zapewnieniu mu pełnego komfortu użytkowania serwisów. Jak zoptymalizować stronę internetową pod wskaźniki Core Web Vitals? Co zrobić, aby już teraz przygotować witrynę do zbliżającej się aktualizacji? Podpowiadamy kilka sprawdzonych sposobów.
-
Core Web Vitals, czyli podstawowe wskaźniki internetowe – czym są oraz jak i gdzie je mierzyć?
11.05.2021Na przestrzeni kolejnych lat sposób korzystania z Internetu znacząco się zmienił. Inaczej eksplorujemy poszczególne witryny, przykładamy większą uwagę do ich zawartości. Coraz większe znaczenie ma dla nas również to, jak na danej stronie internetowej udaje nam się poruszać i znaleźć interesującą nas zawartość. To doświadczenie użytkownika, czyli user experience (UX) ma tutaj ogromne znaczenie dla tego, jak odbieramy i oceniamy daną witrynę. To znaczenie dostrzegł też Google, który od jakiegoś czasu systematycznie wdraża inicjatywę pod nazwą Page Experience, czyli zbioru danych, które oceniają jakość stron pod kątem bezpieczeństwa oraz właśnie oczekiwań i doświadczeń użytkowników.


