Nagłówki bezpieczeństwa HTTP – jak je sprawdzić i poprawnie skonfigurować?
Data publikacji:
Strona działa przez HTTPS, ma ważny certyfikat i aktualny system CMS. Czy to wystarczy, żeby uznać ją za bezpieczną? Nie. Ochrona witryny zależy również od tego, jakie instrukcje serwer przekazuje przeglądarce wraz z odpowiedzią HTTP. Część z nich może ograniczyć skutki wstrzyknięcia niebezpiecznego skryptu, utrudnić podszywanie się pod stronę w ramce albo zapobiec niezamierzonemu ujawnieniu adresu odwiedzanej podstrony.
Takie instrukcje nazywamy nagłówkami bezpieczeństwa HTTP (ang. HTTP security headers). Ich sprawdzenie zajmuje kilka minut, ale wdrożenie wymaga ostrożności: zbyt restrykcyjna polityka może zablokować logowanie, płatności, mapy, formularze czy zewnętrzne skrypty. W tym poradniku przejdziemy od prostego audytu do bezpiecznej konfiguracji i testów po zmianie.
Kluczowe wnioski
- Nagłówki bezpieczeństwa są częścią odpowiedzi serwera, a nie kodu HTML widocznego na stronie. Można je sprawdzić w narzędziach deweloperskich przeglądarki albo poleceniem
curl. Content-Security-Policy(CSP) kontroluje m.in. źródła skryptów i możliwość osadzania strony w ramce. To ważna warstwa ochrony, ale nie zastępuje naprawy podatności XSS.Strict-Transport-Security(HSTS) pomaga wymusić HTTPS w kolejnych połączeniach. Błędnie wdrożony może jednak utrudnić dostęp do strony lub subdomen.X-Content-Type-Options,Referrer-PolicyiPermissions-Policyzwykle da się wdrożyć stosunkowo łatwo, po sprawdzeniu potrzeb aplikacji.- Samo dodanie nagłówka w konfiguracji nie dowodzi, że jest on wysyłany. Trzeba sprawdzić rzeczywiste odpowiedzi, także dla podstron i błędów.
Co to są nagłówki HTTP i dlaczego mają znaczenie?
Kiedy przeglądarka pobiera stronę, serwer odsyła nie tylko HTML, ale też kod odpowiedzi i zestaw pól opisujących sposób obsługi treści. Przykładowa odpowiedź może wyglądać tak:
HTTP/2 200
content-type: text/html; charset=utf-8
x-content-type-options: nosniff
referrer-policy: strict-origin-when-cross-origin
content-security-policy: frame-ancestors 'self'
Content-Type mówi, jakiego rodzaju dane zostały zwrócone. Pozostałe pola wpływają na zachowanie przeglądarki: czy może zgadywać typ pliku, jakie informacje o poprzedniej stronie ujawnić przy przejściu na inną witrynę i kto może osadzić dokument w ramce.
Nie wszystkie nagłówki chronią przed tym samym zagrożeniem. Nie istnieje też jeden uniwersalny zestaw, który bez zmian pasuje do bloga, sklepu internetowego i aplikacji bankowej. Punktem wyjścia powinno być rozpoznanie funkcji strony, a dopiero potem dobór polityk.
Jak sprawdzić nagłówki bezpieczeństwa w przeglądarce?
W Chrome, Edge i Firefox otwórz stronę, uruchom narzędzia deweloperskie klawiszem F12 i przejdź do zakładki Network (Sieć). Odśwież stronę, kliknij pierwszy dokument HTML, a następnie znajdź sekcję Response Headers (Nagłówki odpowiedzi).
Szukaj przede wszystkim następujących nazw:
Content-Security-PolicyStrict-Transport-SecurityX-Content-Type-OptionsReferrer-PolicyPermissions-PolicyX-Frame-Options
Zwróć uwagę na odpowiedź głównego dokumentu, a nie przypadkowego obrazka czy pliku JavaScript. Jeśli witryna przekierowuje z HTTP na HTTPS, przejrzyj również odpowiedź przekierowującą i ostateczny dokument. Niektóre polityki powinny znajdować się na różnych typach odpowiedzi, inne — na przykład HSTS — są istotne dla połączeń HTTPS.
Brak nagłówka nie musi automatycznie oznaczać luki. Przykładowo współczesne przeglądarki stosują domyślną politykę odsyłania adresu źródłowego, nawet gdy serwer nie wysyła Referrer-Policy. Z drugiej strony sam fakt obecności Content-Security-Policy nie świadczy jeszcze o jej jakości: polityka dopuszczająca wszystko niewiele ogranicza.
Jak sprawdzić nagłówki poleceniem curl?
Jeśli masz dostęp do terminala, wykonaj:
curl -I https://example.com/
Polecenie wyśle żądanie HEAD i pokaże nagłówki odpowiedzi. Jest szybkie, ale niektóre aplikacje obsługują HEAD inaczej niż zwykłe wejście na stronę. Dlatego warto sprawdzić także odpowiedź na GET, bez zapisywania treści:
curl -sS -D - -o /dev/null https://example.com/
Jeżeli interesuje Cię cała ścieżka przekierowań, użyj:
curl -sS -L -D - -o /dev/null http://example.com/
Zobaczysz kolejne zestawy nagłówków. Dzięki temu odróżnisz konfigurację serwera HTTP od docelowego serwera HTTPS. Porównaj też stronę główną, podstronę artykułu, ekran logowania i — jeśli możesz — kontrolowaną odpowiedź 404. Nagłówki mogą różnić się między adresami, nawet w obrębie jednej domeny.
Jeśli wcześniej zdarzały się problemy z przekierowaniami, pomocny będzie też poradnik jak naprawić ERR_TOO_MANY_REDIRECTS.
Które nagłówki warto znać? Praktyczna tabela
| Nagłówek | Główne zadanie | Na co uważać |
|---|---|---|
Content-Security-Policy |
Ogranicza źródła zasobów i niektóre działania dokumentu | Zbyt wąska lista może zablokować skrypty, style i integracje |
Strict-Transport-Security |
Nakazuje przeglądarce korzystać z HTTPS przy kolejnych wizytach | Długi czas obowiązywania i includeSubDomains wymagają przygotowania |
X-Content-Type-Options |
Ogranicza zgadywanie typu MIME | Pliki JS i CSS muszą mieć poprawny Content-Type |
Referrer-Policy |
Ogranicza dane o poprzedniej stronie przekazywane dalej | Niektóre integracje analizują nagłówek Referer |
Permissions-Policy |
Kontroluje dostęp do wybranych funkcji przeglądarki | Nie blokuj kamery czy geolokalizacji, jeśli są potrzebne |
X-Frame-Options |
Ogranicza osadzanie dokumentu w ramce | Nie pasuje do stron, które muszą działać wewnątrz iframe |
Poniżej znajdziesz przykłady wartości, ale potraktuj je jako punkt startowy do testów, a nie gotowy szablon dla każdego serwisu.
Content-Security-Policy (CSP) – najważniejszy i najbardziej wymagający nagłówek
CSP pozwala określić, skąd przeglądarka może pobierać skrypty, style, obrazy, czcionki i inne zasoby. Może też ograniczyć osadzanie dokumentu w ramce, wysyłanie formularzy i ładowanie niebezpiecznych obiektów.
Przykład prostej, dość restrykcyjnej polityki dla witryny bez zewnętrznych integracji:
Content-Security-Policy: default-src 'self'; script-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'self'
Co oznaczają poszczególne fragmenty?
default-src 'self'— domyślnie pozwala ładować zasoby z tego samego źródła, o ile bardziej szczegółowa dyrektywa nie stanowi inaczej.script-src 'self'— ogranicza źródła skryptów; zwykłe skrypty inline mogą zostać zablokowane.object-src 'none'— blokuje osadzanie zasobów przez przestarzałe mechanizmy typuobjectiembed.base-uri 'self'— ogranicza adres, jaki może zostać użyty w elemencie HTML<base>.frame-ancestors 'self'— pozwala osadzać stronę w ramkach pochodzących z tego samego źródła.
Nie wklejaj tej polityki od razu na produkcję. Sklep korzystający z bramki płatności, aplikacja ładująca skrypty analityczne czy strona używająca skryptów inline może przestać działać poprawnie. W nowoczesnych aplikacjach warto docelowo rozważyć politykę opartą na nonce lub hashach zamiast szerokiego dopuszczania skryptów inline.
Jak wdrożyć CSP bez wyłączania połowy strony?
Zacznij od inwentaryzacji zasobów. Otwórz ważne podstrony i sprawdź, skąd pochodzą skrypty, style, obrazy, czcionki, połączenia API oraz ramki. Następnie przetestuj proponowaną politykę za pomocą nagłówka:
Content-Security-Policy-Report-Only: default-src 'self'; script-src 'self'; object-src 'none'; base-uri 'self'
W trybie Report-Only przeglądarka może zgłaszać naruszenia polityki bez blokowania zasobów. Zajrzyj do konsoli DevTools. Jeśli chcesz zbierać raporty centralnie, skonfiguruj odpowiedni punkt raportowania zgodnie z dokumentacją przeglądarek. Nie traktuj każdego zgłoszenia jako dowodu ataku: naruszenia mogą powodować także rozszerzenia przeglądarki i legalne integracje.
Ważny wyjątek: dyrektywy frame-ancestors nie należy weryfikować wyłącznie przez Report-Only — jej skuteczne działanie trzeba sprawdzić po wdrożeniu egzekwowanej polityki, najlepiej najpierw w środowisku testowym. Dyrektywa ta nie działa również po umieszczeniu CSP w znaczniku <meta>.
Po usunięciu uzasadnionych naruszeń wprowadź właściwy nagłówek Content-Security-Policy, przetestuj wszystkie funkcje i obserwuj błędy. Szczegółowe zasady opisuje dokumentacja CSP w MDN.
HSTS – jak wymusić HTTPS i nie zablokować użytkowników?
Nagłówek Strict-Transport-Security informuje przeglądarkę, że w przyszłości powinna łączyć się z daną domeną wyłącznie przez HTTPS. Przykładowo:
Strict-Transport-Security: max-age=300
max-age=300 oznacza pięć minut. Taka krótka wartość może być użyteczna na początku testów. Po potwierdzeniu stabilnego HTTPS i poprawnego odnawiania certyfikatu można rozważyć dłuższy okres, na przykład:
Strict-Transport-Security: max-age=31536000
To rok. Nie dodawaj pochopnie includeSubDomains, ponieważ obejmie także subdomeny, na których mogą działać starsze usługi. Jeszcze większej ostrożności wymaga preload: zgłoszenie domeny do listy preloadingowej jest zobowiązaniem długoterminowym i nie nadaje się do eksperymentów.
HSTS jest honorowany, gdy przeglądarka otrzyma go przez prawidłowe połączenie HTTPS. Nie zastępuje ważnego certyfikatu ani poprawnego przekierowania HTTP → HTTPS. Jeśli certyfikat wygaśnie, użytkownik domeny objętej HSTS może nie mieć możliwości ominięcia ostrzeżenia przeglądarki.
Zanim zwiększysz max-age, sprawdź, czy certyfikat strony jest poprawny i czy odnowienie działa automatycznie. Dalsze wyjaśnienia znajdziesz w dokumentacji HSTS w MDN.
X-Content-Type-Options – prosta ochrona przed błędną interpretacją plików
Typowa wartość to:
X-Content-Type-Options: nosniff
Nagłówek mówi przeglądarce, aby w określonych sytuacjach nie próbowała odgadywać typu danych wbrew zadeklarowanemu Content-Type. Pomaga to ograniczyć ryzyko wykonania pliku w niewłaściwym kontekście.
Po jego włączeniu zweryfikuj, czy serwer wysyła właściwe typy MIME. Skrypt JavaScript nie powinien być serwowany jako text/plain, a arkusz CSS jako text/html. Jeśli serwer zwraca stronę błędu HTML pod adresem pliku .js, przeglądarka może odmówić wykonania takiego zasobu. To często ujawnia wcześniej ukryty błąd konfiguracji, a nie wadę samego nagłówka.
Referrer-Policy – mniej danych ujawnianych przy przechodzeniu na inne strony
Gdy użytkownik klika odnośnik, przeglądarka może przekazać docelowej witrynie informację o stronie, z której przyszedł. Kontroluje to nagłówek Referer — nazwa historycznie zawiera literówkę — oraz polityka Referrer-Policy.
Rozsądną wartością wyjściową jest:
Referrer-Policy: strict-origin-when-cross-origin
Dla przejścia między różnymi bezpiecznymi witrynami przeglądarka przekazuje zwykle samą część origin (schemat, host i port), bez ścieżki oraz parametrów zapytania. Dla żądań do tego samego źródła może przesłać pełniejszy adres. Przy przejściu z HTTPS na HTTP nie wysyła informacji o stronie źródłowej.
To obecnie domyślna polityka nowoczesnych przeglądarek, ale jawne ustawienie ułatwia audyt i zapewnia przewidywalną konfigurację. Jeśli zależy Ci na silniejszej prywatności, rozważ no-referrer, pamiętając o skutkach dla statystyk i integracji. Porównanie wariantów znajduje się w dokumentacji MDN.
Permissions-Policy – kontrola funkcji przeglądarki
Ten nagłówek pozwala ograniczyć dostęp dokumentu i osadzonych w nim ramek do wybranych funkcji przeglądarki. Na zwykłej stronie informacyjnej można rozważyć:
Permissions-Policy: camera=(), microphone=(), geolocation=()
Puste nawiasy oznaczają, że wskazane funkcje nie są dozwolone. Jeśli serwis oferuje wideorozmowy, nagrywanie głosu lub mapę ustalającą lokalizację użytkownika, taki zestaw może zepsuć potrzebne funkcje. Wybieraj tylko ograniczenia zgodne z przeznaczeniem strony.
Nagłówek nie zastępuje systemowych uprawnień ani pytania użytkownika o zgodę na dostęp do urządzenia. Stanowi dodatkowe ograniczenie tego, co strona w ogóle może zrobić.
X-Frame-Options i frame-ancestors – ochrona przed clickjackingiem
Clickjacking polega na nakłonieniu użytkownika do kliknięcia elementu strony, który został ukryty lub zwodniczo osadzony w innym serwisie. Jedną z warstw ochrony jest ograniczenie możliwości wyświetlania dokumentu w ramce.
Starszy mechanizm wygląda tak:
X-Frame-Options: SAMEORIGIN
Jeżeli strona nie powinna być osadzana nigdzie, można użyć DENY. Bardziej elastyczne podejście zapewnia CSP:
Content-Security-Policy: frame-ancestors 'self'
Dyrektywa frame-ancestors pozwala wskazać dopuszczone źródła osadzające stronę. Nie myl jej z frame-src, która kontroluje ramki ładowane przez Twoją stronę. Jeśli serwis ma być legalnie osadzany w systemie klienta, sprawdź wymagane domeny i przetestuj integrację przed włączeniem blokady.
Współczesne przeglądarki preferują frame-ancestors, a X-Frame-Options może służyć jako zgodne z zamierzoną polityką uzupełnienie dla starszych klientów. Nie ustawiaj wzajemnie sprzecznych reguł.
Przykład konfiguracji nagłówków w Nginx
Poniższy przykład pokazuje minimalny zestaw do adaptacji, a nie kompletny plik serwera. Zakładamy, że HTTPS i certyfikat są już skonfigurowane:
server {
listen 443 ssl;
server_name example.com;
# Konfiguracja certyfikatu i pozostałych lokalizacji jest pominięta.
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header Content-Security-Policy "frame-ancestors 'self'; object-src 'none'; base-uri 'self'" always;
# Włącz dopiero po zweryfikowaniu HTTPS i planu odnowień.
# add_header Strict-Transport-Security "max-age=300" always;
}
W tym przykładzie CSP celowo nie wprowadza restrykcyjnej polityki script-src ani default-src. To nie jest pełna ochrona przed XSS — taką politykę należy przygotować na podstawie rzeczywistych zasobów aplikacji. Nawet pokazane ograniczenia (object-src, base-uri, ramki) wymagają testów.
Po zmianie konfiguracji wykonaj:
sudo nginx -t
sudo systemctl reload nginx
curl -sS -D - -o /dev/null https://example.com/
Pułapka dziedziczenia add_header
W Nginx łatwo przeoczyć ważny szczegół: gdy wewnątrz location ustawisz własne add_header, domyślnie nagłówki z nadrzędnego bloku server mogą przestać być dziedziczone w tej lokalizacji. Dotyczy to nawet pozornie niezwiązanej dyrektywy Cache-Control.
Od wersji Nginx 1.29.3 dostępna jest dyrektywa add_header_inherit merge;, która pozwala zmienić sposób dziedziczenia. Nie zakładaj jednak, że masz ją w pakiecie systemowym. Na starszych wersjach zwykle trzeba powtórzyć wspólny zestaw dyrektyw w odpowiednich lokalizacjach, np. przez include. W każdym przypadku sprawdź nagłówki faktycznie zwracane dla różnych adresów. Szczegóły opisuje oficjalna dokumentacja Nginx.
Parametr always sprawia, że nagłówek jest dodawany także do odpowiedzi o kodach, dla których zwykłe add_header mogłoby go pominąć. To istotne na przykład dla stron błędów.
Przykład konfiguracji w Apache i pliku .htaccess
W Apache 2.4 nagłówki można ustawiać za pomocą modułu mod_headers. Jeśli hosting dopuszcza takie dyrektywy w .htaccess, przykładowy zestaw wygląda następująco:
<IfModule mod_headers.c>
Header always set X-Content-Type-Options "nosniff"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
Header always set Permissions-Policy "camera=(), microphone=(), geolocation=()"
Header always set X-Frame-Options "SAMEORIGIN"
Header always set Content-Security-Policy "frame-ancestors 'self'; object-src 'none'; base-uri 'self'"
</IfModule>
HSTS ustawiaj osobno w konfiguracji obsługującej HTTPS, po przeprowadzeniu opisanych wcześniej testów. Zanim wprowadzisz zmiany, zachowaj kopię konfiguracji. Pamiętaj też, że .htaccess nie działa w Nginx. Na hostingu zarządzanym nagłówki może ustawiać panel, CDN lub aplikacja — wtedy warto wybrać jedno miejsce odpowiedzialne za daną politykę.
Moduł Apache rozróżnia wewnętrzne zestawy nagłówków onsuccess i always; w niektórych konfiguracjach proxy lub PHP może to prowadzić do zduplikowanych pól. Po wdrożeniu sprawdź odpowiedź, zamiast zakładać, że Header always set automatycznie usuwa wszystkie wcześniejsze wartości. Więcej szczegółów zawiera dokumentacja mod_headers.
A co z WordPressem i usługami CDN?
W WordPressie nagłówki mogą być dodawane przez serwer WWW, wtyczkę, usługę CDN lub warstwę reverse proxy. Włączenie podobnych opcji w kilku miejscach naraz utrudnia diagnostykę. Jeśli masz Apache, plik .htaccess może być właściwym miejscem, ale aktualizacja wtyczki bezpieczeństwa albo zmiana hostingu może zmienić ostateczne nagłówki.
Przed wdrożeniem CSP sprawdź działanie edytora blokowego, formularzy, wyszukiwarki, osadzonych filmów, panelu logowania, CAPTCHA, narzędzi analitycznych i płatności. Szczególnie często problemem okazują się skrypty inline oraz zasoby z zewnętrznych domen. Jeżeli naprawiasz również inne problemy witryny, pomocny może być poradnik jak naprawić stronę na WordPressie.
Jeśli korzystasz z CDN, porównaj odpowiedź widoczną dla użytkownika z odpowiedzią serwera źródłowego. Usługa pośrednicząca może dodać, usunąć lub nadpisać nagłówek. Niektóre reguły obejmują tylko wybrane ścieżki, dlatego test strony głównej nie wystarczy.
Najczęstsze błędy podczas wdrażania nagłówków
1. Kopiowanie gotowej CSP bez sprawdzenia aplikacji. Zablokowane skrypty mogą uniemożliwić zakupy, logowanie lub wysyłanie formularzy. Zacznij od audytu zasobów i stopniowego zaostrzania polityki.
2. Natychmiastowe ustawienie HSTS na rok wraz z includeSubDomains. Jeśli choć jedna subdomena działa wyłącznie po HTTP, część użytkowników straci do niej dostęp. Najpierw zinwentaryzuj subdomeny i sprawdź certyfikaty.
3. Testowanie tylko strony głównej. Panel administracyjny, pliki statyczne, podstrony i strony błędów mogą mieć inną konfigurację nagłówków.
4. Dublowanie nagłówków w aplikacji, CDN i serwerze. Szczególnie kilka niezależnych polityk CSP może dać bardziej restrykcyjny efekt, niż zamierzono. Ustal, która warstwa odpowiada za każdą politykę.
5. Traktowanie wyniku skanera jako pełnego audytu bezpieczeństwa. Skaner może wykryć brak HSTS, ale nie sprawdzi poprawności autoryzacji, podatności w kodzie ani jakości zarządzania sesją. Nagłówki są tylko jedną warstwą ochrony.
6. Dodawanie przestarzałych nagłówków bez zastanowienia. Na przykład X-XSS-Protection nie zastępuje nowoczesnej CSP i nie jest zalecanym sposobem ochrony współczesnych aplikacji. Zamiast mechanicznie kopiować stare poradniki, sprawdź aktualne zalecenia w OWASP HTTP Headers Cheat Sheet.
Lista kontrolna po wdrożeniu
Po każdej zmianie przeprowadź krótki test regresyjny:
- Sprawdź odpowiedź
GETstrony głównej oraz kilku ważnych podstron. - Przejrzyj nagłówki przy przekierowaniu z HTTP na HTTPS i w odpowiedzi docelowej.
- Sprawdź nagłówki dla odpowiedzi
404oraz — jeśli można to zrobić bezpiecznie — kontrolowanego błędu aplikacji. - Otwórz DevTools i sprawdź, czy konsola nie zgłasza nowych naruszeń CSP oraz czy wszystkie skrypty i style się ładują.
- Przetestuj logowanie, formularze, wyszukiwarkę, koszyk, płatności, multimedia i integracje zewnętrzne.
- Zweryfikuj HTTPS, ważność certyfikatu i plan jego automatycznego odnawiania przed wydłużeniem HSTS.
- Sprawdź stronę z telefonu oraz w drugiej przeglądarce, szczególnie gdy używasz iframe lub funkcji urządzenia.
- Zapisz konfigurację, datę wdrożenia i sposób szybkiego wycofania zmiany.
Warto też monitorować dostępność strony i ważne ścieżki użytkownika po wdrożeniu. Nagłówek może nie spowodować błędu HTTP, a mimo to zablokować skrypt potrzebny do wykonania zamówienia. Dlatego zwykły test „czy serwer zwraca 200” nie wystarczy. Więcej o wykrywaniu problemów opisujemy w artykule monitoring dostępności strony — jak szybko wykrywać awarie. Do ciągłej kontroli działania witryny możesz też wykorzystać Ping.pl.
Podsumowanie
Nagłówki bezpieczeństwa HTTP to stosunkowo niewielka zmiana konfiguracyjna, która może realnie ograniczyć niektóre zagrożenia po stronie przeglądarki. Zacznij od sprawdzenia rzeczywistych odpowiedzi serwera, następnie rozważ X-Content-Type-Options, Referrer-Policy, Permissions-Policy i ochronę przed osadzaniem w ramkach. CSP wdrażaj stopniowo, a HSTS dopiero po upewnieniu się, że HTTPS działa stabilnie również w dłuższym okresie.
Najważniejsza zasada brzmi: bezpieczeństwo to nie liczba nagłówków, lecz ich poprawne dopasowanie do aplikacji i potwierdzone działanie. Po wdrożeniu testuj nie tylko nagłówki, ale też funkcje, z których korzystają użytkownicy. I pamiętaj, że żaden nagłówek nie zastąpi aktualizacji oprogramowania, bezpiecznego kodu, kontroli dostępu ani regularnych kopii zapasowych.