Uzyskiwanie bezpieczeństwa i prywatności przez partycjonowanie pamięci podręcznej

Eiji Kitamura
Eiji Kitamura

Ogólnie rzecz biorąc, zapisywanie w pamięci podręcznej może poprawić wydajność, ponieważ umożliwia szybsze przedstawianie przyszłych żądań tych samych danych. Na przykład zasób przechowywany w pamięci podręcznej z sieci pozwala uniknąć komunikacji z serwerem w obie strony. W przypadku wyniku obliczeniowego zapisanego w pamięci podręcznej można z pominięciem czasu wykonywać te same obliczenia.

W Chrome mechanizm pamięci podręcznej jest używany na różne sposoby, a przykładem jest pamięć podręczna HTTP.

Jak obecnie działa pamięć podręczna HTTP Chrome

Od wersji 85 Chrome zapisuje w pamięci podręcznej zasoby pobrane z sieci, używając ich adresów URL jako klucza pamięci podręcznej. (Klucz pamięci podręcznej służy do identyfikowania zasobów w pamięci podręcznej).

Poniższy przykład pokazuje, jak pojedynczy obraz jest zapisywany w pamięci podręcznej i traktowany w 3 różnych kontekstach:

Klucz pamięci podręcznej: https://x.example/doge.png
Klucz pamięci podręcznej: { https://x.example/doge.png}

Użytkownik odwiedza stronę (https://a.example), która żąda obrazu (https://x.example/doge.png). Obraz jest pobierany z sieci i zapisywany w pamięci podręcznej z użyciem klucza https://x.example/doge.png.

Klucz pamięci podręcznej: https://x.example/doge.png
Klucz pamięci podręcznej: { https://x.example/doge.png}

Ten sam użytkownik odwiedza inną stronę (https://b.example), która żąda tego samego obrazu (https://x.example/doge.png). Przeglądarka sprawdza swoją pamięć podręczną HTTP, aby sprawdzić, czy ten zasób jest już w pamięci podręcznej. Adres URL obrazu to klucz. Przeglądarka znajduje dopasowanie w pamięci podręcznej, więc korzysta z wersji zasobu przechowywanej w pamięci podręcznej.

Klucz pamięci podręcznej: https://x.example/doge.png
Klucz pamięci podręcznej: { https://x.example/doge.png}

Nie ma znaczenia, czy obraz jest ładowany w elemencie iframe. Jeśli użytkownik odwiedzi inną witrynę (https://c.example) z elementem iframe (https://d.example), a element iframe poprosi o ten sam obraz (https://x.example/doge.png), przeglądarka może nadal wczytać obraz z pamięci podręcznej, ponieważ na wszystkich stronach jest taki sam klucz pamięci podręcznej.

Ten mechanizm już od dawna sprawdza się w kontekście wydajności. Jednak czas potrzebny na udzielenie odpowiedzi na żądania HTTP może ujawnić, że przeglądarka miała dostęp do tego samego zasobu w przeszłości, przez co przeglądarka jest narażona na ataki zabezpieczeń i prywatności, takie jak:

  • Wykrywa, czy użytkownik odwiedził określoną witrynę: przeciwnik może wykryć historię przeglądania użytkownika, sprawdzając, czy w pamięci podręcznej znajduje się zasób, który może być związany z konkretną witryną lub kohortą witryn.
  • Atak w wielu witrynach: przeciwnik może wykryć, czy w wynikach wyszukiwania użytkownika znajduje się dowolny ciąg znaków, sprawdzając, czy w pamięci podręcznej przeglądarki znajduje się obraz „brak wyników wyszukiwania” używany przez konkretną witrynę.
  • Śledzenie w witrynach: w pamięci podręcznej można przechowywać identyfikatory podobne do plików cookie na potrzeby śledzenia w wielu witrynach.

Aby ograniczyć to ryzyko, od wersji Chrome 86 Chrome będzie partycjonować pamięć podręczną HTTP.

Jak partycjonowanie pamięci podręcznej wpływa na pamięć podręczną HTTP w Chrome?

W przypadku partycjonowania pamięci podręcznej zasoby z pamięci podręcznej będą poddawane kluczowi przy użyciu nowego „klucza izolacji sieci” oprócz adresu URL zasobu. Klucz izolacji sieci składa się z witryny najwyższego poziomu i witryny z bieżącą ramką.

Spójrz na poprzedni przykład, aby zobaczyć, jak partycjonowanie pamięci podręcznej działa w różnych kontekstach:

Klucz pamięci podręcznej { https://a.example, https://a.example, https://x.example/doge.png}
Klucz pamięci podręcznej: { https://a.example, https://a.example, https://x.example/doge.png }

Użytkownik odwiedza stronę (https://a.example), która wysyła żądanie obrazu (https://x.example/doge.png). W takim przypadku żądanie obrazu jest wysyłane do sieci i przechowywane w pamięci podręcznej za pomocą krotki złożonej z https://a.example (witryna najwyższego poziomu), https://a.example (witryna z bieżącą ramką) i https://x.example/doge.png (adresu URL zasobu) jako klucza. (pamiętaj, że jeśli żądanie zasobu pochodzi z ramki najwyższego poziomu, witryna najwyższego poziomu i witryna z bieżącą ramką w kluczu izolacji sieci są takie same).

Klucz pamięci podręcznej { https://a.example, https://a.example, https://x.example/doge.png}
Klucz pamięci podręcznej: { https://b.example, https://b.example, https://x.example/doge.png }

Ten sam użytkownik odwiedza inną stronę (https://b.example), która prosi o ten sam obraz (https://x.example/doge.png). Mimo że w poprzednim przykładzie załadowano ten sam obraz (niepasujący klucz), nie trafi on do pamięci podręcznej.

Obraz jest wysyłany do sieci i zapisywany w pamięci podręcznej przy użyciu krotki złożonej z klucza https://b.example, https://b.example i https://x.example/doge.png.

Klucz pamięci podręcznej { https://a.example, https://a.example, https://x.example/doge.png}
Klucz pamięci podręcznej: { https://a.example, https://a.example, https://x.example/doge.png }

Użytkownik wraca teraz do elementu https://a.example, ale tym razem obraz (https://x.example/doge.png) jest umieszczony w elemencie iframe. W tym przypadku kluczem jest krotka zawierająca https://a.example, https://a.example i https://x.example/doge.png oraz występuje trafienie w pamięci podręcznej. Pamiętaj, że jeśli witryna najwyższego poziomu i element iframe są tą samą witryną, można użyć zasobu zapisanego w pamięci podręcznej z ramką najwyższego poziomu.

Klucz pamięci podręcznej { https://a.example, https://a.example, https://x.example/doge.png}
Klucz pamięci podręcznej: { https://a.example, https://c.example, https://x.example/doge.png}

Użytkownik wrócił do https://a.example, ale tym razem obraz jest hostowany w elemencie iframe z https://c.example.

W tym przypadku obraz jest pobierany z sieci, ponieważ w pamięci podręcznej nie ma zasobu pasującego do klucza https://a.example, https://c.example i https://x.example/doge.png.

Klucz pamięci podręcznej { https://a.example, https://a.example, https://x.example/doge.png}
Klucz pamięci podręcznej: { https://a.example, https://c.example, https://x.example/doge.png}

Co zrobić, jeśli domena zawiera subdomenę lub numer portu? Użytkownik otwiera stronę https://subdomain.a.example, która zawiera element iframe (https://c.example:8080) wysyłający żądanie obrazu.

Klucz jest tworzony na podstawie schematu „schemat://eTLD+1”, więc subdomeny i numery portów są ignorowane. Z tego powodu występuje trafienie w pamięci podręcznej.

Klucz pamięci podręcznej { https://a.example, https://a.example, https://x.example/doge.png}
Klucz pamięci podręcznej: { https://a.example, https://c.example, https://x.example/doge.png}

Co się stanie, jeśli element iframe jest zagnieżdżony wiele razy? Użytkownik otwiera stronę https://a.example, która zawiera element iframe (https://b.example) oraz kolejny element iframe (https://c.example), który w końcu wysyła żądanie obrazu.

Ponieważ klucz jest pobierany z ramki górnej (https://a.example) i bezpośredniej klatki, która wczytuje zasób (https://c.example), występuje trafienie w pamięci podręcznej.

Najczęstsze pytania

Czy ta funkcja jest już włączona w mojej przeglądarce Chrome? Jak sprawdzić?

Ta funkcja będzie wdrażana pod koniec 2020 roku. Aby sprawdzić, czy Twoja instancja Chrome już ją obsługuje:

  1. Otwórz chrome://net-export/ i naciśnij Start Logging to Disk (Rozpocznij rejestrowanie na dysku).
  2. Określ miejsce zapisania pliku dziennika na komputerze.
  3. Przez minutę przejrzyj internet w Chrome.
  4. Wróć do zadania chrome://net-export/ i naciśnij Stop Logging (Zatrzymaj rejestrowanie).
  5. Otwórz: https://netlog-viewer.appspot.com/#import.
  6. Kliknij Choose File (Wybierz plik) i prześlij zapisany plik dziennika.

Zobaczysz dane wyjściowe pliku dziennika.

Na tej samej stronie znajdź SplitCacheByNetworkIsolationKey. Jeśli po nim występuje Experiment_[****], w Chrome włączone jest partycjonowanie pamięci podręcznej HTTP. Jeśli po nim występuje Control_[****] lub Default_[****], nie jest włączona.

Jak mogę przetestować partycjonowanie pamięci podręcznej HTTP w przeglądarce Chrome?

Aby przetestować partycjonowanie pamięci podręcznej HTTP w Chrome, musisz uruchomić Chrome z flagą wiersza polecenia: --enable-features=SplitCacheByNetworkIsolationKey. Wykonaj instrukcje podane w artykule Uruchamianie Chromium z flagami, aby dowiedzieć się, jak uruchomić Chrome przy użyciu flagi wiersza poleceń na platformie.

Czy jako programista stron internetowych mam coś zrobić w związku z tą zmianą?

Nie jest to przełomowa zmiana, ale może wpływać na wydajność niektórych usług internetowych.

Na przykład witryny udostępniające duże ilości zasobów łatwo dostępnych w pamięci podręcznej (takich jak czcionki i popularne skrypty) w wielu witrynach mogą zauważyć wzrost natężenia ruchu. Ponadto osoby korzystające z takich usług mogą w większym stopniu polegać na nich.

Istnieje propozycja włączenia bibliotek udostępnionych w sposób zapewniający ochronę prywatności – biblioteki udostępnione w internecie (film do prezentacji), ale wciąż nad tym rozważamy.

Jaki jest wpływ tej zmiany w zachowaniu?

Ogólny współczynnik niepowodzeń w pamięci podręcznej wzrasta o około 3,6%, zmiany w FCP (pierwsze wyrenderowanie treści) są niewielkie (około 0,3%), a ogólny odsetek bajtów załadowanych z sieci zwiększa się o około 4%. Więcej informacji o wpływie na wydajność znajdziesz w wyjaśnieniu partycjonowania pamięci podręcznej HTTP.

Czy to jest ustandaryzowane? Czy inne przeglądarki działają inaczej?

„partycje pamięci podręcznej HTTP” są standaryzowane w specyfikacji pobierania, chociaż przeglądarki działają inaczej:

Jak są traktowane pobieranie od instancji roboczych?

Dedykowane instancje robocze używają tego samego klucza co ich bieżąca ramka. Skrypty service worker i instancje robocze są bardziej skomplikowane, ponieważ mogą być współdzielone przez wiele witryn najwyższego poziomu. Obecnie trwają prace nad ich rozwiązaniem.

Zasoby