Lista kontrolna bezpieczeństwa aplikacji webowych dla programistów
To praktyczna, gotowa do audytu lista kontrolna zmapowana na poziomy weryfikacji OWASP ASVS 4.0.3 oraz identyfikatory testów WSTG, których faktycznie użyje pentester. Każdy punkt to konkretne zabezpieczenie, które można wdrożyć, przejrzeć w diffie i przetestować w CI — nie slogan. Pracuj od góry do dołu; każdy niezaznaczony punkt traktuj jako otwarte znalezisko.
Uwierzytelnianie i zarządzanie sesją
Błędy uwierzytelniania odpowiadają OWASP Top 10 A07:2021 oraz rozdziałom ASVS V2 (Authentication) i V3 (Session Management). Celem jest uczynienie kradzieży poświadczeń, ataku brute force i przechwycenia sesji strukturalnie niemożliwymi, a nie tylko utrudnionymi. Weryfikuj każdy punkt względem WSTG-ATHN i WSTG-SESS.
- Przechowuj hasła z użyciem pamięciochłonnej funkcji KDF: Argon2id (≥19 MiB, t=2, p=1) lub bcrypt o koszcie ≥10 / scrypt — nigdy MD5, SHA-1 ani niesolonego SHA-256 (ASVS V2.4).
- Wymuszaj minimalną długość 12 znaków, dopuszczaj pełny zakres Unicode i spacje oraz sprawdzaj nowe hasła względem listy wycieków (API k-anonimowości HIBP) — nie narzucaj reguł złożoności ani wymuszonej rotacji (ASVS V2.1, NIST SP 800-63B).
- Ogranicz tempo prób logowania z wykładniczym opóźnieniem per konto i per adres IP; zwracaj identyczne odpowiedzi i czasy dla poprawnych i błędnych nazw użytkownika, aby zapobiec enumeracji (WSTG-ATHN-03).
- Generuj identyfikatory sesji za pomocą CSPRNG (≥128 bitów entropii) i regeneruj identyfikator sesji przy każdej zmianie uprawnień — logowaniu, wylogowaniu i step-up — aby wyeliminować session fixation (WSTG-SESS-03).
- Ustawiaj ciasteczka sesji jako HttpOnly, Secure i SameSite=Lax lub Strict; ograniczaj je prefiksem __Host- bez jawnego atrybutu Domain (ASVS V3.4).
- Wymuszaj po stronie serwera zarówno limit bezczynności, jak i bezwzględny czas życia sesji; unieważniaj token sesji na serwerze przy wylogowaniu, a nie tylko po stronie klienta.
- Oferuj MFA odporne na phishing — WebAuthn/FIDO2 lub TOTP — i nigdy SMS jako jedyny drugi składnik; wymagaj ponownego MFA przed wrażliwymi działaniami (ASVS V2.2, V2.7).
- Uczyń tokeny resetu hasła jednorazowymi, krótkożyjącymi (≤1 godzina), losowymi i dostarczanymi kanałem out-of-band; unieważniaj wszystkie aktywne sesje przy zmianie hasła (WSTG-ATHN-09).
Kontrola dostępu i autoryzacja
Broken Access Control to A01:2021 — ryzyko numer jeden. Większość tych błędów to luki w logice, których nie wykryje żaden skaner, więc wymagają jawnego egzekwowania po stronie serwera i kontroli per obiekt. Testuj względem WSTG-ATHZ (IDOR, eskalacja uprawnień, path traversal).
- Egzekwuj autoryzację na serwerze dla każdego żądania; domyślnie odmawiaj i nigdy nie polegaj na ukrytym elemencie UI, wyłączonym przycisku ani kontroli roli po stronie klienta jako zabezpieczeniu.
- Weryfikuj własność na poziomie obiektu przy każdym dostępie — pobierz zasób, a następnie potwierdź, że uwierzytelniony podmiot może działać na tym konkretnym ID — aby zapobiec IDOR / BOLA (WSTG-ATHZ-04).
- Używaj nieprzewidywalnych lub pośrednich referencji do obiektów (UUIDv4 lub mapowanie per użytkownik), ale traktuj to jako obronę w głąb, nie zamiennik powyższej kontroli własności.
- Scentralizuj autoryzację w jednej warstwie middleware/polityk (np. silnik ABAC/RBAC) zamiast rozrzucać doraźne instrukcje if po kontrolerach.
- Blokuj ścieżki eskalacji uprawnień: sprawdź, czy użytkownik nie może ustawić własnej roli, tenant_id ani flagi is_admin przez mass-assignment na endpointach tworzenia/aktualizacji (WSTG-ATHZ-02).
- Wymuszaj ochronę CSRF na wszystkich żądaniach zmieniających stan — token synchronizujący lub ciasteczka SameSite plus walidacja Origin/Referer dla działań wrażliwych na cross-site (WSTG-SESS-05).
- Waliduj i kanonikalizuj ścieżki plików oraz importowane URL-e, aby zablokować directory traversal (../) i SSRF wobec wewnętrznych endpointów metadanych jak 169.254.169.254 (WSTG-ATHZ-01, A10:2021).
Walidacja danych wejściowych i kodowanie wyjścia
Injection to A03:2021. Trwałym rozwiązaniem jest rozdzielenie kodu i danych na każdej granicy interpretera — SQL, powłoka OS, LDAP, XML i DOM przeglądarki. Waliduj wejście pod kątem intencji, ale w rzeczywistej obronie polegaj na kontekstowym kodowaniu wyjścia i parametryzacji (WSTG-INPV).
- Używaj zapytań parametryzowanych / prepared statements lub sprawdzonego ORM dla całego dostępu do bazy; nigdy nie buduj SQL przez konkatenację stringów, a każdy dynamiczny identyfikator (tabela/kolumna) waliduj względem allowlisty (WSTG-INPV-05).
- Waliduj całe wejście względem pozytywnej allowlisty — typ, długość, format i zakres — na granicy zaufania; tam gdzie to możliwe odrzucaj zamiast sanityzować (ASVS V5.1).
- Stosuj kontekstowe kodowanie wyjścia w obronie przed XSS: kodowanie encji HTML w treści HTML, kodowanie atrybutów w atrybutach oraz kodowanie JavaScript/URL w ich kontekstach — preferuj auto-escapujące silniki szablonów (WSTG-CLNT-01).
- Unikaj wykonywania poleceń OS z danymi użytkownika; jeśli to nieuniknione, używaj API z tablicą argumentów (execFile, nie shell=True) i nigdy nie przekazuj danych przez interpreter powłoki (WSTG-INPV-12).
- Wyłącz rozwijanie zewnętrznych encji XML (XXE) w każdym parserze XML/SOAP/SVG — ustaw FEATURE_SECURE_PROCESSING i zablokuj DOCTYPE (A05:2021, WSTG-INPV-07).
- Odrzucaj niebezpieczną deserializację: nigdy nie deserializuj niezaufanych danych do dowolnych typów; używaj formatu ograniczonego schematem, jak JSON z jawnym mapowaniem pól (A08:2021).
- Egzekwuj kontrolę uploadu plików po stronie serwera: weryfikuj typ zawartości po magic bytes, ograniczaj rozmiar, przechowuj poza web rootem i serwuj z Content-Disposition: attachment.
- Waliduj cele przekierowań względem allowlisty, aby zapobiec open redirect wykorzystywanym w phishingu (WSTG-CLNT-04).
Nagłówki bezpieczeństwa (CSP, HSTS i inne)
Nagłówki odpowiedzi HTTP to tania, wysoce dźwigniowa obrona w głąb przeciw XSS, clickjackingowi i downgrade protokołu. Brak nagłówków podpada pod A05:2021 Security Misconfiguration; weryfikuj przez WSTG-CONF-07 i skaner jak securityheaders.com lub Mozilla Observatory.
- Wdróż restrykcyjne Content-Security-Policy: preferuj script-src oparte na nonce lub hashu z 'strict-dynamic', ustaw object-src 'none' i base-uri 'none' oraz unikaj 'unsafe-inline' — wdrażaj najpierw przez Content-Security-Policy-Report-Only.
- Ustaw Strict-Transport-Security: max-age=31536000; includeSubDomains; preload i zgłoś domenę na listę HSTS preload, aby zablokować SSL-stripping.
- Wysyłaj X-Content-Type-Options: nosniff w każdej odpowiedzi, aby zatrzymać MIME sniffing.
- Zapobiegaj clickjackingowi przez frame-ancestors 'none' (lub jawną allowlistę) w CSP; utrzymaj X-Frame-Options: DENY jako fallback dla starszych przeglądarek.
- Ustaw Referrer-Policy: strict-origin-when-cross-origin, aby nie wyciekać pełnych URL-i (i tokenów w nich) do stron trzecich.
- Ogranicz funkcje przeglądarki przez Permissions-Policy (np. geolocation=(), camera=(), microphone=()) i ustaw Cross-Origin-Opener-Policy: same-origin.
- Konfiguruj CORS jawnie: odbijaj tylko zweryfikowane originy, nigdy nie łącz Access-Control-Allow-Origin: * z Allow-Credentials: true i waliduj nagłówek Origin po stronie serwera (WSTG-CLNT-07).
Bezpieczeństwo zależności i łańcucha dostaw
Podatne i przestarzałe komponenty to A06:2021; tu żyją incydenty klasy SolarWinds i Log4Shell. Dyscyplina polega na dokładnej wiedzy, co dostarczasz, weryfikacji integralności i łataniu według harmonogramu. Wyrównaj do SLSA i NIST SSDF.
- Uruchamiaj automatyczne SCA (Dependabot, npm audit, OWASP Dependency-Check, Trivy) w CI i przerywaj build przy znanych eksploatowalnych (z listy KEV) lub wysokiej wagi CVE.
- Przypinaj zależności do dokładnych wersji i commituj lockfile (package-lock.json, poetry.lock, go.sum), aby buildy były powtarzalne i weryfikowane hashem.
- Generuj i przechowuj SBOM (CycloneDX lub SPDX) dla każdego wydania, abyś w minuty po nowym CVE mógł odpowiedzieć na pytanie „czy nas dotyczy?”.
- Weryfikuj zależności tranzytywne i uważaj na typosquatting / dependency confusion; zastrzegaj wewnętrzne nazwy paczek i skonfiguruj registry, aby preferowało prywatny indeks.
- Weryfikuj integralność artefaktów podpisami (Sigstore/cosign) i przypinaj zewnętrzne GitHub Actions do pełnego SHA commita, nie zmiennego taga.
- Subskrybuj biuletyny bezpieczeństwa dla kluczowych frameworków i zdefiniuj SLA — np. krytyczne CVE łatane w 72 godziny, wysokie w 7 dni.
- Usuwaj nieużywane zależności i martwe funkcje; każda paczka, której nie dostarczasz, to powierzchnia ataku, której nie musisz bronić.
Zarządzanie sekretami
Zaszyte na stałe poświadczenia to odwieczne znalezisko (CWE-798) i element A05:2021. Sekrety nie powinny nigdy trafiać do kodu źródłowego, obrazów ani logów; powinny być wstrzykiwane w czasie działania, rotowane i ograniczone do najmniejszych uprawnień. Weryfikuj względem ASVS V6 (Stored Cryptography) i V2.10 (poświadczenia usług).
- Trzymaj sekrety poza kontrolą wersji; skanuj repozytorium i całą historię git narzędziami gitleaks lub trufflehog i egzekwuj skaner sekretów w pre-commit / CI jako bramkę merge.
- Przechowuj sekrety w dedykowanym menedżerze (HashiCorp Vault, AWS Secrets Manager, GCP Secret Manager) lub szyfrowanym magazynie platformy — wstrzykuj przez środowisko lub zamontowany wolumin w czasie działania, nigdy nie wypiekaj ich w obrazach kontenerów.
- Rotuj poświadczenia według harmonogramu i natychmiast przy podejrzeniu wycieku; preferuj krótkożyjące, dynamicznie wydawane poświadczenia (dynamic secrets Vault, role IAM chmury / federacja OIDC) zamiast długożyjących kluczy statycznych.
- Ogranicz każdy sekret do najmniejszych uprawnień — użytkownik bazy per usługa z tylko potrzebnymi grantami — aby jeden wyciek nie skompromitował całego systemu.
- Nigdy nie loguj sekretów, tokenów ani pełnych nagłówków autoryzacji; dodaj filtry redakcji do potoku logów i zweryfikuj, że działają.
- Szyfruj sekrety w spoczynku zarządzanym KMS i trzymaj materiał klucza poza tą samą granicą zaufania co dane, które chroni.
Logowanie, monitoring i detekcja
Błędy logowania i monitoringu bezpieczeństwa to A09:2021 — nie zareagujesz na to, czego nie widzisz. Loguj zdarzenia istotne dla bezpieczeństwa w sposób ustrukturyzowany i odporny na manipulację oraz podłącz je do alertowania. Weryfikuj względem ASVS V7 i sygnatur ataków wywiedzionych z WSTG.
- Loguj wszystkie zdarzenia uwierzytelniania (sukces i porażkę), odmowy kontroli dostępu, odrzucenia walidacji wejścia i akcje administracyjne — z informacją kto, co, kiedy i skąd, w ustrukturyzowanym JSON (ASVS V7.1).
- Nigdy nie loguj danych wrażliwych — haseł, tokenów sesji, pełnych numerów kart, sekretów — i neutralizuj log injection przez kodowanie niezaufanych wartości (CWE-117).
- Wysyłaj logi poza host do centralnego, tylko-do-dopisywania magazynu (SIEM), aby atakujący, który przejął maszynę, nie mógł zatrzeć śladów; przechowuj zgodnie z wymogiem compliance.
- Alertuj o sygnałach bezpieczeństwa niemal w czasie rzeczywistym: skoki brute-force, serie błędów autoryzacji, tworzenie nowego admina i znane wzorce ataków — ze ścieżką on-call.
- Dołączaj ID korelacji/żądania między usługami, aby incydent dało się zrekonstruować end-to-end.
- Testuj swoją detekcję: przeprowadź atak (lub ćwiczenie purple team) i potwierdź, że zdarzenie faktycznie wyzwala alert — nieprzetestowane logowanie to teatr.
- Synchronizuj zegary (NTP) i zapisuj znaczniki czasu w UTC, aby osie czasu między systemami były wiarygodne w forensyce.
TLS i bezpieczeństwo transportu
Cryptographic Failures to A02:2021. Wszystkie dane w tranzycie muszą być szyfrowane nowoczesnym, poprawnie skonfigurowanym TLS; ważny certyfikat jest konieczny, ale niewystarczający. Testuj przez WSTG-CRYP-01, testssl.sh i SSL Labs, celując w ocenę A+.
- Serwuj wszystko przez HTTPS i przekierowuj HTTP na HTTPS; w połączeniu z HSTS preload nie dopuszczaj fallbacku do plaintextu.
- Wspieraj tylko TLS 1.2 i TLS 1.3; wyłącz SSLv3, TLS 1.0 i TLS 1.1 oraz usuń zestawy szyfrów export/NULL/RC4/3DES (WSTG-CRYP-01).
- Preferuj zestawy AEAD (AES-GCM, ChaCha20-Poly1305) i włącz forward secrecy wyłącznie przez wymianę kluczy ECDHE.
- Używaj certyfikatów od zaufanego CA z kluczem RSA ≥2048 bitów lub ECDSA P-256; automatyzuj wystawianie i odnawianie (ACME/Let's Encrypt), aby certyfikaty nigdy cicho nie wygasały.
- Włącz OCSP stapling i rozważ rekordy DNS CAA, aby ograniczyć, które CA mogą wystawiać certyfikaty dla Twojej domeny.
- Terminuj TLS także dla wewnętrznego ruchu usługa-usługa (mTLS tam, gdzie to praktyczne) — nie traktuj sieci wewnętrznej jako zaufanej.
- Dla klientów natywnych/mobilnych rozważ certificate pinning i zawsze waliduj pełny łańcuch oraz nazwę hosta — nigdy nie wyłączaj weryfikacji „żeby zadziałało”.
Najważniejsze
- ›Egzekwuj każdą decyzję kontroli dostępu i autoryzacji na serwerze, per obiekt — Broken Access Control (A01) to ryzyko numer jeden, a tych luk logicznych żaden skaner za Ciebie nie znajdzie.
- ›Pokonaj injection (A03) zapytaniami parametryzowanymi i kontekstowym kodowaniem wyjścia, a nie filtrowaniem blocklistą.
- ›Wdróż restrykcyjne CSP oparte na nonce plus HSTS preload, X-Content-Type-Options i frame-ancestors — tanie nagłówki tępiące XSS, downgrade i clickjacking.
- ›Trzymaj sekrety poza kodem, rotuj je i preferuj krótkożyjące, dynamicznie wydawane poświadczenia zamiast kluczy statycznych.
- ›Nie zareagujesz na to, czego nie logujesz: ustrukturyzowane, odporne na manipulację logowanie bezpieczeństwa z przetestowanym alertowaniem zamyka A09.
- ›Mapuj pracę na poziomy OWASP ASVS i identyfikatory testów WSTG, aby „bezpieczne” stało się weryfikowalne, a nie aspiracyjne.
FAQ
Jaka jest różnica między OWASP ASVS a OWASP Top 10?+
Top 10 to dokument uświadamiający, rankingujący dziesięć najbardziej krytycznych kategorii ryzyka (np. A01 Broken Access Control). ASVS to szczegółowy, testowalny standard weryfikacji z setkami konkretnych wymagań w trzech poziomach zapewnienia (L1–L3). Używaj Top 10 do komunikowania ryzyka, a ASVS jako faktycznej listy kontrolnej inżynierskiej.
Jaki poziom ASVS powinna osiągnąć moja aplikacja?+
Poziom 1 to minimum dla każdej aplikacji i jest w dużej mierze testowalny metodami black-box. Poziom 2 to standard dla aplikacji przetwarzających dane wrażliwe — większość aplikacji biznesowych powinna celować w L2. Poziom 3 dotyczy systemów o najwyższym zapewnieniu (płatności, zdrowie, infrastruktura krytyczna) i wymaga głębokiego przeglądu projektu.
Czy lista kontrolna może zastąpić pentest?+
Nie. Lista kontrolna zapobiega znanym klasom defektów i przygotowuje do audytu, ale nie znajdzie luk w logice biznesowej, łańcuchowych eksploitów ani błędów konfiguracji specyficznych dla środowiska. Używaj listy do ciągłego hardeningu w CI, a pentestu do niezależnej weryfikacji, że zabezpieczenia faktycznie wytrzymują atak.
Jak często uruchamiać skanowanie zależności?+
Ciągle. Wepnij SCA (Dependabot, Trivy, OWASP Dependency-Check) w każdy przebieg CI, aby nowy kod był sprawdzany przy commicie, i uruchamiaj też zaplanowane skany głównych gałęzi, aby świeżo ujawnione CVE w już zmergowanych zależnościach były wychwytywane nawet gdy nikt nie wdraża.
Chcesz zweryfikować tę listę względem swojej działającej aplikacji? MonMyIP przeprowadza ustrukturyzowaną ocenę opartą na ASVS/WSTG i dostarcza priorytetyzowany raport naprawczy poparty dowodami. Umów zakresowany pentest aplikacji webowej.