Kompleksowy przewodnik po Content Security Policy (CSP) i innych nagłówkach bezpieczeństwa frontendu, chroniący aplikacje internetowe przed atakami i zwiększający bezpieczeństwo użytkowników na całym świecie.
Nagłówki bezpieczeństwa frontendu: Opanowanie Content Security Policy (CSP)
W dzisiejszym cyfrowym świecie, gdzie aplikacje internetowe są coraz bardziej złożone i połączone ze sobą, ochrona przed zagrożeniami bezpieczeństwa jest sprawą nadrzędną. Chociaż bezpieczeństwo backendu często przyciąga znaczną uwagę, bezpieczeństwo frontendu jest równie kluczowe. Nagłówki bezpieczeństwa frontendu działają jako pierwsza linia obrony, dostarczając mechanizmu instruującego przeglądarkę, jak ma się zachowywać i chronić użytkowników przed różnymi atakami. Wśród tych nagłówków, Content Security Policy (CSP) wyróżnia się jako potężne narzędzie do łagodzenia szerokiego zakresu ryzyk.
Czym są nagłówki bezpieczeństwa frontendu?
Nagłówki bezpieczeństwa frontendu to nagłówki odpowiedzi HTTP, które serwer internetowy wysyła do przeglądarki. Nagłówki te zawierają instrukcje dotyczące tego, jak przeglądarka powinna obsługiwać otrzymywaną treść. Pomagają zapobiegać powszechnym atakom, takim jak:
- Cross-Site Scripting (XSS): Wstrzykiwanie złośliwych skryptów do zaufanych stron internetowych.
- Clickjacking: Nakłanianie użytkowników do kliknięcia czegoś innego, niż im się wydaje.
- Ataki typu Man-in-the-Middle: Przechwytywanie komunikacji między użytkownikiem a serwerem.
Do najważniejszych nagłówków bezpieczeństwa frontendu należą:
- Content Security Policy (CSP): Definiuje źródła, z których przeglądarka może ładować zasoby.
- Strict-Transport-Security (HSTS): Zmusza przeglądarkę do używania protokołu HTTPS do całej komunikacji z witryną.
- X-Frame-Options: Zapobiega osadzaniu strony w ramce iframe, łagodząc ataki typu clickjacking.
- X-XSS-Protection: Włącza wbudowany w przeglądarkę filtr XSS. (Uwaga: Często zastępowany przez CSP, ale wciąż może stanowić warstwę obrony).
- Referrer-Policy: Kontroluje ilość informacji o stronie odsyłającej (referrer) wysyłanej z żądaniami.
- Feature-Policy (teraz Permissions-Policy): Pozwala deweloperom na selektywne włączanie i wyłączanie funkcji przeglądarki oraz API.
Dogłębna analiza Content Security Policy (CSP)
Content Security Policy (CSP) to nagłówek odpowiedzi HTTP, który kontroluje zasoby, jakie agent użytkownika (przeglądarka) może załadować dla danej strony. Zasadniczo tworzy białą listę zatwierdzonych źródeł treści, znacznie zmniejszając ryzyko ataków XSS. Poprzez jawne zdefiniowanie pochodzenia zasobów, takich jak skrypty, arkusze stylów, obrazy i czcionki, CSP znacznie utrudnia atakującym wstrzyknięcie złośliwego kodu na Twoją stronę internetową.
Jak działa CSP
CSP działa poprzez dostarczenie przeglądarce listy zatwierdzonych źródeł dla różnych typów treści. Kiedy przeglądarka napotka zasób naruszający CSP, blokuje go i zgłasza naruszenie. Ten mechanizm blokujący zapobiega wykonaniu złośliwego kodu, nawet jeśli atakującemu uda się go wstrzyknąć do kodu HTML.
Dyrektywy CSP
Dyrektywy CSP są podstawowymi składnikami polityki CSP. Określają dozwolone źródła dla różnych typów zasobów. Do najczęściej używanych dyrektyw należą:
- default-src: Ustawia domyślne źródło dla wszystkich typów zasobów. Jest to dyrektywa zapasowa, która ma zastosowanie, gdy nie zdefiniowano innych, bardziej szczegółowych dyrektyw.
- script-src: Określa dozwolone źródła dla JavaScript.
- style-src: Określa dozwolone źródła dla arkuszy stylów CSS.
- img-src: Określa dozwolone źródła dla obrazów.
- font-src: Określa dozwolone źródła dla czcionek.
- media-src: Określa dozwolone źródła dla audio i wideo.
- object-src: Określa dozwolone źródła dla wtyczek, takich jak Flash. (Generalnie najlepiej unikać zezwalania na wtyczki, jeśli to możliwe).
- frame-src: Określa dozwolone źródła dla ramek (iframe).
- connect-src: Określa dozwolone źródła dla żądań sieciowych (AJAX, WebSockets).
- base-uri: Ogranicza adresy URL, które mogą być używane w elemencie
<base>. - form-action: Ogranicza adresy URL, do których mogą być wysyłane formularze.
- frame-ancestors: Określa prawidłowe elementy nadrzędne, które mogą osadzać stronę za pomocą
<frame>,<iframe>,<object>,<embed>lub<applet>. Ta dyrektywa zapewnia ochronę przed atakami typu Clickjacking. - upgrade-insecure-requests: Nakazuje agentom użytkownika traktowanie wszystkich niezabezpieczonych adresów URL witryny (ładowanych przez HTTP) tak, jakby zostały zastąpione bezpiecznymi adresami URL (ładowanymi przez HTTPS). Ta dyrektywa jest przeznaczona dla stron internetowych w trakcie migracji z HTTP na HTTPS.
- report-uri: Określa adres URL, na który przeglądarka powinna wysyłać raporty o naruszeniach CSP. Przestarzałe na rzecz `report-to`.
- report-to: Określa nazwę grupy zdefiniowaną w nagłówku `Report-To`. Pozwala to na bardziej szczegółową kontrolę nad raportowaniem, w tym na określenie wielu punktów końcowych raportowania.
Wartości źródłowe CSP
Wartości źródłowe definiują pochodzenie, z którego zasoby mogą być ładowane. Niektóre popularne wartości źródłowe to:
- *: Pozwala na treści z dowolnego źródła (Unikaj używania w środowisku produkcyjnym!).
- 'self': Pozwala na treści z tego samego pochodzenia (schemat, host i port) co chroniony dokument.
- 'none': Nie pozwala na treści z żadnego źródła.
- 'unsafe-inline': Pozwala na użycie wbudowanego JavaScript i CSS (Unikaj używania w środowisku produkcyjnym!).
- 'unsafe-eval': Pozwala na użycie dynamicznej ewaluacji kodu (np.
eval(),Function()) (Unikaj używania w środowisku produkcyjnym!). - 'strict-dynamic': Określa, że zaufanie jawnie udzielone skryptowi obecnemu w kodzie strony, poprzez dołączenie do niego wartości nonce lub hasha, zostanie rozpropagowane na wszystkie skrypty ładowane przez ten skrypt nadrzędny.
- 'unsafe-hashes': Pozwala na użycie określonych wbudowanych obsług zdarzeń. Jest to generalnie odradzane ze względu na złożoność i ograniczone korzyści.
- data:: Pozwala na ładowanie zasobów z adresów URL danych (np. osadzone obrazy). Używać z ostrożnością.
- mediastream:: Pozwala na użycie URI `mediastream:` jako źródła mediów.
- blob:: Pozwala na użycie URI `blob:` jako źródła mediów.
- filesystem:: Pozwala na ładowanie zasobów z systemu plików.
- https://example.com: Pozwala na treści z określonej domeny i portu.
- *.example.com: Pozwala na treści z dowolnej subdomeny example.com.
- nonce-{random-value}: Pozwala na skrypty lub style z pasującym atrybutem nonce. Wymaga to generowania losowej wartości nonce po stronie serwera dla każdego żądania.
- sha256-{hash-value}: Pozwala na skrypty lub style z pasującym hashem SHA256, SHA384 lub SHA512.
Tryby CSP: Wymuszający (Enforce) vs. Tylko raportujący (Report-Only)
CSP można wdrożyć w dwóch trybach:
- Tryb wymuszający (Enforce Mode): W tym trybie przeglądarka blokuje wszelkie zasoby naruszające CSP. Jest to zalecany tryb dla środowisk produkcyjnych. CSP jest wysyłane za pomocą nagłówka `Content-Security-Policy`.
- Tryb tylko raportujący (Report-Only Mode): W tym trybie przeglądarka raportuje naruszenia CSP, ale nie blokuje zasobów. Jest to przydatne do testowania i oceny CSP przed jego wdrożeniem. CSP jest wysyłane za pomocą nagłówka `Content-Security-Policy-Report-Only`.
Wdrażanie CSP: Przewodnik krok po kroku
Wdrożenie CSP może wydawać się zniechęcające, ale stosując uporządkowane podejście, można skutecznie zabezpieczyć swoją aplikację internetową.
1. Zacznij od polityki w trybie Report-Only
Zacznij od wdrożenia CSP w trybie tylko raportującym. Pozwoli to monitorować naruszenia bez zakłócania funkcjonalności Twojej strony internetowej. Skonfiguruj dyrektywę report-uri lub report-to, aby wysyłać raporty o naruszeniach do wyznaczonego punktu końcowego.
Przykładowy nagłówek (Report-Only):
Content-Security-Policy-Report-Only: default-src 'self'; report-uri /csp-report
2. Analizuj raporty o naruszeniach
Dokładnie analizuj raporty o naruszeniach, aby zidentyfikować, które zasoby są blokowane i dlaczego. Pomoże to zrozumieć zależności zasobów Twojej strony internetowej i zidentyfikować potencjalne luki w zabezpieczeniach.
Raporty o naruszeniach są zazwyczaj wysyłane jako dane JSON do skonfigurowanego punktu końcowego report-uri lub report-to. Raporty te zawierają informacje o naruszeniu, takie jak zablokowany URI, naruszona dyrektywa i URI dokumentu.
3. Dopracuj politykę CSP
Na podstawie raportów o naruszeniach dopracuj swoją politykę CSP, aby zezwolić na legalne zasoby, jednocześnie utrzymując silną postawę bezpieczeństwa. Dodaj określone wartości źródłowe dla zasobów, które są blokowane. Rozważ użycie wartości nonce lub hashy dla wbudowanych skryptów i stylów, aby uniknąć używania 'unsafe-inline'.
4. Przejdź do trybu wymuszającego (Enforce Mode)
Gdy będziesz pewien, że Twoja polityka CSP не blokuje legalnych zasobów, przejdź do trybu wymuszającego. Zablokuje to wszelkie pozostałe naruszenia i zapewni solidną warstwę ochrony przed atakami XSS.
Przykładowy nagłówek (Enforce):
Content-Security-Policy: default-src 'self'; script-src 'self' https://example.com; style-src 'self' 'unsafe-inline'; img-src 'self' data:; report-uri /csp-report
5. Monitoruj i utrzymuj politykę CSP
CSP to nie jest rozwiązanie typu „ustaw i zapomnij”. Niezbędne jest ciągłe monitorowanie polityki CSP i aktualizowanie jej w miarę ewolucji strony internetowej i pojawiania się nowych zagrożeń bezpieczeństwa. Regularnie przeglądaj raporty o naruszeniach i w razie potrzeby dostosowuj politykę.
Praktyczne przykłady CSP
Przyjrzyjmy się kilku praktycznym przykładom CSP dla różnych scenariuszy:
Przykład 1: Podstawowe CSP для prostej strony internetowej
To CSP pozwala na treści z tego samego pochodzenia i zezwala na obrazy z dowolnego źródła.
Content-Security-Policy: default-src 'self'; img-src *
Przykład 2: CSP z określonymi źródłami skryptów i stylów
To CSP zezwala na skrypty z tego samego pochodzenia i z określonego CDN, a także style z tego samego pochodzenia i style wbudowane.
Content-Security-Policy: default-src 'self'; script-src 'self' https://cdn.example.com; style-src 'self' 'unsafe-inline'
Przykład 3: CSP z wartościami nonce dla wbudowanych skryptów
To CSP wymaga unikalnej wartości nonce dla każdego wbudowanego skryptu.
Content-Security-Policy: default-src 'self'; script-src 'self' 'nonce-r4nd0mn0nc3'
HTML:
<script nonce="r4nd0mn0nc3">console.log('Hello, world!');</script>
Ważne: Wartość nonce musi być dynamicznie generowana na serwerze dla każdego żądania. Zapobiega to ponownemu wykorzystaniu nonce przez atakujących.
Przykład 4: CSP ograniczające `frame-ancestors` w celu zapobiegania atakom typu Clickjacking
To CSP uniemożliwia osadzenie strony w ramce iframe na jakiejkolwiek domenie z wyjątkiem `https://example.com`.
Content-Security-Policy: frame-ancestors 'self' https://example.com
Przykład 5: Bardziej restrykcyjne CSP używające 'strict-dynamic' z fallbackiem do 'self'
To CSP wykorzystuje `strict-dynamic` dla nowoczesnych przeglądarek, jednocześnie wspierając starsze przeglądarki, które go не obsługują. Zawiera również `report-uri` do monitorowania naruszeń.
Content-Security-Policy: default-src 'self'; script-src 'strict-dynamic' 'nonce-{random-nonce}' 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; report-uri /csp-report
Pamiętaj, aby zastąpić `{random-nonce}` dynamicznie generowaną wartością nonce po stronie serwera.
CSP a aplikacje jednostronicowe (SPA)
Implementacja CSP w aplikacjach SPA może być wyzwaniem ze względu на dynamiczny charakter tych aplikacji. Aplikacje SPA często w dużym stopniu polegają na JavaScript do generowania i manipulowania DOM, co może prowadzić do naruszeń CSP, jeśli nie zostanie to odpowiednio obsłużone.
Oto kilka wskazówek dotyczących wdrażania CSP w aplikacjach SPA:
- Unikaj
'unsafe-inline'i'unsafe-eval': Te dyrektywy powinny być unikane w aplikacjach SPA, gdy tylko jest to możliwe. Znacznie osłabiają bezpieczeństwo Twojej aplikacji. - Używaj wartości Nonce lub hashy: Używaj wartości nonce lub hashy dla wbudowanych skryptów i stylów. Jest to zalecane podejście dla aplikacji SPA.
- Rozważ użycie Trusted Types: Trusted Types to API przeglądarki, które pomaga zapobiegać podatnościom XSS opartym na DOM. Może być używane w połączeniu z CSP w celu dalszego zwiększenia bezpieczeństwa.
- Używaj frameworka kompatybilnego z CSP: Niektóre frameworki frontendowe (takie jak React z określonymi konfiguracjami, Angular i Vue.js) oferują funkcje ułatwiające implementację CSP.
Inne ważne nagłówki bezpieczeństwa frontendu
Chociaż CSP jest kamieniem węgielnym bezpieczeństwa frontendu, inne nagłówki odgrywają kluczową rolę w zapewnieniu kompleksowej strategii obrony:
Strict-Transport-Security (HSTS)
Nagłówek Strict-Transport-Security (HSTS) instruuje przeglądarkę, aby zawsze używała protokołu HTTPS do łączenia się ze stroną internetową. Zapobiega to atakom typu man-in-the-middle, które próbują obniżyć poziom połączenia do HTTP.
Przykładowy nagłówek:
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
max-age: Określa czas (w sekundach), przez który przeglądarka powinna pamiętać, aby dostęp do strony odbywał się wyłącznie przez HTTPS. Wartość 31536000 sekund (1 rok) jest zalecana dla środowisk produkcyjnych.includeSubDomains: Wskazuje, że polityka HSTS dotyczy wszystkich subdomen danej domeny.preload: Pozwala na umieszczenie domeny na liście domen z włączonym HSTS, która jest wstępnie ładowana do przeglądarek. Wymaga to zgłoszenia domeny do listy preload HSTS prowadzonej przez Google.
X-Frame-Options
Nagłówek X-Frame-Options zapobiega atakom typu clickjacking, kontrolując, czy strona internetowa może być osadzona w ramce iframe.
Przykładowy nagłówek:
X-Frame-Options: DENY
Możliwe wartości:
DENY: Zapobiega wyświetlaniu strony w ramce iframe, niezależnie od pochodzenia.SAMEORIGIN: Pozwala na wyświetlanie strony w ramce iframe tylko wtedy, gdy pochodzenie ramki iframe jest zgodne z pochodzeniem strony.ALLOW-FROM uri: Pozwala na wyświetlanie strony w ramce iframe tylko wtedy, gdy pochodzenie ramki iframe jest zgodne z podanym URI. Uwaga: Ta opcja jest przestarzała i może nie być obsługiwana przez wszystkie przeglądarki.
Uwaga: Dyrektywa frame-ancestors w CSP zapewnia bardziej elastyczny i potężny sposób kontrolowania osadzania i jest generalnie preferowana nad X-Frame-Options.
X-XSS-Protection
Nagłówek X-XSS-Protection włącza wbudowany w przeglądarkę filtr XSS. Chociaż CSP jest bardziej solidnym rozwiązaniem do zapobiegania atakom XSS, ten nagłówek może stanowić dodatkową warstwę obrony, zwłaszcza dla starszych przeglądarek, które mogą nie w pełni obsługiwać CSP.
Przykładowy nagłówek:
X-XSS-Protection: 1; mode=block
1: Włącza filtr XSS.0: Wyłącza filtr XSS.mode=block: Nakazuje przeglądarce zablokowanie strony, jeśli wykryty zostanie atak XSS.report=uri: Określa adres URL, na który przeglądarka powinna wysłać raport, jeśli wykryty zostanie atak XSS.
Referrer-Policy
Nagłówek Referrer-Policy kontroluje ilość informacji o stronie odsyłającej (referrer), która jest wysyłana z żądaniami. Informacje te mogą być używane do śledzenia użytkowników na różnych stronach internetowych, więc ich kontrolowanie może poprawić prywatność użytkowników.
Przykładowy nagłówek:
Referrer-Policy: strict-origin-when-cross-origin
Niektóre popularne wartości:
no-referrer: Nigdy nie wysyłaj nagłówka Referer.no-referrer-when-downgrade: Nie wysyłaj nagłówka Referer do źródeł bez TLS (HTTPS).origin: Wysyłaj tylko pochodzenie (schemat, host i port) w nagłówku Referer.origin-when-cross-origin: Wysyłaj pochodzenie dla żądań cross-origin i pełny URL dla żądań same-origin.same-origin: Wysyłaj nagłówek Referer dla żądań same-origin, ale nie dla żądań cross-origin.strict-origin: Wysyłaj tylko pochodzenie, gdy poziom bezpieczeństwa protokołu pozostaje taki sam (HTTPS do HTTPS), ale nie wysyłaj nagłówka do mniej bezpiecznego miejsca docelowego (HTTPS do HTTP).strict-origin-when-cross-origin: Wysyłaj pochodzenie podczas wykonywania żądania same-origin. Dla żądań cross-origin, wysyłaj pochodzenie tylko wtedy, gdy poziom bezpieczeństwa protokołu pozostaje taki sam (HTTPS do HTTPS), ale nie wysyłaj nagłówka do mniej bezpiecznego miejsca docelowego (HTTPS do HTTP).unsafe-url: Wysyłaj pełny URL w nagłówku Referer, niezależnie od pochodzenia. Używać z najwyższą ostrożnością, ponieważ może to ujawnić wrażliwe informacje.
Permissions-Policy (dawniej Feature-Policy)
Nagłówek Permissions-Policy (dawniej znany jako Feature-Policy) pozwala deweloperom na selektywne włączanie i wyłączanie funkcji przeglądarki oraz API. Może to pomóc w zmniejszeniu powierzchni ataku Twojej aplikacji i poprawie prywatności użytkowników.
Przykładowy nagłówek:
Permissions-Policy: geolocation=()
Ten przykład wyłącza API geolokalizacji dla strony internetowej.
Inne funkcje, które można kontrolować za pomocą Permissions-Policy, to:
cameramicrophonegeolocationaccelerometergyroscopemagnetometerusbmidipaymentfullscreen
Ustawianie nagłówków bezpieczeństwa na różnych platformach
Metoda ustawiania nagłówków bezpieczeństwa różni się w zależności od używanego serwera WWW lub platformy. Oto kilka popularnych przykładów:
Apache
Możesz ustawić nagłówki bezpieczeństwa w Apache, dodając je do pliku .htaccess lub pliku konfiguracyjnego serwera (httpd.conf).
Przykładowa konfiguracja .htaccess:
<IfModule mod_headers.c>
Header set Content-Security-Policy "default-src 'self'; script-src 'self' https://cdn.example.com; style-src 'self' 'unsafe-inline'; img-src 'self' data:; report-uri /csp-report"
Header set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
Header set X-Frame-Options "DENY"
Header set X-XSS-Protection "1; mode=block"
Header set Referrer-Policy "strict-origin-when-cross-origin"
</IfModule>
Nginx
Możesz ustawić nagłówki bezpieczeństwa w Nginx, dodając je do bloku serwera w pliku konfiguracyjnym Nginx (nginx.conf).
Przykładowa konfiguracja Nginx:
server {
listen 443 ssl;
server_name example.com;
add_header Content-Security-Policy "default-src 'self'; script-src 'self' https://cdn.example.com; style-src 'self' 'unsafe-inline'; img-src 'self' data:; report-uri /csp-report";
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload";
add_header X-Frame-Options "DENY";
add_header X-XSS-Protection "1; mode=block";
add_header Referrer-Policy "strict-origin-when-cross-origin";
...
}
Node.js (Express)
Możesz ustawić nagłówki bezpieczeństwa w Node.js, używając oprogramowania pośredniczącego (middleware), takiego jak Helmet.
Przykład z użyciem Helmet:
const express = require('express');
const helmet = require('helmet');
const app = express();
app.use(helmet());
// Dostosuj CSP w razie potrzeby
app.use(helmet.contentSecurityPolicy({
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'", "https://cdn.example.com"],
styleSrc: ["'self'", "'unsafe-inline'"],
imgSrc: ["'self'", "data:"],
reportUri: '/csp-report'
},
}));
app.get('/', (req, res) => {
res.send('Hello World!');
});
app.listen(3000, () => {
console.log('Server listening on port 3000');
});
Cloudflare
Cloudflare pozwala na ustawienie nagłówków bezpieczeństwa za pomocą Page Rules lub Transform Rules.
Testowanie nagłówków bezpieczeństwa
Po wdrożeniu nagłówków bezpieczeństwa kluczowe jest ich przetestowanie, aby upewnić się, że działają poprawnie. Kilka narzędzi online może pomóc w analizie nagłówków bezpieczeństwa Twojej strony internetowej:
- SecurityHeaders.com: Proste i skuteczne narzędzie do analizy nagłówków bezpieczeństwa.
- Mozilla Observatory: Kompleksowe narzędzie do testowania bezpieczeństwa stron internetowych, w tym nagłówków bezpieczeństwa.
- WebPageTest.org: Pozwala na przeglądanie nagłówków HTTP na wykresie wodospadowym.
Podsumowanie
Nagłówki bezpieczeństwa frontendu, zwłaszcza Content Security Policy (CSP), są niezbędne do ochrony aplikacji internetowych przed różnymi atakami i zwiększania bezpieczeństwa użytkowników. Poprzez staranne wdrażanie i utrzymywanie tych nagłówków można znacznie zmniejszyć ryzyko ataków XSS, clickjacking i innych luk w zabezpieczeniach. Pamiętaj, aby zacząć od polityki w trybie tylko raportującym, analizować raporty o naruszeniach, dopracować politykę, a następnie przejść do trybu wymuszającego. Regularnie monitoruj i aktualizuj swoje nagłówki bezpieczeństwa, aby Twoja strona internetowa była bezpieczna w miarę jej ewolucji i pojawiania się nowych zagrożeń.
Przyjmując proaktywne podejście do bezpieczeństwa frontendu, możesz tworzyć bezpieczniejsze i bardziej godne zaufania aplikacje internetowe, które chronią Twoich użytkowników i Twój biznes.