Zapobieganie wyciekom informacji z wykorzystaniem CSRF, XSS i cross-origin.
Dlaczego warto izolować zasoby internetowe?
Wiele aplikacji internetowych jest podatnych na ataki z innych źródeł, takie jak fałszowanie żądań z innych witryn (CSRF), wstawianie skryptów z innych witryn (XSSI), ataki oparte na czasie, wyciek informacji z innych źródeł lub ataki typu spekulacyjne (Spectre).
Nagłówki żądań Pobierz metadane umożliwiają wdrażanie silnego mechanizmu obrony w głębi (zasady izolacji zasobów), aby chronić aplikację przed tymi typowymi atakami między domenami.
Zasoby udostępnione przez daną aplikację internetową są zwykle wczytywane tylko przez tę aplikację, a nie przez inne witryny. W takich przypadkach wdrożenie zasady izolacji zasobów na podstawie nagłówków żądań pobierania metadanych nie wymaga wiele wysiłku, a jednocześnie chroni aplikację przed atakami na wiele witryn.
Zgodność z przeglądarką
Nagłówki żądań pobierania metadanych są obsługiwane we wszystkich nowoczesnych silnikach przeglądarek.
Tło
Wiele ataków na wiele witryn jest możliwych, ponieważ internet jest domyślnie otwarty, a serwer aplikacji nie może łatwo chronić się przed komunikacją pochodzącą z zewnętrznych aplikacji. Typowym atakiem między domenami jest fałszowanie żądań między domenami (CSRF), w którym atakujący zwodzi użytkownika, aby ten odwiedził witrynę kontrolowaną przez atakującego, a następnie przesyła formularz na serwer, na którym użytkownik jest zalogowany. Ponieważ serwer nie może określić, czy żądanie pochodzi z innej domeny (z innej witryny), a przeglądarka automatycznie dołącza pliki cookie do żądań z innych witryn, serwer wykona działanie zażądane przez atakującego w imieniu użytkownika.
Inne ataki między witrynami, takie jak wstawianie skryptu między witrynami (XSSI) czy wycieki informacji między domenami, mają charakter podobny do ataku CSRF i polegają na wczytywaniu zasobów z aplikacji ofiary w dokument kontrolowany przez atakującego oraz na wycieku informacji o aplikacji ofiary. Aplikacje nie mogą łatwo odróżnić żądań zaufanych od nieznanych, więc nie mogą odrzucać złośliwego ruchu w różnych witrynach.
Przedstawiamy Fetch Metadata
Nagłówki żądania pobierania metadanych to nowa funkcja zabezpieczeń platformy internetowej, która pomaga serwerom bronić się przed atakami między domenami. Podając informacje o kontekście żądania HTTP w zestawie nagłówków Sec-Fetch-*
, pozwalają serwerowi odpowiadającemu na żądanie zastosować zasady bezpieczeństwa przed przetworzeniem żądania. Dzięki temu deweloperzy mogą decydować, czy zaakceptować czy odrzucić prośbę na podstawie sposobu jej przesłania i kontekstu, w jakim ma być wykorzystana. Umożliwia to odpowiadanie tylko na uzasadnione prośby wysłane przez własną aplikację.
Sec-Fetch-Site
Sec-Fetch-Site
informuje serwer, z którego witryny pochodzi żądanie. Przeglądarka ustawia tę wartość na jedną z tych wartości:
same-origin
, jeśli prośba została wysłana przez Twoją aplikację (np.site.example
)same-site
, jeśli prośba została wysłana przez subdomenę Twojej witryny (np.bar.site.example
)none
, jeśli żądanie zostało wyraźnie wywołane przez interakcję użytkownika z klientem użytkownika (np. kliknięcie zakładki);cross-site
, jeśli prośba została wysłana z innej witryny (np.evil.example
)
Sec-Fetch-Mode
Sec-Fetch-Mode
wskazuje tryb żądania. Odpowiada ono w przybliżeniu rodzajowi żądania i pozwala odróżnić wczytywanie zasobów od żądań nawigacyjnych. Na przykład wartość navigate
wskazuje żądanie nawigacji najwyższego poziomu, a no-cors
– żądanie zasobu, np. wczytywania obrazu.
Sec-Fetch-Dest
Sec-Fetch-Dest
podaje miejsce docelowe żądania (np. czy żądanie zostało przesłane przez przeglądarkę z powodu tagu script
lub img
).
Jak używać funkcji pobierania metadanych, aby chronić się przed atakami między domenami
Dodatkowe informacje zawarte w tych nagłówkach żądań są dość proste, ale dodatkowy kontekst umożliwia tworzenie za pomocą zaledwie kilku linii kodu zaawansowanej logiki zabezpieczeń po stronie serwera, zwanej też zasadą izolacji zasobów.
Wdrażanie zasady izolacji zasobów
Zasady izolacji zasobów uniemożliwiają zewnętrznym witrynom wysyłanie żądań do Twoich zasobów. Blokowanie takiego ruchu pozwala ograniczyć częste luki w zabezpieczeniach w witrynach internetowych, takie jak CSRF, XSSI, ataki na czas trwania operacji i wycieki informacji z wielu źródeł. Te zasady można włączyć dla wszystkich punktów końcowych aplikacji. Umożliwi to wszystkie żądania zasobów pochodzące z Twojej aplikacji, a także bezpośrednie przejścia (za pomocą żądania HTTP GET
). Punkty końcowe, które mają być wczytywane w kontekście wielu witryn (np. punkty końcowe wczytywane za pomocą CORS), mogą być wyłączone z działania tej logiki.
Krok 1. Zezwalaj na żądania z przeglądarek, które nie wysyłają żądania pobierania metadanych
Nie wszystkie przeglądarki obsługują pobieranie metadanych, więc musisz zezwolić na żądania, które nie ustawiają nagłówków Sec-Fetch-*
, sprawdzając obecność nagłówka sec-fetch-site
.
if not req['sec-fetch-site']:
return True # Allow this request
Krok 2. Zezwól na żądania z tej samej witryny i inicjowane przez przeglądarkę
Dozwolone będą wszystkie żądania, które nie pochodzą z kontekstu z innej domeny (np. evil.example
). Dotyczy to w szczególności żądań, które:
- pochodzić z Twojej aplikacji (np. żądanie z tego samego pochodzenia, w którym żądania
site.example
będą zawsze dozwolone);site.example/foo.json
- pochodzą z Twoich subdomen,
- są wyraźnie wywoływane przez użytkownika (np. przez bezpośrednie przejście do witryny lub kliknięcie zakładki);
if req['sec-fetch-site'] in ('same-origin', 'same-site', 'none'):
return True # Allow this request
Krok 3. Zezwól na prostą nawigację na najwyższym poziomie i ramowanie
Aby umożliwić linkowanie do Twojej witryny z innych witryn, musisz zezwolić na prostą nawigację najwyższego poziomu (HTTP GET
).
if req['sec-fetch-mode'] == 'navigate' and req.method == 'GET'
# <object> and <embed> send navigation requests, which we disallow.
and req['sec-fetch-dest'] not in ('object', 'embed'):
return True # Allow this request
Krok 4. Wyłącz punkty końcowe, które mają obsługiwać ruch z wielu witryn (opcjonalnie)
W niektórych przypadkach aplikacja może udostępniać zasoby, które mają być ładowane w różnych witrynach. Te zasoby muszą być wyłączone na poziomie ścieżki lub punktu końcowego. Przykłady takich punktów końcowych:
- Punkty końcowe, do których można uzyskać dostęp w ramach różnych witryn: jeśli Twoja aplikacja obsługuje punkty końcowe z włączoną funkcją
CORS
, musisz je wyraźnie wyłączyć z izolacji zasobów, aby zapewnić możliwość wysyłania żądań do tych punktów końcowych z różnych witryn. - Zasoby publiczne (np. obrazy, style itp.): Wyjątek można też zastosować do wszystkich publicznych zasobów bez uwierzytelniania, które powinny być ładowalne z innych witryn.
if req.path in ('/my_CORS_endpoint', '/favicon.png'):
return True
Krok 5. Odrzuć wszystkie inne żądania, które są żądaniami między witrynami, a nie żądaniami nawigacyjnymi
Inne żądania między witrynami zostaną odrzucone przez tę zasadę izolacji zasobów, co ochroni Twoją aplikację przed typowymi atakami między witrynami.
Przykład: poniższy kod pokazuje pełną implementację solidnej zasady izolacji zasobów na serwerze lub jako oprogramowania pośredniczącego, aby odrzucać potencjalnie złośliwe żądania zasobów w wielu witrynach, a jednocześnie zezwalać na proste żądania nawigacyjne:
# Reject cross-origin requests to protect from CSRF, XSSI, and other bugs
def allow_request(req):
# Allow requests from browsers which don't send Fetch Metadata
if not req['sec-fetch-site']:
return True
# Allow same-site and browser-initiated requests
if req['sec-fetch-site'] in ('same-origin', 'same-site', 'none'):
return True
# Allow simple top-level navigations except <object> and <embed>
if req['sec-fetch-mode'] == 'navigate' and req.method == 'GET'
and req['sec-fetch-dest'] not in ('object', 'embed'):
return True
# [OPTIONAL] Exempt paths/endpoints meant to be served cross-origin.
if req.path in ('/my_CORS_endpoint', '/favicon.png'):
return True
# Reject all other requests that are cross-site and not navigational
return False
Wdrażanie zasady izolacji zasobów
- Zainstaluj moduł, np. fragment kodu podany powyżej, aby rejestrować i monitorować działanie witryny oraz upewnić się, że ograniczenia nie wpływają na prawidłowy ruch.
- Usuń potencjalne naruszenia, wykluczając z nich legalne punkty końcowe w ramach wielu źródeł.
- egzekwowanie zasad przez odrzucanie żądań niezgodnych z zasadami.
Wykrywanie i usuwanie naruszeń zasad
Zalecamy przetestowanie zasad w taki sposób, aby nie powodowały efektów ubocznych, przez ich włączenie w trybie raportowania w kodzie po stronie serwera. Możesz też zastosować tę logikę w oprogramowaniu pośredniczącym lub w usługach odwrotnego serwera proxy, które rejestrują wszelkie naruszenia zasad, które mogą wystąpić po zastosowaniu zasad w ruchu produkcyjnym.
Z naszych doświadczeń z wdrażania zasad izolacji zasobów w Google wynika, że większość aplikacji jest domyślnie zgodna z tymi zasadami i rzadko wymaga wyłączenia punktów końcowych, aby umożliwić ruch między witrynami.
Egzekwowanie zasady izolacji zasobów
Gdy upewnisz się, że Twoje zasady nie wpływają na legalny ruch produkcyjny, możesz wdrożyć ograniczenia, które zagwarantują, że inne witryny nie będą mogły żądać Twoich zasobów, a także ochronią użytkowników przed atakami na wiele witryn.
Więcej informacji
- Specyfikacja nagłówków żądania do pobierania metadanych W3C
- Pobierz Playground metadanych
- Prezentacja na konferencji Google I/O: zabezpieczanie aplikacji internetowych za pomocą nowoczesnych funkcji platformy (prezentacja)