Hero Image

Объяснение SameSiteатрибута файлов cookie

Объяснение SameSiteатрибута файлов cookie

Защитите свой сайт, узнав, как явно отмечать межсайтовые файлы cookie.

Обновлено
Appears in: Безопасность и надежность

Эта статья относится к циклу статей об изменениях в атрибуте SameSite файлов cookie:

Файлы cookieэто один из доступных методов добавления постоянного состояния веб-сайтам. С годами возможности cookie росли и развивались, но платформа сохранила часть прежних проблем. Для их решения браузеры (в том числе Chrome, Firefox и Edge) меняют свое поведение, чтобы обеспечить больше устанавливаемых по умолчанию параметров, сохраняющих конфиденциальность.

Каждый файл cookie представляет собой пару key=value, дополненную рядом атрибутов, которые определяют, когда и где используется этот файл cookie. Вероятно, вы уже использовали эти атрибуты, чтобы установить дату истечения срока действия или указать, что файл cookie должен отправляться только по HTTPS. Серверы устанавливают файлы cookie, отправляя в своем ответе заголовок Set-Cookie. Чтобы узнать обо всех подробностях, вы можете погрузиться в RFC6265bis, а пока что краткое напоминание.

Допустим, у вас есть блог, в котором вы хотите показывать своим пользователям рекламу «Что нового». Пользователи могут закрыть рекламу, и не будут видеть ее в течение некоторого времени. Вы можете сохранить это предпочтение в файле cookie, установить для него срок действия в месяц (2600000 секунд) и отправлять  файл cooki ​только по HTTPS. Этот заголовок будет выглядеть так:

Set-Cookie: promo_shown=1; Max-Age=2600000; Secure
Три файла cookie отправляются в браузер с сервера в ответе
Серверы устанавливают файлы cookie с помощью заголовка Set-Cookie.

Когда ваш читатель просматривает страницу, которая соответствует этим требованиям, то есть просматривается в безопасном соединении, а возраст cookie не превышает одного месяца, браузер пользователя отправит этот заголовок в своем запросе:

Cookie: promo_shown=1
Три файла cookie отправляются из браузера на сервер в запросе
Браузер отправляет файл cookie обратно в заголовке Cookie.

Вы также можете добавлять и читать файлы cookie, доступные для этого сайта, в JavaScript, используя document.cookie. Запись в document.cookie приведет к созданию или переопределению файла cookie с этим ключом. Например, в консоли JavaScript браузера можно попробовать выполнить следующее:

> document.cookie = "promo_shown=1; Max-Age=2600000; Secure"
< "promo_shown=1; Max-Age=2600000; Secure"

При чтении document.cookie будут выведены все файлы cookie, доступные в текущем контексте, причем каждый файл cookie разделен точкой с запятой:

> document.cookie;
< "promo_shown=1; color_theme=peachpuff; sidebar_loc=left"
Доступ к файлам cookie в браузере через JavaScript
JavaScript может получить доступ к файлам cookie с помощью document.cookie.

Если вы попробуете сделать это на нескольких популярных сайтах, вы заметите, что большинство из них устанавливают значительно больше трех файлов cookie. В большинстве случаев эти файлы cookie отправляются при каждом запросе к этому домену, что имеет ряд последствий. Пропускная способность каналов загрузки часто более ограничена, чем каналов скачивания для ваших пользователей, поэтому накладные расходы на все исходящие запросы добавляют задержку к времени до первого байта. Будьте осторожны в выборе количества и размера файлов cookie, которые вы устанавливаете. Используйте атрибут Max-Age, чтобы гарантировать, что файлы cookie не будут храниться дольше необходимого.

Если вы вернетесь к предыдущей подборке сайтов, то, вероятно, заметите, что присутствуют файлы cookie для различных доменов, а не только для того, который вы посещаете в данный момент. Файлы cookie, соответствующие домену текущего сайта, то есть тому, что отображается в адресной строке браузера, называются основными файлами cookie. Аналогично, файлы cookie из доменов, отличных от текущего сайта, называются сторонними файлами cookie. Это определение не абсолютное, а зависит от контекста пользователя; один и тот же файл cookie может быть как основным, так и сторонним, в зависимости от того, на каком сайте пользователь находится в данный момент.

Три файла cookie отправляются в браузер из разных запросов на одной странице
Файлы cookie могут поступать с разных доменов на одной странице.

Продолжая приведенный выше пример, предположим, что в одном из ваших сообщений в блоге есть изображение изумительно чудесного котика, и оно размещено по адресу /blog/img/amazing-cat.png. Поскольку это изображение такое изумительное, другой человек использует его прямо на своем сайте. Если посетитель был в вашем блоге и у него файл cookie promo_shown, то, когда он просматривает amazing-cat.png на сайте другого человека, этот файл cookie будет отправлен в этом запросе для изображения. Это никому не нужно, так как promo_shown ни для чего не используется на сайте этого человека, он просто добавляет накладные расходы к запросу.

Если это непреднамеренный эффект, то зачем вам это нужно? Именно этот механизм позволяет сайтам сохранять состояние, когда они используются в стороннем контексте. Например, если вы разместите на своем сайте видео с YouTube, посетители увидят в проигрывателе опцию «Посмотреть позже». Если ваш посетитель уже зарегистрирован на YouTube, его сессия будет доступна во встроенном проигрывателе с помощью стороннего cookie, то есть кнопка «Посмотреть позже» просто сохранит видео одним махом, а не предложит ему войти в систему или переместит его с вашей страницы обратно на YouTube.

Один и тот же файл cookie отправляется в трех разных контекстах<br>

Файл cookie в стороннем контексте отправляется при посещении разных страниц.

Одно из культурных свойств Интернета заключается в том, что он по умолчанию считается открытым. Отчасти это позволило многим людям создавать собственный контент и приложения. Однако это также породило ряд проблем, связанных с безопасностью и конфиденциальностью. Атаки с подделкой межсайтовых запросов (CSRF) основываются на том факте, что файлы cookie прикрепляются к любому запросу из заданного источника, независимо от того, кто инициирует запрос. Например, если вы посетите evil.example, он может инициировать запросы к your-blog.example, и ваш браузер с радостью прикрепит связанные файлы cookie. Если ваш блог не будет внимательно следить за тем, как он проверяет эти запросы, то evil.example ​может инициировать такие действия, как удаление сообщений или добавление собственного контента.

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

Введение атрибута SameSite (определенного в RFC6265bis) позволяет вам объявить, должен ли ваш файл cookie быть основным или внутрисайтовым. На этом моменте давайте вспомним, что именно означает «сайт». Сайтэто комбинация суффикса домена и части домена непосредственно перед ним. Например, домен www.web.dev является частью сайта web.dev.

Ключевой термин:

Если пользователь находится на www.web.dev и запрашивает изображение у static.web.dev, то это внутрисайтовый запрос.

Список публичных суффиксов public suffix list определяет это, поэтому речь не только о доменах верхнего уровня, таких как .com, но и о сервисах, таких как github.io, что позволяет считать your-project.github.io и my-project.github.io отдельными сайтами.

Ключевой термин:

Если пользователь находится на your-project.github.io и запрашивает изображение с my-project.github.io, это межсайтовый запрос.

Введение атрибута SameSite в файл cookie предоставляет три различных способа управления этим поведением. Вы можете не указывать атрибут или использовать значения атрибута Strict или Lax, чтобы ограничить файлы cookie внутрисайтовыми запросами.

Если вы установите для атрибута SameSite значение Strict, ваш файл cookie будет отправляться только для внутрисайтовых запросов. Говоря языком пользователей, файл cookie будет отправлен только в том случае, если сайт для файла cookie совпадает с сайтом, который в данный момент отображается в адресной строке браузера. То есть, если файл cookie promo_shown задан следующим образом:

Set-Cookie: promo_shown=1; SameSite=Strict

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

Именно здесь и приходит на помощь SameSite=Lax, который разрешает доступ к навигации верхнего уровня. Давайте вернемся к приведенному выше примеру статьи о котике,  где другой сайт ссылается на ваш контент. Они используют непосредственно вашу фотографию котика и дают ссылку на вашу оригинальную статью.

<p>Look at this amazing cat!</p>
<img src="https://blog.example/blog/img/amazing-cat.png" />
<p>Read the <a href="https://blog.example/blog/cat.html">article</a>.</p>

И файл cookie был задан следующим образом:

Set-Cookie: promo_shown=1; SameSite=Lax

Когда читатель находится в блоге другого человека, файл cookie не будет отправлен, если браузер запросит amazing-cat.png. Однако когда читатель перейдет по ссылке на cat.html в вашем блоге, этот запрос будет включать файл cookie. Это делает значение Lax хорошим выбором для файлов cookie, влияющих на отображение сайта, а значение Strictполезным для файлов cookie, связанных с действиями пользователя.

Внимание:

Ни Strict, ни Lax не закрывают полностью проблему с безопасностью.  Файлы cookie отправляются как часть запроса пользователя, и вы должны относиться к ним так же, как и к любому другому пользовательскому вводу. Это означает, что необходимо проверять и подтверждать вводимые данные. Никогда не используйте файлы cookie для безопасного хранения данных на стороне сервера.

Наконец, можно не указывать значение, что ранее было способом неявного заявления о том, что вы хотите, чтобы файлы cookie отправлялись во всех контекстах. В последнем проекте RFC6265bis это делается явным образом путем введения нового значения SameSite=None. Это означает, что вы можете использовать значение None, чтобы четко указать, что вы намеренно хотите, чтобы файл cookie был отправлен в стороннем контексте.

Три файла cookie, помеченных как None, Lax или Strict в зависимости от их контекста
Файлы cookie с явно указанным контекстом None, Lax или Strict.

Если вы предоставляете услугу, которую потребляют другие сайты, например, виджеты, встроенный контент, партнерские программы, рекламу или вход на нескольких сайтах, то вам следует использовать None, чтобы убедиться, что ваши намерения передавать cookie ясны.

Изменения поведения по умолчанию без атрибута SameSite #

Хотя атрибут SameSite широко поддерживается, он, к сожалению, не получил широкого распространения среди разработчиков. Открытая по умолчанию отправка файлов cookies повсюду означает, что все варианты использования работают, но оставляют пользователя уязвимым для CSRF-атак и непреднамеренной утечки информации. Чтобы побудить разработчиков заявить о своих намерениях и предоставить пользователям более безопасный опыт, в проект IETF (Incrementally Better Cookies) внесены два ключевых изменения:

  • если у файлов cookie не задан атрибут SameSite, будет считаться, что SameSite=Lax;
  • для файлов cookie с SameSite=None также нужно указывать параметр Secure, что означает, что такой запрос должен приходить только по защищённому каналу.

Chrome реализует это поведение по умолчанию, начиная с версии 84. В Firefox эти ключевые изменения доступны для тестирования, начиная с Firefox 69, и в будущем они будут использоваться по умолчанию. Чтобы проверить это поведение в Firefox, откройте about:config и установите network.cookie.sameSite.laxByDefault. Edge также планирует изменить свое поведение по умолчанию.

Эта статья будет обновляться по мере того, как дополнительные браузеры объявят о поддержке.

SameSite=Lax по умолчанию #

No attribute set

Set-Cookie: promo_shown=1

Если вы отправляете файл cookie без заданного значения для атрибута SameSite

Default behavior applied

Set-Cookie: promo_shown=1; SameSite=Lax

Браузер будет обрабатывать этот файл cookie, как если бы было указано SameSite=Lax.

Хотя это и задумывалось для применения более безопасного значения по умолчанию, в идеале вам следует явно задать значение атрибута SameSite, а не полагаться на то, что браузер применит его за вас. Это делает ваше намерение в отношении файлов cookie явным и повышает шансы на согласованное использование в разных браузерах.

Внимание:

Поведение по умолчанию, применяемое Chrome, не настолько строгое, чем явное SameSite=Lax, поскольку оно позволяет отправлять определенные файлы cookie при POST-запросах верхнего уровня. Точные подробности можно посмотреть в обсуждениях в группе blink-dev. Это временная мера, вам всё равно следует исправить свои межсайтовые файлы cookie на SameSite=None; Secure.

SameSite=None должен быть безопасным #

Rejected

Set-Cookie: widget_session=abc123; SameSite=None

Установка cookie без Secure будет отклонена.

Accepted

Set-Cookie: widget_session=abc123; SameSite=None; Secure

Вы должны убедиться, что для значения атрибута SameSite=None задан параметр Secure.

Вы можете протестировать это поведение в Chrome 76, включив about://flags/#cookies-without-same-site-must-be-secure и в Firefox 69, установив в about:config настройку network.cookie.sameSite.noneRequiresSecure.

Уверены, вы захотите применить эту настройку для новых файлов cookie и обновить существующие файлы cookie, даже если срок их действия еще не истек.

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

Оба эти изменения обратно совместимы с браузерами, которые правильно реализовали предыдущую версию SameSite или просто не поддерживают его. Применяя эти изменения к своим файлам cookie, вы явно указываете на их предполагаемое использование, а не полагаетесь на поведение браузера по умолчанию. Точно так же любые клиенты, которые еще не распознают SameSite=None должны игнорировать его и продолжать работу, как если бы атрибут не был установлен.

Предупреждение:

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

Чтобы прочитать подробнее о том, как именно обновить файлы cookie для успешной обработки изменений SameSite=None и о различиях в поведении браузеров, перейдите к следующей статье, Рецепты cookie SameSite.

Благодарим за вклад и отзывы Лили Чен, Мальте Убл, Майка Уэста, Роба Додсона, Тома Штайнера и Вивека Сехара.

Главное изображения печенья от Пилле-Рийн Приске на Unsplash

Последнее обновление: Улучшить статью