Dlaczego zaawansowane funkcje są potrzebne do obsługi zasobów z innych domen

Dowiedz się, dlaczego witryna izolowana od zasobów z innych domen jest potrzebna do korzystania z zaawansowanych funkcji, takich jak SharedArrayBuffer, performance.measureUserAgentSpecificMemory() i timer o wysokiej rozdzielczości z większą precyzją.

Wprowadzenie

W artykule Jak sprawić, aby witryna była „odizolowana od innych domen” za pomocą COOP i COEP wyjaśniliśmy, jak przejść do stanu „odizolowania od innych domen” za pomocą COOP i COEP. To artykuł uzupełniający, który wyjaśnia, dlaczego izolacja od zasobów z innych domen jest wymagana, aby włączyć w przeglądarce zaawansowane funkcje.

Tło

Internet opiera się na zasadzie tego samego pochodzenia, czyli funkcji zabezpieczeń, która ogranicza sposób, w jaki dokumenty i skrypty mogą wchodzić w interakcje z zasobami z innego źródła. Ta zasada ogranicza sposoby, w jakie witryny mogą uzyskiwać dostęp do zasobów z innych domen. Na przykład dokument z domeny https://a.example nie może uzyskać dostępu do danych hostowanych w domenie https://b.example.

Zasada dotycząca tej samej domeny miała jednak w przeszłości pewne wyjątki. Każda witryna może:

  • Umieszczanie elementów iframe z różnych domen
  • zawierać zasoby z innych domen, takie jak obrazy lub skrypty;
  • Otwieranie wyskakujących okienek z innej domeny za pomocą odwołania DOM

Gdyby sieć można było zaprojektować od zera, te wyjątki nie istniałyby. Niestety, gdy społeczność internetowa zdała sobie sprawę z kluczowych zalet ścisłej polityki tego samego pochodzenia, internet już korzystał z tych wyjątków.

Skutki uboczne tak liberalnej zasady takiego samego pochodzenia zostały usunięte na 2 sposoby. Jednym ze sposobów było wprowadzenie nowego protokołu o nazwie Cross-Origin Resource Sharing (CORS), którego celem jest zapewnienie, że serwer zezwala na udostępnianie zasobu danemu źródłu. Drugi sposób polega na niejawnym usunięciu bezpośredniego dostępu skryptu do zasobów z innych domen przy zachowaniu zgodności wstecznej. Takie zasoby z innych domen są nazywane zasobami „nieprzezroczystymi”. Dlatego na przykład manipulowanie pikselami obrazu z innej domeny za pomocą elementu CanvasRenderingContext2D nie działa, chyba że do obrazu zastosowano CORS.

Wszystkie te decyzje dotyczące zasad są podejmowane w ramach grupy kontekstu przeglądania.

Grupa kontekstów przeglądania

Przez długi czas połączenie CORS i nieprzezroczystych zasobów wystarczało, aby zapewnić bezpieczeństwo przeglądarek. Czasami wykrywano przypadki brzegowe (np. luki w zabezpieczeniach JSON), które wymagały załatania, ale ogólnie zasada niedozwalania na bezpośredni dostęp do odczytu surowych bajtów zasobów z innych domen okazała się skuteczna.

Wszystko zmieniło się wraz z pojawieniem się Spectre, które sprawia, że wszystkie dane wczytywane do tej samej grupy kontekstu przeglądania co Twój kod mogą być potencjalnie czytelne. Mierząc czas wykonywania określonych operacji, atakujący mogą odgadnąć zawartość pamięci podręcznej procesora, a tym samym zawartość pamięci procesu. Takie ataki czasowe są możliwe w przypadku timerów o niskiej ziarnistości, które są dostępne na platformie, ale można je przyspieszyć za pomocą timerów o wysokiej ziarnistości, zarówno jawnych (np. performance.now()), jak i niejawnych (np. SharedArrayBuffer). Jeśli evil.com osadzi obraz z innej domeny, może użyć ataku Spectre, aby odczytać dane pikseli, co sprawia, że ochrona oparta na „nieprzezroczystości” jest nieskuteczna.

Spectr

W idealnej sytuacji wszystkie żądania pochodzące z innych domen powinny być wyraźnie sprawdzane przez serwer, który jest właścicielem zasobu. Jeśli weryfikacja nie jest przeprowadzana przez serwer będący właścicielem zasobu, dane nigdy nie trafią do grupy kontekstu przeglądania złośliwego podmiotu, a tym samym pozostaną poza zasięgiem ataków Spectre, które może przeprowadzić strona internetowa. Nazywamy to stanem izolowanym od zasobów z innych domen. Na tym właśnie polega COOP+COEP.

W stanie izolacji między źródłami witryna wysyłająca żądanie jest uważana za mniej niebezpieczną, co odblokowuje zaawansowane funkcje, takie jak SharedArrayBuffer, performance.measureUserAgentSpecificMemory()timery o wysokiej rozdzielczości o większej precyzji, które w innych okolicznościach mogłyby zostać wykorzystane do ataków podobnych do Spectre. Zapobiega też modyfikowaniu document.domain.

Zasady umieszczania zasobów z innych domen

Zasady dotyczące osadzania z innej domeny (COEP) uniemożliwiają dokumentowi wczytywanie zasobów z innych domen, które nie przyznają mu wyraźnie uprawnień (za pomocą CORP lub CORS). Dzięki tej funkcji możesz zadeklarować, że dokument nie może wczytywać takich zasobów.

Jak działa COEP

Aby aktywować te zasady, dodaj do dokumentu ten nagłówek HTTP:

Cross-Origin-Embedder-Policy: require-corp

COEP przyjmuje jedną wartość require-corp. Wymusza to zasadę, że dokument może wczytywać zasoby tylko z tego samego źródła lub zasoby wyraźnie oznaczone jako wczytywane z innego źródła.

Aby zasoby można było wczytywać z innego źródła, muszą one obsługiwać współdzielenie zasobów pomiędzy serwerami z różnych domen (CORS) lub zasadę dotyczącą zasobów z innych witryn (CORP).

Mechanizm CORS

Jeśli zasób z innej domeny obsługuje współdzielenie zasobów pomiędzy serwerami z różnych domen (CORS), możesz użyć crossoriginatrybutu, aby załadować go na stronę internetową bez blokowania przez COEP.

<img src="https://third-party.example.com/image.jpg" crossorigin>

Jeśli na przykład ten zasób obrazu jest wyświetlany z nagłówkami CORS, użyj atrybutu crossorigin, aby żądanie pobrania zasobu korzystało z trybu CORS. Zapobiega to też wczytywaniu obrazu, chyba że ustawia on nagłówki CORS.

Podobnie możesz pobierać dane z innych domen za pomocą metody fetch(), która nie wymaga specjalnej obsługi, o ile serwer odpowiada z odpowiednimi nagłówkami HTTP.

Zasady dotyczące zasobów z innych domen

Zasady dotyczące zasobów z innych domen (CORP) zostały pierwotnie wprowadzone jako opcja, która chroni zasoby przed wczytywaniem przez inne domeny. W kontekście COEP zasada CORP może określać zasady właściciela zasobu dotyczące tego, kto może go wczytać.

Nagłówek Cross-Origin-Resource-Policy może mieć 3 wartości:

Cross-Origin-Resource-Policy: same-site

Zasoby oznaczone symbolem same-site można wczytywać tylko z tej samej witryny.

Cross-Origin-Resource-Policy: same-origin

Zasoby oznaczone symbolem same-origin można wczytywać tylko z tego samego źródła.

Cross-Origin-Resource-Policy: cross-origin

Zasoby oznaczone symbolem cross-origin mogą być wczytywane przez dowolną witrynę. (Ta wartość została dodana do specyfikacji CORP wraz z COEP).

Zasada dotycząca otwierającego z innej domeny

Zasady dotyczące otwierającego z innej domeny (COOP) pozwalają odizolować okno najwyższego poziomu od innych dokumentów, umieszczając je w innej grupie kontekstu przeglądania, dzięki czemu nie mogą one bezpośrednio wchodzić w interakcje z oknem najwyższego poziomu. Jeśli na przykład dokument z COOP otworzy wyskakujące okienko, jego właściwość window.opener będzie miała wartość null. Właściwość .closed odwołania do niej z okna otwierającego zwróci wartość true.

COOP

Nagłówek Cross-Origin-Opener-Policy może mieć 3 wartości:

Cross-Origin-Opener-Policy: same-origin

Dokumenty oznaczone symbolem same-origin mogą współdzielić grupę kontekstu przeglądania z dokumentami pochodzącymi z tej samej domeny, które również są wyraźnie oznaczone symbolem same-origin.

COOP

Cross-Origin-Opener-Policy: same-origin-allow-popups

Dokument najwyższego poziomu z wartością same-origin-allow-popups zachowuje odniesienia do wszystkich wyskakujących okienek, które nie mają ustawionych zasad COOP lub które rezygnują z izolacji, ustawiając zasady COOP na unsafe-none.

COOP

Cross-Origin-Opener-Policy: unsafe-none

unsafe-none to wartość domyślna, która umożliwia dodanie dokumentu do grupy kontekstów przeglądania otwierającego, chyba że sam otwierający ma COOP ustawiony na same-origin.

Podsumowanie

Jeśli chcesz mieć gwarancję dostępu do zaawansowanych funkcji, takich jak SharedArrayBuffer, performance.measureUserAgentSpecificMemory() czy timery o wysokiej rozdzielczości z większą precyzją, pamiętaj, że dokument musi używać zarówno COEP z wartością require-corp, jak i COOP z wartością same-origin. W przeciwnym razie przeglądarka nie będzie w stanie zagwarantować wystarczającej izolacji, aby bezpiecznie włączyć te zaawansowane funkcje. Sytuację strony możesz określić, sprawdzając, czy self.crossOriginIsolated zwraca true.

Więcej informacji o wdrażaniu tego rozwiązania znajdziesz w artykule Ustawianie witryny jako „odizolowanej od innych domen” za pomocą nagłówków COOP i COEP.

Zasoby