Nagłówki bezpieczeństwa WordPress: CSP, HSTS i inne
Nagłówki bezpieczeństwa WordPress: bezpieczne wartości startowe HSTS, CSP, Referrer-Policy i Permissions-Policy, miejsce konfiguracji i unikanie awarii strony.
Także po: English Deutsch Français Español Italiano Português Türkçe
Większość witryn WordPress można w godzinę doprowadzić do dobrej oceny nagłówków. Wystarczy dziś dodać cztery nagłówki o niskim ryzyku: HSTS, X-Content-Type-Options, Referrer-Policy i Permissions-Policy. Content-Security-Policy należy wdrażać powoli, najpierw w trybie report-only. Ten poradnik podaje bezpieczne wartości startowe dla każdego z tych nagłówków bezpieczeństwa WordPress, wskazuje, gdzie je skonfigurować, i ostrzega, które mogą zepsuć edytor lub osadzone treści.
Co robią nagłówki bezpieczeństwa WordPress, a czego nie
Nagłówki bezpieczeństwa to instrukcje, które serwer wysyła do przeglądarki odwiedzającego. Mówią jej, żeby używała wyłącznie HTTPS, nie zgadywała typów plików, nie pozwalała innym witrynom osadzać Państwa stron w ramkach i wskazują, jakie skrypty wolno uruchamiać. Dzięki temu ograniczają ataki typu downgrade, MIME sniffing, clickjacking oraz skutki ataków cross-site scripting (XSS).
Nie załatają za to podatnej wtyczki, nie powstrzymają zgadywania haseł i nie ochronią samego serwera. Jeśli atakujący może zapisywać pliki PHP na serwerze, żaden nagłówek nie pomoże. Nagłówki to jedna warstwa utwardzania po stronie przeglądarki, a nie zamiennik poprawki bezpieczeństwa.
Brakujące nagłówki to klasyczny przykład błędnej konfiguracji zabezpieczeń z listy OWASP Top 10. Są też tanim, dobrze udokumentowanym środkiem, więc wpisują się w „stan wiedzy technicznej”, który należy uwzględnić zgodnie z art. 32 RODO.
Punkt wyjścia: bezpieczne wartości startowe
Poniższe wartości są celowo zachowawcze. Typowa witryna WordPress powinna po nich działać bez zmian, a później można je zaostrzyć.
| Nagłówek | Do czego służy | Bezpieczna wartość startowa |
|---|---|---|
| Strict-Transport-Security | Wymusza HTTPS przy kolejnych wizytach | max-age=300 |
| X-Content-Type-Options | Wyłącza zgadywanie typu MIME | nosniff |
| Referrer-Policy | Ogranicza dane o adresie URL wysyłane do innych witryn | strict-origin-when-cross-origin |
| Permissions-Policy | Wyłącza funkcje przeglądarki, z których Państwo nie korzystają | camera=(), microphone=(), geolocation=() |
| Content-Security-Policy | Ochrona przed osadzaniem w ramkach (na razie) | frame-ancestors 'self' |
| X-Frame-Options | Starsza ochrona przed ramkami | SAMEORIGIN |
HSTS opisuje RFC 6797. Zacznij od pięciu minut (max-age=300) i sprawdź, czy nic się nie psuje. Potem podnieś wartość do doby (86400), następnie do tygodnia, a na końcu do roku (31536000). Dyrektywę includeSubDomains dodaj dopiero wtedy, gdy każda subdomena działa przez HTTPS.
Referrer-Policy w wersji strict-origin-when-cross-origin wysyła do innych witryn tylko nazwę Państwa domeny, a nie pełny adres URL. W WordPressie ma to znaczenie, bo adresy często zawierają parametry zapytania, takie jak wyszukiwane frazy, numery zamówień czy parametry kampanii, i nie powinny one trafiać do osób trzecich.
Permissions-Policy wyłącza kamerę, mikrofon i geolokalizację na Państwa stronach oraz w osadzonych ramkach. Jeśli korzystają Państwo z wyszukiwarki sklepów, która potrzebuje lokalizacji, pominięcie geolocation na liście rozwiązuje sprawę.
Ochrona przed ramkami należy dziś do CSP jako frame-ancestors 'self'. X-Frame-Options: SAMEORIGIN warto zostawić tylko jako zabezpieczenie dla starych przeglądarek. Mała, wymuszana polityka CSP zawierająca wyłącznie frame-ancestors jest bezpieczna do wdrożenia od razu. Pełne CSP przyjdzie później.
X-XSS-Protection jest przestarzały. Nie włączaj go. Sterował filtrem XSS, który nowoczesne przeglądarki usunęły, a sam filtr dawał się wykorzystać do wywoływania nowych problemów na stronach, które poza tym były bezpieczne. Ustawienie 1; mode=block niczego nie daje. Zastępuje go CSP.
Gdzie ustawić nagłówki: serwer, wtyczka czy CDN
Dla każdego nagłówka wybierz jedno miejsce. Jeśli Strict-Transport-Security wysyłają jednocześnie serwer, wtyczka bezpieczeństwa i CDN, pojawiają się zduplikowane lub sprzeczne wartości i nikt nie wie, która z nich obowiązuje.
Najlepszym miejscem jest zwykle serwer WWW. Jego reguły obejmują każdą odpowiedź, także obrazy, pliki CSS i strony serwowane z pełnego cache. Na Apache, który działa na większości hostingów współdzielonych, dodaj poniższe wpisy do pliku .htaccess w katalogu głównym WordPressa, powyżej bloku # BEGIN WordPress. Wymaga to modułu mod_headers:
<IfModule mod_headers.c>
Header always set Strict-Transport-Security "max-age=300"
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 Content-Security-Policy "frame-ancestors 'self'"
Header always set X-Frame-Options "SAMEORIGIN"
</IfModule>
Na nginx równoważne linie umieszcza się w bloku server dla witryny HTTPS, a przed przeładowaniem konfiguracji uruchamia nginx -t:
add_header Strict-Transport-Security "max-age=300" always;
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 Content-Security-Policy "frame-ancestors 'self'" always;
add_header X-Frame-Options "SAMEORIGIN" always;
W nginx jest jedna pułapka. Blok location, który ma własną linię add_header, nie dziedziczy żadnych linii add_header z poziomu server. Nagłówek cache-control dodany dla /wp-content/uploads/ może po cichu usunąć wszystkie nagłówki bezpieczeństwa z tych plików. Powtórz nagłówki w takim bloku albo wydziel je do snippetu i dołączaj go dyrektywą include wszędzie.
Wtyczki i kod korzystające z haka send_headers w WordPressie działają tylko wtedy, gdy stronę buduje PHP. Pliki statyczne nigdy nie przechodzą przez PHP. Strony z pełnego cache również mogą go pomijać, zależnie od tego, jak cache zapisuje i odtwarza nagłówki. Dobrą alternatywą są reguły CDN lub edge, ponieważ obejmują wszystko, co przechodzi przez CDN. Hosting zarządzany często udostępnia własne ustawienia nagłówków w panelu. Jeśli Państwa host to robi, korzystajcie z panelu i nie dublujcie reguł w .htaccess.
Content-Security-Policy bez psucia WordPressa
CSP daje największą korzyść i niesie największe ryzyko. Mówi przeglądarce, z jakich źródeł wolno ładować skrypty, style, obrazy, czcionki i ramki. WordPress to utrudnia. Rdzeń i edytor blokowy generują skrypty i style inline, a page buildery dokładają kolejne. Narzędzia analityczne, osadzenia YouTube i map, banery cookies oraz widżety płatności ładują kod z innych domen. Zbyt restrykcyjna polityka, która zablokuje któryś z tych elementów, może zepsuć finalizację zamówienia albo zostawić pusty ekran edytora.
Zacznij od trybu report-only. Przeglądarka zapisuje wtedy naruszenia, ale niczego nie blokuje:
Content-Security-Policy-Report-Only: default-src 'self'; img-src 'self' data:; object-src 'none'; base-uri 'self'
Otwórz główne typy stron: stronę główną, wpis na blogu, stronę z osadzoną treścią, koszyk i finalizację zamówienia. Następnie w narzędziach deweloperskich przeglądarki sprawdź konsolę dla każdej z nich. Każde naruszenie wskazuje zablokowany zasób i dyrektywę, którą naruszył. Potraktuj tę listę jako inwentarz zapytań do podmiotów trzecich, które wysyła Państwa witryna. Często znajdzie się tam coś, czego nikt nie pamięta, na przykład stary widżet czatu albo czcionki ładowane z Google. Jak sobie z nimi poradzić, opisuje nasz artykuł o Google Fonts.
Dodaj źródła, których naprawdę potrzebujesz, usuń te zbędne i ponownie sprawdź konsolę. Nazwę nagłówka zmień na Content-Security-Policy dopiero wtedy, gdy naruszenia znikną na wszystkich ważnych stronach. W pełnej polityce uwzględnij frame-ancestors 'self': przeglądarki ignorują frame-ancestors w trybie report-only, a pełny nagłówek zastąpi wcześniej ustawiony mały. Najtrudniejsze są skrypty inline: zezwolenie na 'unsafe-inline' odbiera sporą część ochrony przed XSS, a nonce lub hashe wymagają wsparcia ze strony motywu lub wtyczki. Wszystkie dyrektywy opisuje dokumentacja CSP w MDN.
Warto rozważyć wyłączenie wp-admin ze ścisłej polityki, przynajmniej na początku. Na nginx ustaw CSP dla części publicznej w tych lokalizacjach, które obsługują publiczną witrynę, a nie w całym bloku server.
Można dodać punkt końcowy report-uri lub report-to, aby zbierać naruszenia centralnie. Takie raporty zawierają adresy URL stron i dane przeglądarki, a każdy z nich dociera wraz z adresem IP odwiedzającego. Zewnętrzna usługa raportowa zwykle działa jako Państwa podmiot przetwarzający w rozumieniu RODO, więc potrzebna jest umowa powierzenia przetwarzania danych (art. 28). W małej witrynie często wystarczy samodzielne czytanie konsoli.
HSTS preload: dlaczego warto poczekać
Preload umieszcza Państwa domenę na liście, którą przeglądarki mają wbudowaną. Te przeglądarki używają wtedy HTTPS dla domeny jeszcze przed pierwszą wizytą, i to dla każdej subdomeny. Na tym polega problem. Stary host poczty webowej, środowisko testowe, interfejs drukarki albo narzędzie intranetowe działające wyłącznie przez zwykły HTTP przestają być w tych przeglądarkach osiągalne.
Usunięcie domeny z listy jest możliwe, ale trwa długo. Przeglądarki porzucają wpis dopiero wtedy, gdy zmiana dotrze do użytkowników z aktualizacjami przeglądarek. Najlepiej założyć, że ta decyzja jest nieodwracalna.
Podnoś max-age stopniowo i przez jakiś czas utrzymuj wysokie wartości. Wypisz każdą subdomenę używaną w organizacji, także te w DNS, których nikt już nie odwiedza. Preload warto rozważyć dopiero wtedy, gdy wszystkie działają przez HTTPS. Aktualne wymagania wobec nagłówka publikuje serwis zgłoszeniowy hstspreload.org. Czytaj je tam, zamiast kopiować wartości z wpisów na blogach.
Testowanie nagłówków i pilnowanie ich obecności
Sprawdzaj rzeczywiste odpowiedzi, a nie pliki konfiguracyjne. W narzędziach deweloperskich przeglądarki otwórz kartę Network, kliknij żądanie dokumentu i przeczytaj nagłówki odpowiedzi. Z terminala:
curl -sI https://example.com/
curl -sI https://example.com/wp-includes/css/dist/block-library/style.min.css
Szybki przegląd dają publiczne serwisy do sprawdzania nagłówków. OWASP Secure Headers Project wyjaśnia uzasadnienie każdego zalecanego nagłówka. Przetestuj co najmniej te pięć odpowiedzi:
- Strona główna
- Strona serwowana z cache, otwarta bez logowania
- Plik statyczny (CSS, JS lub obraz)
/wp-login.php- Ekran w wp-admin, w tym edytor blokowy
Nagłówki lubią znikać niezauważone. Typowe przyczyny to migracja do innego hosta, która gubi reguły z .htaccess, zmiana w CDN albo nowa wtyczka cache lub bezpieczeństwa wysyłająca własne wartości. Po każdej takiej zmianie sprawdź nagłówki ponownie. Aktywną konfigurację i datę testu przechowuj razem z pozostałą dokumentacją utwardzania z listy kontrolnej bezpieczeństwa. Taki zapis pokaże Państwo w ankiecie klienta lub audytorowi.
Wtyczka audytowa secaudit.eu wykonuje skan utwardzenia i konfiguracji, a swoje ustalenia odnosi do art. 32 RODO i art. 21 NIS2. Warto używać jej obok powyższych kontroli nagłówków → secaudit.eu
FAQ
Czy nagłówki bezpieczeństwa wpływają na SEO lub szybkość strony?
Wpływ jest pomijalny. Dodają kilkaset bajtów do każdej odpowiedzi. HSTS może przy kolejnych wizytach oszczędzić przekierowanie z HTTP na HTTPS.
Czy wtyczka może ustawić za mnie wszystkie nagłówki bezpieczeństwa?
Częściowo. Wtyczka obejmie strony generowane przez PHP, ale może ominąć pliki statyczne i strony z cache. Pewniejsze są reguły serwera lub CDN.
Wysyłać X-XSS-Protection: 0 czy pominąć nagłówek?
Pomiń go albo wyślij 0, jeśli ankieta wymaga jawnej wartości. 0 wyłącza przestarzały filtr. Nigdy nie używaj 1; mode=block.
Czy RODO wymaga HSTS?
Żaden przepis RODO nie wymienia konkretnych nagłówków. RODO wymaga jednak odpowiednich środków bezpieczeństwa z uwzględnieniem stanu wiedzy technicznej. Wymuszenie HTTPS za pomocą HSTS to tani, standardowy środek, który się w tym wymaganiu mieści.
Ten artykuł ma charakter ogólnoinformacyjny i nie stanowi porady prawnej.
Sprawdź swoją stronę
Security Audit & Compliance to wtyczka WordPress od secaudit.eu: wyszukuje złośliwe oprogramowanie, ukryty spam, zmienione pliki rdzenia i podatny kod oraz przypisuje wyniki do art. 32 RODO, art. 21 NIS2 i OWASP Top 10.
Zobacz, co sprawdza wtyczka