Обеспечение безопасности и конфиденциальности путем разделения кеша

В целом, кэширование может повысить производительность за счет хранения данных, благодаря чему будущие запросы тех же данных будут обслуживаться быстрее. Например, кэшированный сетевой ресурс может избежать обратного пути к серверу. Кэшированный результат вычислений может не указывать время на выполнение того же вычисления.

В Chrome механизм кэширования используется по-разному, и HTTP-кэш является одним из примеров.

Как сейчас работает HTTP-кеш Chrome

Начиная с версии 85, Chrome кэширует ресурсы, полученные из сети, используя соответствующие URL-адреса ресурсов в качестве ключа кэша. (Ключ кэша используется для идентификации кэшированного ресурса.)

Следующий пример иллюстрирует, как одно изображение кэшируется и обрабатывается в трех разных контекстах:

Ключ кэша: https://x.example/doge.png
Ключ кэша : { https://x.example/doge.png }

Пользователь посещает страницу ( https://a.example ), которая запрашивает изображение ( https://x.example/doge.png ). Изображение запрашивается из сети и кэшируется с использованием https://x.example/doge.png в качестве ключа.

Ключ кэша: https://x.example/doge.png
Ключ кэша : { https://x.example/doge.png }

Тот же пользователь посещает другую страницу ( https://b.example ), которая запрашивает то же изображение ( https://x.example/doge.png ). Браузер проверяет свой HTTP-кеш, чтобы узнать, кэширован ли уже этот ресурс, используя URL-адрес изображения в качестве ключа. Браузер находит совпадение в своем кэше и использует кэшированную версию ресурса.

Ключ кэша: https://x.example/doge.png
Ключ кэша : { https://x.example/doge.png }

Не имеет значения, загружено ли изображение из iframe. Если пользователь посещает другой веб-сайт ( https://c.example ) с помощью iframe ( https://d.example ) и iframe запрашивает то же изображение ( https://x.example/doge.png ), браузер по-прежнему может загрузить изображение из своего кэша, поскольку ключ кэша одинаков на всех страницах.

Этот механизм уже давно хорошо работает с точки зрения производительности. Однако время, необходимое веб-сайту для ответа на HTTP-запросы, может показать, что браузер обращался к тому же ресурсу в прошлом, что открывает браузер для атак на безопасность и конфиденциальность, таких как следующие:

  • Обнаружить, посетил ли пользователь определенный сайт . Злоумышленник может обнаружить историю просмотров пользователя, проверив, есть ли в кеше ресурс, который может быть специфичным для определенного сайта или группы сайтов.
  • Атака межсайтового поиска : злоумышленник может обнаружить, есть ли произвольная строка в результатах поиска пользователя, проверив, находится ли в кеше браузера изображение «нет результатов поиска», используемое конкретным веб-сайтом.
  • Межсайтовое отслеживание . Кэш можно использовать для хранения идентификаторов, подобных файлам cookie, в качестве механизма межсайтового отслеживания.

Чтобы снизить эти риски, Chrome разделит свой HTTP-кеш, начиная с Chrome 86.

Как разделение кеша повлияет на HTTP-кэш Chrome?

При разделении кэша кэшированные ресурсы будут иметь ключ с использованием нового «ключа сетевой изоляции» в дополнение к URL-адресу ресурса. Ключ сетевой изоляции состоит из сайта верхнего уровня и сайта текущего кадра.

Посмотрите еще раз на предыдущий пример, чтобы увидеть, как разделение кэша работает в разных контекстах:

Ключ кэша { https://a.example, https://a.example, https://x.example/doge.png}
Ключ кэша : { https://a.example , https://a.example , https://x.example/doge.png }

Пользователь посещает страницу ( https://a.example ), которая запрашивает изображение ( https://x.example/doge.png ). В этом случае изображение запрашивается из сети и кэшируется с использованием кортежа, состоящего из https://a.example (сайт верхнего уровня), https://a.example (сайт текущего кадра) и https://x.example/doge.png (URL-адрес ресурса) в качестве ключа. (Обратите внимание, что когда запрос ресурса поступает из фрейма верхнего уровня, сайт верхнего уровня и сайт текущего фрейма в ключе изоляции сети совпадают.)

Ключ кэша { https://a.example, https://a.example, https://x.example/doge.png}
Ключ кэша : { https://b.example , https://b.example , https://x.example/doge.png }

Тот же пользователь посещает другую страницу ( https://b.example ), которая запрашивает то же изображение ( https://x.example/doge.png ). Хотя в предыдущем примере было загружено то же самое изображение, поскольку ключ не соответствует, это не будет попаданием в кеш.

Изображение запрашивается из сети и кэшируется с использованием кортежа, состоящего из https://b.example , https://b.example и https://x.example/doge.png в качестве ключа.

Ключ кэша { https://a.example, https://a.example, https://x.example/doge.png}
Ключ кэша : { https://a.example , https://a.example , https://x.example/doge.png }

Теперь пользователь возвращается к https://a.example , но на этот раз изображение ( https://x.example/doge.png ) встроено в iframe. В этом случае ключ представляет собой кортеж, содержащий https://a.example , https://a.example и https://x.example/doge.png , и происходит попадание в кеш. (Обратите внимание: если сайт верхнего уровня и iframe являются одним и тем же сайтом, можно использовать ресурс, кэшированный вместе с фреймом верхнего уровня.

Ключ кэша { https://a.example, https://a.example, https://x.example/doge.png}
Ключ кэша : { https://a.example , https://c.example , https://x.example/doge.png }

Пользователь вернулся на https://a.example , но на этот раз изображение размещается в iframe из https://c.example .

В этом случае изображение загружается из сети, поскольку в кеше нет ресурса, соответствующего ключу, состоящему из https://a.example , https://c.example и https://x.example/doge.png .

Ключ кэша { https://a.example, https://a.example, https://x.example/doge.png}
Ключ кэша : { https://a.example , https://c.example , https://x.example/doge.png }

Что делать, если домен содержит субдомен или номер порта? Пользователь посещает https://subdomain.a.example , где встраивается iframe ( https://c.example:8080 ), который запрашивает изображение.

Поскольку ключ создается на основе схемы://eTLD+1, субдомены и номера портов игнорируются. Следовательно, происходит попадание в кэш.

Ключ кэша { https://a.example, https://a.example, https://x.example/doge.png}
Ключ кэша : { https://a.example , https://c.example , https://x.example/doge.png }

Что делать, если iframe вложен несколько раз? Пользователь посещает https://a.example , который встраивает iframe ( https://b.example ), который встраивает еще один iframe ( https://c.example ), который, наконец, запрашивает изображение.

Поскольку ключ берется из верхнего кадра ( https://a.example ) и непосредственного кадра, который загружает ресурс ( https://c.example ), происходит попадание в кеш.

Часто задаваемые вопросы

Это уже включено в моем Chrome? Как я могу проверить?

Эта функция будет реализована до конца 2020 года. Чтобы проверить, поддерживает ли ее уже ваш экземпляр Chrome:

  1. Откройте chrome://net-export/ и нажмите «Начать запись на диск ».
  2. Укажите, где сохранить файл журнала на вашем компьютере.
  3. Просмотрите веб-страницы в Chrome в течение минуты.
  4. Вернитесь на chrome://net-export/ и нажмите «Остановить регистрацию» .
  5. Перейдите на https://netlog-viewer.appspot.com/#import .
  6. Нажмите «Выбрать файл» и передайте сохраненный файл журнала.

Вы увидите вывод файла журнала.

На той же странице найдите SplitCacheByNetworkIsolationKey . Если за ним следует Experiment_[****] , в вашем Chrome включено разделение HTTP-кеша. Если за ним следует Control_[****] или Default_[****] , он не включен.

Как я могу проверить разделение HTTP-кеша в Chrome?

Чтобы протестировать разделение HTTP-кеша в Chrome, вам необходимо запустить Chrome с флагом командной строки: --enable-features=SplitCacheByNetworkIsolationKey . Следуйте инструкциям в разделе «Запуск Chromium с флагами» , чтобы узнать, как запустить Chrome с флагом командной строки на вашей платформе.

Как веб-разработчик, должен ли я предпринять какие-либо действия в ответ на это изменение?

Это не критическое изменение, но оно может повлиять на производительность некоторых веб-сервисов.

Например, те, кто обслуживает большие объемы ресурсов с высокой степенью кэширования на многих сайтах (например, шрифты и популярные скрипты), могут заметить увеличение своего трафика. Кроме того, те, кто пользуется такими услугами, могут в большей степени полагаться на них.

(Есть предложение включить общие библиотеки с сохранением конфиденциальности под названием «Общие веб-библиотеки» ( презентационное видео ), но оно все еще находится на рассмотрении.)

Каково влияние этого изменения поведения?

Общий процент промахов в кэше увеличивается примерно на 3,6%, изменения в FCP (First Contentful Paint) скромны (~0,3%), а общая доля байтов, загружаемых из сети, увеличивается примерно на 4%. Подробнее о влиянии на производительность можно узнать в пояснении по разбиению кэша HTTP .

Это стандартизировано? Другие браузеры ведут себя по-другому?

«Разделы кэша HTTP» стандартизированы в спецификации выборки , хотя браузеры ведут себя по-разному:

  • Chrome : использует схему верхнего уровня://eTLD+1 и схему фрейма://eTLD+1.
  • Safari : использует eTLD верхнего уровня+1.
  • Firefox : планируется реализовать схему верхнего уровня://eTLD+1 и рассмотреть возможность включения второго ключа, например Chrome.

Как обрабатывается выборка от рабочих?

Выделенные работники используют тот же ключ, что и их текущий фрейм. Сервисные работники и общие работники более сложны, поскольку они могут совместно использоваться несколькими сайтами верхнего уровня. Решение для них сейчас обсуждается.

Ресурсы