Powrót do bloga

Security headers: HSTS, CSP, X-Frame-Options i inne

· 7 min czytania

W skrócie: Security HTTP headers to linie, które serwer dodaje do każdej odpowiedzi HTTP, aby powiedzieć przeglądarce, jak ma traktować twoją stronę. Poprawnie ustawione eliminują całe klasy ataków (XSS, clickjacking, MITM) - i są darmowe.

W skrócie: Security HTTP headers to linie, które serwer dodaje do każdej odpowiedzi HTTP, aby powiedzieć przeglądarce, jak ma traktować twoją stronę. Poprawnie ustawione eliminują całe klasy ataków (XSS, clickjacking, MITM) - i są darmowe.

Dlaczego mają znaczenie

Aplikacja może być backend-side doskonale bezpieczna, ale bez odpowiednich headerów wciąż podatna na ataki browser-side: cross-site scripting (XSS), clickjacking, protocol downgrade, MIME confusion. Security headers przesuwają obronę do przeglądarki.

Strict-Transport-Security (HSTS)

Wymusza HTTPS dla wszystkich przyszłych odwiedzin. Po pierwszej wizycie HTTPS przeglądarka zapamiętuje domenę i sama przepisuje każdy link http:// na https://, nawet jeśli użytkownik kliknie złą odpowiedź.

Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
  • max-age=63072000 = obowiązuje 2 lata
  • includeSubDomains = reguła obowiązuje też dla wszystkich subdomen (uwaga: jeśli masz subdomenę HTTP-only, zepsuje ją)
  • preload = pozwala na włączenie do listy HSTS preload wbudowanej w Chrome / Firefox / Safari

Uwaga: HSTS z preload jest usuwany z listy 6+ miesięcy. Nie włączaj preload zanim nie zweryfikujesz, że HTTPS działa stabilnie dla wszystkich subdomen.

Content-Security-Policy (CSP)

Najmocniejszy ale również najtrudniejszy do skonfigurowania header. Whitelistuje, skąd przeglądarka może załadować skrypty, style, obrazy, iframe-y. Bez CSP atakujący, który potrafi wstrzyknąć tag <script>, może uruchomić dowolny JS - z CSP tylko kod ze zatwierdzonych źródeł.

Content-Security-Policy: default-src 'self'; script-src 'self' 'sha256-...'; img-src 'self' data: https://cdn.example.com; style-src 'self' 'unsafe-inline'; frame-ancestors 'none'

Zwykłe dyrektywy:

  • default-src 'self' = jako default pozwól tylko zasoby z mojej domeny
  • script-src = źródła JS (określ hash lub nonce dla skryptów inline)
  • style-src = źródła CSS
  • img-src = obrazy
  • connect-src = AJAX, WebSocket, EventSource
  • frame-ancestors 'none' = nikt nie może osadzić strony w iframe (lepsze niż X-Frame-Options)
  • report-uri /csp-report = browser wysyła JSON przy każdej violation (ty łapiesz w backend i logujesz)

X-Frame-Options

Starsza alternatywa do frame-ancestors. Chroni przed clickjackingiem - atakujący wkłada twoją stronę jako iframe i pokrywa niewidzialnymi przyciskami.

X-Frame-Options: DENY

Wartości: DENY (nikt), SAMEORIGIN (tylko moja domena), ALLOW-FROM uri (deprecated).

X-Content-Type-Options

X-Content-Type-Options: nosniff

Wyłącza MIME sniffing - przeglądarka będzie respektować Content-Type, który zwrócił serwer. Bez tego atakujący może wgrać plik z błędnym typem (np. obraz, który w rzeczywistości jest HTML ze skryptem) i przeglądarka może go uruchomić jako web page.

Referrer-Policy

Referrer-Policy: strict-origin-when-cross-origin

Kontroluje, ile informacji o poprzedniej stronie przeglądarka wysyła w nagłówku Referer przy kliknięciu. Default w nowoczesnych przeglądarkach już jest strict-origin-when-cross-origin, ale jawny deklaratywny header zapewnia spójność.

Permissions-Policy

Wyłącza API, których nie potrzebujesz - kamerę, mikrofon, GPS, geolocation. Atakujący przez XSS nie może żądać tych API.

Permissions-Policy: camera=(), microphone=(), geolocation=(), payment=()

Praktyczna konfiguracja w nginx

server {
  listen 443 ssl http2;
  server_name example.com;

  add_header Strict-Transport-Security "max-age=63072000; includeSubDomains" always;
  add_header X-Content-Type-Options "nosniff" always;
  add_header X-Frame-Options "DENY" always;
  add_header Referrer-Policy "strict-origin-when-cross-origin" always;
  add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;

  # CSP jest rozległa - zdefiniuj według swojej aplikacji
  add_header Content-Security-Policy "default-src 'self'; script-src 'self'; ..." always;
}

Kluczowe jest always - bez niego nginx pomija headery przy odpowiedziach error (4xx, 5xx).

Audit aktualnego stanu

Najprościej przez narzędzie online. Nasz header check pokaże ci, których headerów brakuje i które są niewłaściwe. Dla dokładnego audytu securityheaders.com również daje wynik A-F.

Wnioski

Security headery są jedną z najlepszych inwestycji w stosunku wysiłek do zysku w obszarze security - typowo pół godziny ustawienia w reverse proxy przeciwko całej kategorii ataków browser-side. Audit raz na pół roku w ramach regularnej konserwacji to rozsądne minimum.

Bezpłatny audit security headers

Bez rejestracji, wynik w trzy sekundy.

Przetestuj stronę →


Wypróbuj ePulz.io za darmo - 7 dni bez karty kredytowej.

Załóż konto