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

Ogólnie rzecz biorąc, buforowanie może zwiększyć wydajność, przechowując dane, dzięki czemu przyszłe żądania tych samych danych będą szybciej obsługiwane. Na przykład zasób z pamięci podręcznej sieci może uniknąć przesyłania danych w obie strony do serwera. Wynik obliczeń w pamięci podręcznej może nie zawierać czasu na wykonywanie tych samych obliczeń.

W Chrome mechanizm pamięci podręcznej jest wykorzystywany na różne sposoby, a jednym z nich jest pamięć podręczna HTTP.

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

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

Poniższy przykład pokazuje, jak pojedynczy obraz jest przechowywany 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 wysyła żądanie wyświetlenia obrazu (https://x.example/doge.png). Obraz jest wysyłany z sieci i zapisywany w pamięci podręcznej z wykorzystaniem https://x.example/doge.png jako klucza.

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 wysyła żądanie tego samego obrazu (https://x.example/doge.png). Przeglądarka sprawdza swoją pamięć podręczną HTTP, używając jako klucza adresu URL obrazu. Przeglądarka znajduje dopasowanie w swojej pamięci podręcznej, więc używa wersji zasobu z 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 wczytywany z elementu iframe. Jeśli użytkownik odwiedzi inną witrynę (https://c.example) korzystającą z elementu iframe (https://d.example), a element iframe zażąda tego samego obrazu (https://x.example/doge.png), przeglądarka może wciąż wczytać obraz z pamięci podręcznej, ponieważ klucz pamięci podręcznej jest taki sam na wszystkich stronach.

Mechanizm ten od dawna sprawdza się z perspektywy wydajności. Czas potrzebny witrynie na reakcję na żądania HTTP może jednak ujawnić, że przeglądarka korzystała wcześniej z tego samego zasobu, co powoduje jej ataki z powodu zabezpieczeń i ochrony prywatności, takie jak:

  • Wykrywanie, czy użytkownik odwiedził określoną witrynę: przeciwnik może wykryć historię przeglądania użytkownika, sprawdzając, czy pamięć podręczna zawiera zasób, który może być specyficzny dla konkretnej witryny lub kohorty witryn.
  • Atak na wyszukiwanie w wielu witrynach: przeciwnik może wykryć, czy dowolny ciąg znaków znajduje się w wynikach wyszukiwania użytkownika, sprawdzając, czy obraz „brak wyników wyszukiwania” używany przez konkretną witrynę znajduje się w pamięci podręcznej przeglądarki.
  • Śledzenie w witrynach: pamięć podręczna może służyć do przechowywania identyfikatorów podobnych do plików cookie jako mechanizmu śledzenia w witrynach.

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

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

Gdy partycjonowanie pamięci podręcznej polega na stosowaniu klucza dostępu do zasobów zapisanych w pamięci podręcznej, oprócz adresu URL zasobu będzie używany nowy „klucz izolacji sieci”. Klucz izolacji sieci składa się z witryny najwyższego poziomu i witryny z bieżącą ramką.

Ponownie 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 prosi o obraz (https://x.example/doge.png). W tym przypadku żądanie grafiki (https://x.example/doge.png) jest pobierane z sieci i zapisywane w pamięci podręcznej za pomocą krotki złożonej z klucza https://a.example (witryna najwyższego poziomu), https://a.example (witryna z bieżącą ramką) i https://x.example/doge.png (adres URL zasobu). Pamiętaj, że gdy żądanie zasobu pochodzi z klatki 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 wczytano ten sam obraz, niepasujący klucz nie spowoduje trafienia w pamięci podręcznej.

Żądanie obrazu jest pobierane z sieci i zapisywane w pamięci podręcznej za pomocą 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 }

Teraz użytkownik wraca do 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, a następnie występuje trafienie w pamięci podręcznej. (Pamiętaj, że gdy witryna najwyższego poziomu i element iframe znajdują się w tej samej witrynie, może zostać użyty zasób z 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 jest z powrotem pod adresem 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 składającego się z 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 się stanie, jeśli domena zawiera subdomenę lub numer portu? Użytkownik odwiedza 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://eTLD+1”, dlatego subdomeny i numery portów są ignorowane. W efekcie dochodzi do trafienia 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 zrobić, jeśli element iframe jest zagnieżdżony wiele razy? Użytkownik odwiedza stronę https://a.example, na której umieszcza się element iframe (https://b.example), który umieszcza jeszcze jeden element iframe (https://c.example), który w końcu wysyła żądanie obrazu.

Ponieważ klucz jest pobierany z klatki najwyższego poziomu (https://a.example) i natychmiastowej ramki, która wczytuje zasób (https://c.example), występuje trafienie w pamięci podręcznej.

Najczęstsze pytania

Czy jest już włączony w mojej przeglądarce Chrome? Jak mogę to sprawdzić?

Ta funkcja jest wdrażana do końca 2020 roku. Aby sprawdzić, czy Twoja instancja Chrome już ją obsługuje:

  1. Otwórz plik chrome://net-export/ i kliknij Start Logging to Disk (Rozpocznij rejestrowanie na dysku).
  2. Określ, gdzie na komputerze zapisać plik dziennika.
  3. Przejrzyj internet w Chrome przez minutę.
  4. Wróć do funkcji chrome://net-export/ i naciśnij Zatrzymaj rejestrowanie.
  5. Jedź do: 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 znajduje się po niej znak Experiment_[****], partycjonowanie pamięci podręcznej HTTP jest włączone w Chrome. Jeśli po nim znajduje się ciąg Control_[****] lub Default_[****], funkcja nie jest włączona.

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

Aby przetestować partycjonowanie pamięci podręcznej HTTP w Chrome, musisz uruchomić Chrome z flagą --enable-features=SplitCacheByNetworkIsolationKey w wierszu poleceń. Postępuj zgodnie z instrukcjami w artykule Uruchamianie Chromium z flagami, by dowiedzieć się, jak uruchomić Chrome za pomocą flagi wiersza poleceń na swojej platformie.

Czy jako programista stron internetowych muszę podjąć jakieś działania w związku z tą zmianą?

Nie jest to niekorzystna zmiana, ale może mieć wpływ na wydajność niektórych usług internetowych.

Na przykład witryny, które obsługują duże ilości zasobów z dużą ilością pamięci podręcznej (takich jak czcionki i popularne skrypty) z dużą ilością zasobów zapisanych w pamięci podręcznej, mogą zauważyć wzrost natężenia ruchu. Poza tym osoby korzystające z takich usług mogą w większym stopniu polegać na nich.

(Udostępniamy biblioteki udostępnione w sposób zapewniający ochronę prywatności, tzw. biblioteki współużytkowane w internecie (prezentacja wideo), ale wciąż ją rozważamy).

Jaki jest wpływ tej zmiany w działaniu?

Ogólny współczynnik błędów w pamięci podręcznej rośnie o około 3,6%, zmiany FCP (pierwsze wyrenderowanie treści) są niewielkie (ok. 0,3%), a ogólny odsetek bajtów wczytanych 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 ustandaryzowane? Czy inne przeglądarki zachowują się inaczej?

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

  • Chrome: używa schematu obrazu najwyższego poziomu://eTLD+1 i frameschema://eTLD+1
  • Safari: używa eTLD + 1 najwyższego poziomu
  • Firefox: planowanie wdrożenia za pomocą schematu najwyższego poziomu://eTLD+1 i rozważenie dodania drugiego klucza, np. Chrome

Jak jest traktowane pobieranie od instancji roboczych?

Dedykowane instancje robocze używają tego samego klucza co ich bieżąca ramka. Skrypty service worker i współdzielone instancje robocze są bardziej skomplikowane, ponieważ mogą być współdzielone przez wiele witryn najwyższego poziomu. Rozwiązanie tego problemu jest obecnie w trakcie dyskusji.

Zasoby