День 1680. #Безопасность
Cookie и Управление Сессиями
Управление сессиями в ASP.NET Core зависит от файлов cookie. Сервер отправляет cookie с использованием HTTP-заголовка Set-Cookie, который содержит имя файла cookie, его значение и необязательные атрибуты, например дату истечения срока действия (по умолчанию cookie истекает при закрытии браузера). Браузер может принять, отклонить файл cookie или спросить пользователя, что делать. Почти всегда действует первый вариант. Отключение файлов cookie в браузере практически не позволяет использовать многие веб-приложения.
Поскольку cookie хранятся в браузере, их значениями легко манипулировать. Нельзя хранить конфиденциальную информацию в файле cookie, например текущее имя пользователя или его привилегии. Управление сессиями использует cookie, но снижает риски манипулирования данными. Сервер хранит уникальный идентификатор сессии, который отправляется клиенту в виде файла cookie. Идентификатор генерируется на сервере, он довольно длинный, и его практически невозможно угадать.
В ASP.NET Core функциональность сессий должна быть активирована явно. В Program.cs нужно вызвать
Браузер отправляет файлы cookie обратно на сервер с каждым последующим запросом, поэтому сервер всегда может идентифицировать сессию и получить доступ к правильным данным. Пока идентификатор сессии не будет украден, процесс безопасен. Но если злоумышленник получает идентификатор, он может выдать себя за пользователя при общении с сервером.
Злоумышленник может украсть идентификатор сессии 3 способами:
1. на стороне клиента, как правило, используя межсайтовый скриптинг;
2. на стороне сервера, но осуществить такую атаку довольно непросто;
3. при передаче данных между клиентом и сервером через анализ трафика (сниффинг). Обычно такое возможно, только через HTTP.
См. также Принудительный HTTPS в ASP.NET Core.
Защитить файлы cookie можно с помощью флагов:
- HttpOnly – скрывает cookie от прямого доступа из кода JavaScript, что затрудняет межсайтовый скриптинг;
- secure – гарантирует, что cookie отправляется только через HTTPS.
Настройку флагов сеансовых файлов cookie нужно сделать явно в Program.cs:
Есть несколько признаков – но не доказательств! – успешной атаки:
1. Изменение IP-адреса.
Однако на это могут быть и законные причины: переключение мобильных устройств с Wi-Fi на мобильный интернет и обратно, балансировщики интернет-нагрузки в сети компании, автоматический сброс подключения через 24 часа у некоторых провайдеров и т.п.
2. Изменение других заголовков HTTP, например, строки user agent.
Это более весомый признак, хотя может случаться при обновлении браузера, поэтому сравнивать useк agent как строки посимвольно – не очень хорошая идея.
Требование повторного входа перед выполнением каких-либо критически важных операций может быть хорошей защитой от перехвата.
Источник: Кристиан Венц “Безопасность ASP.NET Core”. М.: ДМК Пресс, 2023. Глава 3.
Cookie и Управление Сессиями
Управление сессиями в ASP.NET Core зависит от файлов cookie. Сервер отправляет cookie с использованием HTTP-заголовка Set-Cookie, который содержит имя файла cookie, его значение и необязательные атрибуты, например дату истечения срока действия (по умолчанию cookie истекает при закрытии браузера). Браузер может принять, отклонить файл cookie или спросить пользователя, что делать. Почти всегда действует первый вариант. Отключение файлов cookie в браузере практически не позволяет использовать многие веб-приложения.
Поскольку cookie хранятся в браузере, их значениями легко манипулировать. Нельзя хранить конфиденциальную информацию в файле cookie, например текущее имя пользователя или его привилегии. Управление сессиями использует cookie, но снижает риски манипулирования данными. Сервер хранит уникальный идентификатор сессии, который отправляется клиенту в виде файла cookie. Идентификатор генерируется на сервере, он довольно длинный, и его практически невозможно угадать.
В ASP.NET Core функциональность сессий должна быть активирована явно. В Program.cs нужно вызвать
builder.Services.AddSession() и app.UseSession().Браузер отправляет файлы cookie обратно на сервер с каждым последующим запросом, поэтому сервер всегда может идентифицировать сессию и получить доступ к правильным данным. Пока идентификатор сессии не будет украден, процесс безопасен. Но если злоумышленник получает идентификатор, он может выдать себя за пользователя при общении с сервером.
Злоумышленник может украсть идентификатор сессии 3 способами:
1. на стороне клиента, как правило, используя межсайтовый скриптинг;
2. на стороне сервера, но осуществить такую атаку довольно непросто;
3. при передаче данных между клиентом и сервером через анализ трафика (сниффинг). Обычно такое возможно, только через HTTP.
См. также Принудительный HTTPS в ASP.NET Core.
Защитить файлы cookie можно с помощью флагов:
- HttpOnly – скрывает cookie от прямого доступа из кода JavaScript, что затрудняет межсайтовый скриптинг;
- secure – гарантирует, что cookie отправляется только через HTTPS.
Настройку флагов сеансовых файлов cookie нужно сделать явно в Program.cs:
builder.Services.AddSession(opt => {
opt.Cookie.HttpOnly = true;
opt.Cookie.SecurePolicy =
CookieSecurePolicy.Always;
});
Там же можно ограничить время, в течение которого можно использовать сеансовые cookie (по умолчанию 20 минут бездействия):opt.IdleTimeout = TimeSpan.FromMinutes(5);Обнаружение перехвата сессии
Есть несколько признаков – но не доказательств! – успешной атаки:
1. Изменение IP-адреса.
Однако на это могут быть и законные причины: переключение мобильных устройств с Wi-Fi на мобильный интернет и обратно, балансировщики интернет-нагрузки в сети компании, автоматический сброс подключения через 24 часа у некоторых провайдеров и т.п.
2. Изменение других заголовков HTTP, например, строки user agent.
Это более весомый признак, хотя может случаться при обновлении браузера, поэтому сравнивать useк agent как строки посимвольно – не очень хорошая идея.
Требование повторного входа перед выполнением каких-либо критически важных операций может быть хорошей защитой от перехвата.
Источник: Кристиан Венц “Безопасность ASP.NET Core”. М.: ДМК Пресс, 2023. Глава 3.
👍17
День 1759. #Оффтоп #Безопасность
Осторожно: URL – Это Указатели на Изменяемые Сущности
Люди часто оценивают URL как: «Безопасные или вредоносные». В частности, поставщики продуктов безопасности ставят URL в один ряд с такими индикаторами опасности, как хэш известного вредоносного файла, вредоносный/скомпрометированный цифровой сертификат или заведомо вредоносный IP.
К сожалению, это разные вещи. Хэш файла никогда не меняется, содержимое файла не может измениться без изменения его хэша, и «безвредный» файл не может стать «вредоносным»*.
*Мы говорим о самом файле, а не о пути к файлу.
Однако IP или URL, может легко измениться с «безобидного» на «опасный» и наоборот. IP – просто указатель, а URL — указатель на указатель. И даже после того, как клиент подключается к целевому серверу, этот сервер решает, как интерпретировать запрос, и может каждый раз возвращать разное содержимое.
Поэтому не только URL со временем может измениться с безобидного на вредоносный (например, злоумышленник приобретёт домен после истечения срока его регистрации). URL может даже быть одновременно безвредным и вредоносным в зависимости от того, кто его запрашивает (например, злоумышленник может «замаскировать» свою атаку, чтобы вернуть вредоносный контент целевым жертвам, одновременно предоставляя безвредный контент другим). Или сервер может выдавать разные ответы разным клиентам.
Недавно поиск «YouTube» в Google приводил к тому, что первая ссылка на странице была «рекламной» ссылкой. Если ничего не подозревающий пользователь нажимал на ссылку, он попадал на сайт мошенников, которые пытались захватить экран и убедить пользователя, что ему нужно позвонить злоумышленнику.
Как это возможно? Злоумышленники просто воспользовались тем фактом, что URL являются указателями на изменяемые объекты. Скорее всего злоумышленник разместил заказ на рекламу и указал ссылку на редиректор, который перенаправлял на какую-то страницу на YouTube. Система проверки рекламы Google проверила целевой URL, чтобы убедиться, что он действительно указывает на YouTube, и начала показывать рекламу. Затем злоумышленник обновил редиректор на свой мошеннический сайт — классическая уязвимость «время проверки, время использования».
Цепочка перенаправлений браузера при нажатии ссылки
Из-за того, как работает модель безопасности веб-платформы, способность Google обнаруживать такого рода уловки ограничена: после того, как браузер пользователя покидает сервер googleadservices.com, рекламная система Google не знает, где в итоге окажется пользователь, и не может знать, что следующий редиректор теперь отправляет пользователя на сайт атаки.
Более того, вы можете подсмотреть на подсказку статуса браузера в нижнем углу браузера, чтобы увидеть, куда ведёт ссылка, прежде чем нажать на неё. Но на самом деле перед этим есть ещё один уровень косвенности: ссылка (элемент
В частности, страница результатов поиска Google помещает URL в тэг
Вредоносные сайты всегда могли подделать статус, но производители браузеров ожидали, что «хорошие сайты» этого не делают. К сожалению, это неверное предположение. В этом случае отображение «настоящего» URL в статусе, вероятно, не добавит никакой защиты для осторожного пользователя — все ссылки на странице результатов Google проходят через какой-то редиректор.
Источник: https://textslashplain.com/2023/10/13/beware-urls-are-pointers-to-mutable-entities/
Осторожно: URL – Это Указатели на Изменяемые Сущности
Люди часто оценивают URL как: «Безопасные или вредоносные». В частности, поставщики продуктов безопасности ставят URL в один ряд с такими индикаторами опасности, как хэш известного вредоносного файла, вредоносный/скомпрометированный цифровой сертификат или заведомо вредоносный IP.
К сожалению, это разные вещи. Хэш файла никогда не меняется, содержимое файла не может измениться без изменения его хэша, и «безвредный» файл не может стать «вредоносным»*.
*Мы говорим о самом файле, а не о пути к файлу.
Однако IP или URL, может легко измениться с «безобидного» на «опасный» и наоборот. IP – просто указатель, а URL — указатель на указатель. И даже после того, как клиент подключается к целевому серверу, этот сервер решает, как интерпретировать запрос, и может каждый раз возвращать разное содержимое.
Поэтому не только URL со временем может измениться с безобидного на вредоносный (например, злоумышленник приобретёт домен после истечения срока его регистрации). URL может даже быть одновременно безвредным и вредоносным в зависимости от того, кто его запрашивает (например, злоумышленник может «замаскировать» свою атаку, чтобы вернуть вредоносный контент целевым жертвам, одновременно предоставляя безвредный контент другим). Или сервер может выдавать разные ответы разным клиентам.
Недавно поиск «YouTube» в Google приводил к тому, что первая ссылка на странице была «рекламной» ссылкой. Если ничего не подозревающий пользователь нажимал на ссылку, он попадал на сайт мошенников, которые пытались захватить экран и убедить пользователя, что ему нужно позвонить злоумышленнику.
Как это возможно? Злоумышленники просто воспользовались тем фактом, что URL являются указателями на изменяемые объекты. Скорее всего злоумышленник разместил заказ на рекламу и указал ссылку на редиректор, который перенаправлял на какую-то страницу на YouTube. Система проверки рекламы Google проверила целевой URL, чтобы убедиться, что он действительно указывает на YouTube, и начала показывать рекламу. Затем злоумышленник обновил редиректор на свой мошеннический сайт — классическая уязвимость «время проверки, время использования».
Цепочка перенаправлений браузера при нажатии ссылки
Из-за того, как работает модель безопасности веб-платформы, способность Google обнаруживать такого рода уловки ограничена: после того, как браузер пользователя покидает сервер googleadservices.com, рекламная система Google не знает, где в итоге окажется пользователь, и не может знать, что следующий редиректор теперь отправляет пользователя на сайт атаки.
Более того, вы можете подсмотреть на подсказку статуса браузера в нижнем углу браузера, чтобы увидеть, куда ведёт ссылка, прежде чем нажать на неё. Но на самом деле перед этим есть ещё один уровень косвенности: ссылка (элемент
<a>) сама по себе является указателем-на-указатель-на-указатель. Благодаря манипуляциям с JavaScript URL, на который указывает ссылка на странице, может измениться при нажатии на него.В частности, страница результатов поиска Google помещает URL в тэг
<a>, но, когда пользователь нажимает на него, URL изменяется на «настоящий»: googleadservices.com/... и только потом осуществляется перенаправление на целевой URL.Вредоносные сайты всегда могли подделать статус, но производители браузеров ожидали, что «хорошие сайты» этого не делают. К сожалению, это неверное предположение. В этом случае отображение «настоящего» URL в статусе, вероятно, не добавит никакой защиты для осторожного пользователя — все ссылки на странице результатов Google проходят через какой-то редиректор.
Источник: https://textslashplain.com/2023/10/13/beware-urls-are-pointers-to-mutable-entities/
👍10
День 1896. #Оффтоп #Безопасность
Бэкдор в SSH Linux
«Linux безопасен», - говорили они. «В Linux нет вирусов», - говорили они.
Зато туда едва не проник бэкдор, который мог позволить его автору получать root доступ к любой (!!!) машине под управлением Linux и в которой была установлена нужная версия библиотеки XZ Utils. Причём сделал это один из её главных контрибуторов и довольно хитро - в make-файле (которые обычно никто досконально не проверяет). Бэкдор активировался при сборке проекта. Насколько я понял, достаточно было добавить малозаметную точку в файл в очередном релизе, чтобы сборка «выбрасывала ошибку» при поиске одной из нужных библиотек, и вместо неё использовала «стандартную» с уязвимостью. После этого оставалось только ждать, пока все серверы обновят версию библиотеки и…
По иронии судьбы обнаружил это парень из Microsoft. Он заметил, что его входы в систему стали занимать дольше обычного (2,5 секунды против 2х раньше), и стал копать. Из-за этой счастливой случайности уязвимость не успела распространиться далее нескольких превью версий.
Национальная база данных уязвимостей США присвоила этой уязвимости критичность 10 из 10.
Больше подробностей об этом, а также чем процесс релиза кода в Microsoft отличается от процесса в «диком опенсорсе» смотрите в видео Dave’s Garage.
Бэкдор в SSH Linux
«Linux безопасен», - говорили они. «В Linux нет вирусов», - говорили они.
Зато туда едва не проник бэкдор, который мог позволить его автору получать root доступ к любой (!!!) машине под управлением Linux и в которой была установлена нужная версия библиотеки XZ Utils. Причём сделал это один из её главных контрибуторов и довольно хитро - в make-файле (которые обычно никто досконально не проверяет). Бэкдор активировался при сборке проекта. Насколько я понял, достаточно было добавить малозаметную точку в файл в очередном релизе, чтобы сборка «выбрасывала ошибку» при поиске одной из нужных библиотек, и вместо неё использовала «стандартную» с уязвимостью. После этого оставалось только ждать, пока все серверы обновят версию библиотеки и…
По иронии судьбы обнаружил это парень из Microsoft. Он заметил, что его входы в систему стали занимать дольше обычного (2,5 секунды против 2х раньше), и стал копать. Из-за этой счастливой случайности уязвимость не успела распространиться далее нескольких превью версий.
Национальная база данных уязвимостей США присвоила этой уязвимости критичность 10 из 10.
Больше подробностей об этом, а также чем процесс релиза кода в Microsoft отличается от процесса в «диком опенсорсе» смотрите в видео Dave’s Garage.
👍27
День 1970. #Безопасность
Межсайтовая Подделка Запросов (CSRF). Начало
В 2005 г. исследователь в области информационной безопасности Сами Камкар обнаружил уязвимость в популярной в то время социальной сети Myspace. Ему удалось внедрить код JavaScript на страницу своего профиля. Это классическая XSS-атака. Код отправлял HTTP-запрос от имени жертвы, добавляя её в список друзей Камкара. Не прошло и 20 часов, как у него было более миллиона друзей на Myspace.
Название атаки (Cross-Site Request Forgery - межсайтовая подделка запросов), по сути, описывает ее анатомию. Какой-то другой сайт (созданный злоумышленником) принудительно отправляет от имени клиента поддельный запрос. Чаще всего это выглядит так:
1. Пользователь ранее посещал (целевой) сайт и создал состояние – например, выполнил вход или добавил товары в корзину. Это состояние сохраняется, обычно в виде файла cookie (скажем, сеансового файла cookie, а сессия содержит состояние входа в систему или содержимое корзины).
2. Пока браузер открыт и сессия активна, пользователь переходит на другой сайт, контролируемый злоумышленником. Этот сайт делает запрос на целевой сайт, с которым пользователь ранее взаимодействовал, одним из двух способов:
- в случае GET-запроса сайт злоумышленника содержит код JavaScript, выполняющий запрос через скрытый
- в случае POST-запроса сайт злоумышленника содержит элемент
В итоге целевой сайт получает HTTP-запрос, отправленный браузером пользователя. Запрос содержит сеансовый файл cookie для идентификации пользователя. Поэтому сайт может выполнять действия «от имени» пользователя. GET-запросы обычно не так страшны, поскольку не меняют состояния (в соответствии с лучшими практиками), а вот POST-запросы могут действительно повлиять на приложение.
Замечание: конечно, у этой атаки есть некоторые предпосылки. Жертва должна была ранее посещать целевой сайт, и злоумышленник должен иметь подробное представление о том, как этот сайт работает. Но, как правило, если что-то может пойти не так, в итоге именно так и будет, поэтому можно с уверенностью предположить, что все эти условия будут соблюдены и атака удастся.
Эту атаку ещё называют "катание на сессии", т.к. сессия пользователя не крадётся, злоумышленник просто использует её "втёмную".
Именно так Сами Камкар завел новых друзей на Myspace: он нашел XSS-уязвимость и внедрил код JavaScript, который выполнял POST-запрос, чтобы «добавить пользователя в друзья».
В зависимости от того, в каком браузере вы пытаетесь это сделать, данная атака может сработать – или нет. Но всецело полагаться на защиту со стороны браузеров не стоит.
Окончание следует…
Источник: Кристиан Венц “Безопасность ASP.NET Core”. М.: ДМК Пресс, 2023. Глава 4.
Межсайтовая Подделка Запросов (CSRF). Начало
В 2005 г. исследователь в области информационной безопасности Сами Камкар обнаружил уязвимость в популярной в то время социальной сети Myspace. Ему удалось внедрить код JavaScript на страницу своего профиля. Это классическая XSS-атака. Код отправлял HTTP-запрос от имени жертвы, добавляя её в список друзей Камкара. Не прошло и 20 часов, как у него было более миллиона друзей на Myspace.
Название атаки (Cross-Site Request Forgery - межсайтовая подделка запросов), по сути, описывает ее анатомию. Какой-то другой сайт (созданный злоумышленником) принудительно отправляет от имени клиента поддельный запрос. Чаще всего это выглядит так:
1. Пользователь ранее посещал (целевой) сайт и создал состояние – например, выполнил вход или добавил товары в корзину. Это состояние сохраняется, обычно в виде файла cookie (скажем, сеансового файла cookie, а сессия содержит состояние входа в систему или содержимое корзины).
2. Пока браузер открыт и сессия активна, пользователь переходит на другой сайт, контролируемый злоумышленником. Этот сайт делает запрос на целевой сайт, с которым пользователь ранее взаимодействовал, одним из двух способов:
- в случае GET-запроса сайт злоумышленника содержит код JavaScript, выполняющий запрос через скрытый
iframe или <img> с адресом целевого сайта в атрибуте href;- в случае POST-запроса сайт злоумышленника содержит элемент
<form> с атрибутом method=POST и адресом целевого сайта в атрибуте action. А страница содержит код JavaScript, который отправляет данные формы.В итоге целевой сайт получает HTTP-запрос, отправленный браузером пользователя. Запрос содержит сеансовый файл cookie для идентификации пользователя. Поэтому сайт может выполнять действия «от имени» пользователя. GET-запросы обычно не так страшны, поскольку не меняют состояния (в соответствии с лучшими практиками), а вот POST-запросы могут действительно повлиять на приложение.
Замечание: конечно, у этой атаки есть некоторые предпосылки. Жертва должна была ранее посещать целевой сайт, и злоумышленник должен иметь подробное представление о том, как этот сайт работает. Но, как правило, если что-то может пойти не так, в итоге именно так и будет, поэтому можно с уверенностью предположить, что все эти условия будут соблюдены и атака удастся.
Эту атаку ещё называют "катание на сессии", т.к. сессия пользователя не крадётся, злоумышленник просто использует её "втёмную".
Именно так Сами Камкар завел новых друзей на Myspace: он нашел XSS-уязвимость и внедрил код JavaScript, который выполнял POST-запрос, чтобы «добавить пользователя в друзья».
В зависимости от того, в каком браузере вы пытаетесь это сделать, данная атака может сработать – или нет. Но всецело полагаться на защиту со стороны браузеров не стоит.
Окончание следует…
Источник: Кристиан Венц “Безопасность ASP.NET Core”. М.: ДМК Пресс, 2023. Глава 4.
👍21
День 1971. #Безопасность
Межсайтовая Подделка Запросов (CSRF). Окончание
Начало
В случае с CSRF есть два аспекта, которые делают атаку возможной:
1. Злоумышленник может точно предсказать HTTP-запрос. Это сделать несложно, проанализировав настоящий запрос. Данные формы передаются в открытом виде, поэтому их легко подменить, имитировав нужные параметры.
2. Активная сессия. Но файлы cookie клиента автоматически отправляются на сервер, которому они принадлежат. Злоумышленнику не нужно красть идентификатор сессии; он использует сессию пользователя.
Замечание: конечно, пользователь также должен как-то принимать в этом участие. Обычно ему нужно зайти на целевой сайт, а также посетить сайт злоумышленника. Но этого возможно добиться с помощью методов социальной инженерии или распространения вредоносного URL-адреса, и вполне вероятно, подходящая жертва найдется.
Делаем HTTP-запрос непредсказуемым
Если к данным формы мы добавим дополнительный случайный токен, то атака завершится неудачей. Злоумышленник не сможет предугадать токен, поэтому не сможет создать валидный запрос. Если приложение использует одноразовые токены, то каждый из них будет действителен только один раз. Случайный токен будет явной частью HTML-формы, и такой же токен в файле cookie будет отправлен клиентом автоматически. На сервере оба этих значения проверяются. Если они отсутствуют или не совпадают, то приложение выдаёт ошибку 400 Bad Request.
В ASP.NET Core такой механизм уже есть и активирован по умолчанию. ASP.NET Core автоматически добавляет в форму дополнительное скрытое поле, вроде такого:
А сервер отправляет cookie, например:
Всего символов в значениях поля и cookie около 150. Примерно первые 20 совпадают, остальные нет. При каждой перезагрузке формы токен в поле меняется, но файл cookie останется прежним. Так приложение может работать на нескольких вкладках браузера с общим файлом cookie.
Никакой дополнительной настройки не требуется, если вы используете форму следующими способами:
-
-
Механизм защиты от CSRF представляет собой промежуточное ПО, которое автоматически активируется, при использовании стандартных методов в классе Program:
- MVC (AddMvc(), AddControllersWithViews() или MapControllerRoute()),
- Razor Pages (AddRazorPages() или MapRazorPages()),
- Blazor (MapBlazorHub())
Если вы хотите избавиться от токенов (а у вас для этого должна быть очень веская причина, например другое приложение, отправляющее POST-запрос в вашу конечную точку), то либо:
- используйте
- деактивируйте CSRF-токен для каждой формы с помощью
Токен по умолчанию генерируется и добавляется в любую форму, но не проверяется автоматически. Используя фильтры в ASP.NET Core (атрибуты или глобальные фильтры), можно реализовать 3 варианта:
-
-
-
Источник: Кристиан Венц “Безопасность ASP.NET Core”. М.: ДМК Пресс, 2023. Глава 4.
Межсайтовая Подделка Запросов (CSRF). Окончание
Начало
В случае с CSRF есть два аспекта, которые делают атаку возможной:
1. Злоумышленник может точно предсказать HTTP-запрос. Это сделать несложно, проанализировав настоящий запрос. Данные формы передаются в открытом виде, поэтому их легко подменить, имитировав нужные параметры.
2. Активная сессия. Но файлы cookie клиента автоматически отправляются на сервер, которому они принадлежат. Злоумышленнику не нужно красть идентификатор сессии; он использует сессию пользователя.
Замечание: конечно, пользователь также должен как-то принимать в этом участие. Обычно ему нужно зайти на целевой сайт, а также посетить сайт злоумышленника. Но этого возможно добиться с помощью методов социальной инженерии или распространения вредоносного URL-адреса, и вполне вероятно, подходящая жертва найдется.
Делаем HTTP-запрос непредсказуемым
Если к данным формы мы добавим дополнительный случайный токен, то атака завершится неудачей. Злоумышленник не сможет предугадать токен, поэтому не сможет создать валидный запрос. Если приложение использует одноразовые токены, то каждый из них будет действителен только один раз. Случайный токен будет явной частью HTML-формы, и такой же токен в файле cookie будет отправлен клиентом автоматически. На сервере оба этих значения проверяются. Если они отсутствуют или не совпадают, то приложение выдаёт ошибку 400 Bad Request.
В ASP.NET Core такой механизм уже есть и активирован по умолчанию. ASP.NET Core автоматически добавляет в форму дополнительное скрытое поле, вроде такого:
html
<input name="__RequestVerificationToken" type="hidden"
value="CfDJ8FflGUpl_…U90c" />
А сервер отправляет cookie, например:
.AspNetCore.Antiforgery.Za7zYHoQn5w=CfDJ8FflGUpl_…0ueI
Всего символов в значениях поля и cookie около 150. Примерно первые 20 совпадают, остальные нет. При каждой перезагрузке формы токен в поле меняется, но файл cookie останется прежним. Так приложение может работать на нескольких вкладках браузера с общим файлом cookie.
Никакой дополнительной настройки не требуется, если вы используете форму следующими способами:
-
<form method="post">...</form>-
@Html.BeginForm(...)Механизм защиты от CSRF представляет собой промежуточное ПО, которое автоматически активируется, при использовании стандартных методов в классе Program:
- MVC (AddMvc(), AddControllersWithViews() или MapControllerRoute()),
- Razor Pages (AddRazorPages() или MapRazorPages()),
- Blazor (MapBlazorHub())
Если вы хотите избавиться от токенов (а у вас для этого должна быть очень веская причина, например другое приложение, отправляющее POST-запрос в вашу конечную точку), то либо:
- используйте
<!form>...<!/form>;- деактивируйте CSRF-токен для каждой формы с помощью
asp-antiforgery="false".Токен по умолчанию генерируется и добавляется в любую форму, но не проверяется автоматически. Используя фильтры в ASP.NET Core (атрибуты или глобальные фильтры), можно реализовать 3 варианта:
-
AutoValidateAntiForgeryToken – требует (и проверяет) токены для всех HTTP-запросов, меняющих состояние приложения (все, кроме GET, HEAD, OPTIONS и TRACE);-
ValidateAntiForgeryToken – гарантирует, что метод-действие, помеченный этим атрибутом, проверит запрос, независимо от HTTP-метода;-
IgnoreAntiForgeryToken – отключает проверку токенов.Источник: Кристиан Венц “Безопасность ASP.NET Core”. М.: ДМК Пресс, 2023. Глава 4.
👍15
День 2189. #Безопасность
CORS. Использование Ресурсов Между Разными Источниками. Начало
Рассмотрим, что было бы, если бы можно было использовать JavaScript для вызова конечной точки из другого источника.
См. определение источника тут.
Ниже показан простой веб-API https://localhost:3000 с конечными точками Get() и Post():
Get() возвращает случайное число между 10 и 99, а Post() ничего не делает.
В другом проекте, в другом источнике https://localhost:5000, для вызова этого API страница Razor использует JavaScript:
Код JavaScript использует метод fetch() для вызова API на другом сервере, а затем выводит результаты. Однако выполнение кода приводит тому, что случайное число не отображается, а на вкладке Сеть в инструментах разработчика браузера вызов API выделен красным цветом.
Запрос был отправлен, но JS не получил никаких данных. Причина: правило ограничения домена (CORS). Если бы этот запрос работал, злоумышленник мог бы использовать JS для отправки HTTP-запроса на страницу, чтобы, например, добавить товар в корзину – автоматически с использованием файла cookie идентификатора сессии пользователя (см. также Безопасность Cookie). В рамках анализа ответа злоумышленник мог бы извлечь antiforgery-токен из формы и, следовательно, обойти защиту от межсайтовой подделки запросов.
И хотя данный вид атаки ещё не был изобретен, когда появилось правило ограничения домена, поскольку JS не может получить доступ к HTTP-ответу (спасибо правилу ограничения домена), атака не сработает.
Продолжение следует…
Источник: Кристиан Венц “Безопасность ASP.NET Core”. М.: ДМК Пресс, 2023. Глава 4.
CORS. Использование Ресурсов Между Разными Источниками. Начало
Рассмотрим, что было бы, если бы можно было использовать JavaScript для вызова конечной точки из другого источника.
См. определение источника тут.
Ниже показан простой веб-API https://localhost:3000 с конечными точками Get() и Post():
using Microsoft.AspNetCore.Mvc;
namespace MyApp.Controllers;
[Route("api/[controller]")]
[ApiController]
public class CorsController : ControllerBase
{
// GET: api/Cors
[HttpGet]
public int Get()
{
return new Random().Next(10, 100);
}
// POST api/Cors
[HttpPost]
public void Post([FromBody] int value)
{
}
}
Get() возвращает случайное число между 10 и 99, а Post() ничего не делает.
В другом проекте, в другом источнике https://localhost:5000, для вызова этого API страница Razor использует JavaScript:
@page
<div class="text-center">
<h1 class="display-4">CORS</h1>
<div id="output"></div>
</div>
@section Scripts {
<script>
fetch("https://localhost:3000/api/Cors")
.then(response => response.json())
.then(data => {
document
.getElementById("output")
.textContent = data;
});
</script>
}
Код JavaScript использует метод fetch() для вызова API на другом сервере, а затем выводит результаты. Однако выполнение кода приводит тому, что случайное число не отображается, а на вкладке Сеть в инструментах разработчика браузера вызов API выделен красным цветом.
Запрос был отправлен, но JS не получил никаких данных. Причина: правило ограничения домена (CORS). Если бы этот запрос работал, злоумышленник мог бы использовать JS для отправки HTTP-запроса на страницу, чтобы, например, добавить товар в корзину – автоматически с использованием файла cookie идентификатора сессии пользователя (см. также Безопасность Cookie). В рамках анализа ответа злоумышленник мог бы извлечь antiforgery-токен из формы и, следовательно, обойти защиту от межсайтовой подделки запросов.
И хотя данный вид атаки ещё не был изобретен, когда появилось правило ограничения домена, поскольку JS не может получить доступ к HTTP-ответу (спасибо правилу ограничения домена), атака не сработает.
Продолжение следует…
Источник: Кристиан Венц “Безопасность ASP.NET Core”. М.: ДМК Пресс, 2023. Глава 4.
👍17
День 2190. #Безопасность
CORS. Использование Ресурсов Между Разными Источниками. Продолжение
Начало
Но что, если у JavaScript кода приложения есть законный интерес к вызову API? Если внимательно посмотреть на HTTP-запрос, который был сгенерирован, когда мы попытались вызвать API из JavaScript, мы заметим кое-что любопытное. Заголовок Origin не отправляется с каждым запросом, но браузер автоматически добавляет его при кросс-доменном запросе:
Заголовок содержит источник – протокол, домен, порт – вызывающей страницы. Тогда сервер может взять эту информацию и решить, может ли код JavaScript иметь доступ к данным, поступающим с сервера. Если да, то HTTP-ответ должен включать заголовок Access-Control-Allow-Origin и в качестве значения для него должен использовать отправленный источник (или заполнитель *, но, как всегда, лучше быть как можно более явным):
Этот механизм называется совместное использование ресурсов между источниками (CORS), и ASP.NET Core поддерживает его – нет необходимости реализовывать его вручную. В диспетчере пакетов NuGet по запросу «CORS» выдаётся длинный список результатов. Но все они предназначены для .NET Standard и .NET Framework. ASP.NET Core автоматически использует собственную версию пакета Microsoft.AspNetCore.Cors. CORS поставляется как промежуточное ПО в ASP.NET Core, поэтому нужно сделать его доступным и активировать. В классе Program требуется:
- добавить поддержку CORS (и настроить её), с помощью AddCors();
- активировать CORS - UseCors().
При вызове AddCors() можно указать параметры. Обычно нужно настроить хотя бы одну политику CORS (т.е. определить разрешённые источники):
Важно:
- Используйте источник клиента API, а не URL самого API!
- Источник должен состоять только из протокола, домена и порта, без слеша в конце.
Можно использовать произвольное количество политик, и у каждой может быть любое количество источников. Переменная bldr (типа CorsPolicyBuilder) также предоставляет методы, чтобы явно разрешить другие фрагменты информации для кросс-доменного запроса с использованием JS:
- WithExposedHeaders() – список заголовков HTTP-ответа, которые возвращаются и становятся доступными для JS;
- WithHeaders() – список разрешённых дополнительных заголовков HTTP-запросов, к которым клиент хотел бы получить доступ;
- WithMethods() – список разрешённых дополнительных HTTP-методов.
- AllowAnyHeader() – разрешать все заголовки;
- AllowAnyMethod() – разрешать все методы.
По умолчанию никакие учётные данные, например заголовки Authorization, не отправляются вместе с кросс-доменным запросом. Опять же, причина
тому – защита от межсайтовой подделки запросов. Если вы хотите, чтобы эта информация была доступна для API, метод AllowCredentials() сообщает клиенту, что её можно отправлять, а DisallowCredentials() - явно запрещает.
Наконец, можно использовать политику по умолчанию:
Окончание следует…
Источник: Кристиан Венц “Безопасность ASP.NET Core”. М.: ДМК Пресс, 2023. Глава 4.
CORS. Использование Ресурсов Между Разными Источниками. Продолжение
Начало
Но что, если у JavaScript кода приложения есть законный интерес к вызову API? Если внимательно посмотреть на HTTP-запрос, который был сгенерирован, когда мы попытались вызвать API из JavaScript, мы заметим кое-что любопытное. Заголовок Origin не отправляется с каждым запросом, но браузер автоматически добавляет его при кросс-доменном запросе:
GET /api/Cors HTTP/2
Host: localhost:3000
…
Origin: https://localhost:5000
…
Заголовок содержит источник – протокол, домен, порт – вызывающей страницы. Тогда сервер может взять эту информацию и решить, может ли код JavaScript иметь доступ к данным, поступающим с сервера. Если да, то HTTP-ответ должен включать заголовок Access-Control-Allow-Origin и в качестве значения для него должен использовать отправленный источник (или заполнитель *, но, как всегда, лучше быть как можно более явным):
Access-Control-Allow-Origin: https://localhost:5000
Этот механизм называется совместное использование ресурсов между источниками (CORS), и ASP.NET Core поддерживает его – нет необходимости реализовывать его вручную. В диспетчере пакетов NuGet по запросу «CORS» выдаётся длинный список результатов. Но все они предназначены для .NET Standard и .NET Framework. ASP.NET Core автоматически использует собственную версию пакета Microsoft.AspNetCore.Cors. CORS поставляется как промежуточное ПО в ASP.NET Core, поэтому нужно сделать его доступным и активировать. В классе Program требуется:
- добавить поддержку CORS (и настроить её), с помощью AddCors();
- активировать CORS - UseCors().
При вызове AddCors() можно указать параметры. Обычно нужно настроить хотя бы одну политику CORS (т.е. определить разрешённые источники):
builder.Services.AddCors(opts =>
{
opts.AddPolicy("CORS API Endpoint",
bldr =>
{
bldr.WithOrigins("https://localhost:5000");
});
});
Важно:
- Используйте источник клиента API, а не URL самого API!
- Источник должен состоять только из протокола, домена и порта, без слеша в конце.
Можно использовать произвольное количество политик, и у каждой может быть любое количество источников. Переменная bldr (типа CorsPolicyBuilder) также предоставляет методы, чтобы явно разрешить другие фрагменты информации для кросс-доменного запроса с использованием JS:
- WithExposedHeaders() – список заголовков HTTP-ответа, которые возвращаются и становятся доступными для JS;
- WithHeaders() – список разрешённых дополнительных заголовков HTTP-запросов, к которым клиент хотел бы получить доступ;
- WithMethods() – список разрешённых дополнительных HTTP-методов.
- AllowAnyHeader() – разрешать все заголовки;
- AllowAnyMethod() – разрешать все методы.
По умолчанию никакие учётные данные, например заголовки Authorization, не отправляются вместе с кросс-доменным запросом. Опять же, причина
тому – защита от межсайтовой подделки запросов. Если вы хотите, чтобы эта информация была доступна для API, метод AllowCredentials() сообщает клиенту, что её можно отправлять, а DisallowCredentials() - явно запрещает.
Наконец, можно использовать политику по умолчанию:
options.AddDefaultPolicy(
bldr =>
{
bldr.WithOrigins("https://localhost:5000");
});
Окончание следует…
Источник: Кристиан Венц “Безопасность ASP.NET Core”. М.: ДМК Пресс, 2023. Глава 4.
👍17
День 2191. #Безопасность
CORS. Использование Ресурсов Между Разными Источниками. Окончание
Начало
Продолжение
Теперь, когда политика настроена, пришло время её использовать. В зависимости от приложения, возможно, вы захотите, чтобы она применялась глобально, только для определённых конечных точек или маршрутов.
1. Глобально
Нужна политика по умолчанию, затем нужно добавить вызов метода UseCors(). Важен порядок. CORS необходимо активировать:
- после маршрутизации (UseRouting()),
- перед кешированием ответов, аутентификацией и авторизацией (UseResponseCaching(), UseAuthentication(), UseAuthorization()).
Для политики по умолчанию достаточно вызвать:
2. Для конечных точек
Для именованных политик также нужен вызов UseCors() в Program.cs, но т.к. нет политики по умолчанию, затем необходимо добавить атрибут [EnableCors] с именем политики в класс контроллера (для всех методов) или только в отдельные методы:
Теперь все методы в контроллере API отправляют правильный заголовок Access-Control-Allow-Origin. При этом атрибут [DisableCors] отключит политику для отдельных методов контроллера. Применив эти изменения к API и снова вызвав страницу из изначального примера, мы получаем желаемый результат. На этот раз не только проходит HTTP-запрос, но и код JS может получить доступ к возвращаемому значению и отобразить его.
3. Для маршрутов
Применяе именованные политики к маршрутам. В ASP.NET Core это настраивается в методе app.UseEndpoints() с помощью расширения RequireCors() после вызова MapControllers(), MapControllerRoute(), MapGet() или аналогичных:
CORS на стероидах: предварительные запросы
GET-запрос из нашего примера всё равно выполняется, даже если не соответствует политике (т.к. считается, что GET-запросы не изменяют состояния приложения), но код JS не получает доступа к возвращаемым данным. POST (и другие) запросы могут изменить состояние приложения, поэтому их нельзя просто отправить. В таких случаях браузеры отправляют предварительные запросы (preflight request). Сначала - запрос OPTIONS. Он также не должен ничего изменить на сервере. Если ответ содержит заголовок Access-Control-Allow-Origin с соответствующим значением, и ответ положительный, на сервер будет отправлен ещё один запрос, чтобы получить ресурсы.
Поскольку REST API не имеют состояния, сервер должен проверять все запросы. Но мы можем указать (через заголовок Access-Control-Max-Age), что предварительный запрос не обязательно делать каждый раз. В .NET это можно легко настроить внутри метода AddCors:
SetPreflightMaxAge даст указание клиенту кэшировать предварительный запрос CORS на 10 минут (т.е. он отправляет заголовок Access-Control-Max-Age со значением 600).
Источники:
- Кристиан Венц “Безопасность ASP.NET Core”. М.: ДМК Пресс, 2023. Глава 4.
- https://steven-giesel.com/blogPost/5fc7cb62-d5ad-4f07-831c-d6c1c6974641/cache-cors-preflight-requests
CORS. Использование Ресурсов Между Разными Источниками. Окончание
Начало
Продолжение
Теперь, когда политика настроена, пришло время её использовать. В зависимости от приложения, возможно, вы захотите, чтобы она применялась глобально, только для определённых конечных точек или маршрутов.
1. Глобально
Нужна политика по умолчанию, затем нужно добавить вызов метода UseCors(). Важен порядок. CORS необходимо активировать:
- после маршрутизации (UseRouting()),
- перед кешированием ответов, аутентификацией и авторизацией (UseResponseCaching(), UseAuthentication(), UseAuthorization()).
Для политики по умолчанию достаточно вызвать:
app.UseCors();
2. Для конечных точек
Для именованных политик также нужен вызов UseCors() в Program.cs, но т.к. нет политики по умолчанию, затем необходимо добавить атрибут [EnableCors] с именем политики в класс контроллера (для всех методов) или только в отдельные методы:
[Route("api/[controller]")]
[EnableCors("CORS API Endpoint")]
[ApiController]
public class CorsController : ControllerBase
{
…
}Теперь все методы в контроллере API отправляют правильный заголовок Access-Control-Allow-Origin. При этом атрибут [DisableCors] отключит политику для отдельных методов контроллера. Применив эти изменения к API и снова вызвав страницу из изначального примера, мы получаем желаемый результат. На этот раз не только проходит HTTP-запрос, но и код JS может получить доступ к возвращаемому значению и отобразить его.
3. Для маршрутов
Применяе именованные политики к маршрутам. В ASP.NET Core это настраивается в методе app.UseEndpoints() с помощью расширения RequireCors() после вызова MapControllers(), MapControllerRoute(), MapGet() или аналогичных:
app.UseEndpoints(eps =>
{
eps.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}")
.RequireCors("CORS API Endpoint");
});
CORS на стероидах: предварительные запросы
GET-запрос из нашего примера всё равно выполняется, даже если не соответствует политике (т.к. считается, что GET-запросы не изменяют состояния приложения), но код JS не получает доступа к возвращаемым данным. POST (и другие) запросы могут изменить состояние приложения, поэтому их нельзя просто отправить. В таких случаях браузеры отправляют предварительные запросы (preflight request). Сначала - запрос OPTIONS. Он также не должен ничего изменить на сервере. Если ответ содержит заголовок Access-Control-Allow-Origin с соответствующим значением, и ответ положительный, на сервер будет отправлен ещё один запрос, чтобы получить ресурсы.
Поскольку REST API не имеют состояния, сервер должен проверять все запросы. Но мы можем указать (через заголовок Access-Control-Max-Age), что предварительный запрос не обязательно делать каждый раз. В .NET это можно легко настроить внутри метода AddCors:
builder.Services.AddCors(opts =>
{
opts.AddPolicy("CORS API Endpoint",
bldr =>
{
bldr.
…
.SetPreflightMaxAge(TimeSpan.FromMinutes(10));
});
});
SetPreflightMaxAge даст указание клиенту кэшировать предварительный запрос CORS на 10 минут (т.е. он отправляет заголовок Access-Control-Max-Age со значением 600).
Источники:
- Кристиан Венц “Безопасность ASP.NET Core”. М.: ДМК Пресс, 2023. Глава 4.
- https://steven-giesel.com/blogPost/5fc7cb62-d5ad-4f07-831c-d6c1c6974641/cache-cors-preflight-requests
👍13
День 2231. #Безопасность
Атрибуты Безопасности Файлов Cookie
Один из самых распространённых способов, которым веб-браузеры используют cookie, — это аутентификация пользователя и сохранение сессии. Злоумышленники могут украсть или подделать cookie для получения доступа к аутентифицированным областям и существующим сессиям пользователя.
Существует 3 распространённых атаки с использованием cookie:
1. Атаки с использованием межсайтового скриптинга (XSS) и атаки типа «человек посередине» (MITM) часто используются для кражи файлов cookie.
2. Атаки с использованием межсайтовой подделки запросов (CSRF) используют способ обработки файлов cookie браузерами для выполнения вредоносных действий от имени аутентифицированных пользователей.
Спецификация протокола HTTP содержит несколько механизмов, которые разработчики могут использовать для снижения риска доступа злоумышленников к содержимому cookie с конфиденциальными данными, их повторного использования или подделки. Ниже перечислены атрибуты заголовка HTTP Set-Cookie, которые можно использовать для повышения безопасности файлов cookie.
1. Expire и Max-Age
Определяют срок действия cookie. Expire устанавливает абсолютную дату/время истечения срока действия (формат: weekday, DD-MM-YYYY hh:mm:ss GMT), а атрибут Max-Age - ограничение по времени с момента установки cookie. Если Expire и Max-Age не установлены, браузер обрабатывает cookie как сеансовый и удаляет его при закрытии браузера. Если установлены, сохраняет cookie как постоянный на стороне клиента и удаляет в соответствии со значениями Expire и Max-Age (в зависимости от того, что наступит раньше).
2. Secure
Указывает, что cookie может передаваться только с использованием HTTPS-соединений и никогда не отправляется в открытом виде. Браузер не будет отправлять Secure cookie с запросами HTTP.
Атрибут Secure предназначен для защиты от атак типа «человек посередине» (MITM). Однако он защищает только конфиденциальность файла cookie, а не его целостность. Злоумышленник не получит cookie с сервера через незашифрованное соединение, но всё равно может отправить поддельный cookie на сервер в виде обычного текста.
3. Domain
Объявляет домен, на который будет отправлен cookie (а также все поддомены). Если атрибут Domain не установлен, cookie будет отправлен только на исходный хост (без поддоменов). Поэтому наиболее безопасный способ — не устанавливать атрибут Domain, если это не необходимо.
4. Path
URL-путь, по которому будет отправлен cookie (включая все подпути). По умолчанию - / (все URL-пути на сервере).
5. HttpOnly
Введён для предотвращения атак XSS. Браузер будет отправлять cookie с этим атрибутом только в ответ на HTTP-запросы, т.е. к ним нельзя будет получить доступ из клиентского кода JavaScript. Однако атрибут HttpOnly не защищает cookie от перезаписи. Браузер может хранить только ограниченное количество файлов cookie для домена. Злоумышленник может использовать атаку переполнения хранилища cookie, тем самым удаляя исходный cookie из памяти браузера и добавляя cookie с тем же именем без атрибута HttpOnly.
6. SameSite
Предписывает веб-браузерам отправлять cookie по-разному в зависимости от того, как посетитель взаимодействует с сайтом, установившим cookie. Используется для защиты от атак CSRF. Может иметь одно из следующих значений:
-
-
-
Внимание: если атрибут SameSite не установлен, можно ожидать разного поведения браузеров и разных версий одного браузера.
См. также Cookie и Управление Сессиями
Источник: https://www.invicti.com/learn/cookie-security-flags/
Атрибуты Безопасности Файлов Cookie
Один из самых распространённых способов, которым веб-браузеры используют cookie, — это аутентификация пользователя и сохранение сессии. Злоумышленники могут украсть или подделать cookie для получения доступа к аутентифицированным областям и существующим сессиям пользователя.
Существует 3 распространённых атаки с использованием cookie:
1. Атаки с использованием межсайтового скриптинга (XSS) и атаки типа «человек посередине» (MITM) часто используются для кражи файлов cookie.
2. Атаки с использованием межсайтовой подделки запросов (CSRF) используют способ обработки файлов cookie браузерами для выполнения вредоносных действий от имени аутентифицированных пользователей.
Спецификация протокола HTTP содержит несколько механизмов, которые разработчики могут использовать для снижения риска доступа злоумышленников к содержимому cookie с конфиденциальными данными, их повторного использования или подделки. Ниже перечислены атрибуты заголовка HTTP Set-Cookie, которые можно использовать для повышения безопасности файлов cookie.
1. Expire и Max-Age
Определяют срок действия cookie. Expire устанавливает абсолютную дату/время истечения срока действия (формат: weekday, DD-MM-YYYY hh:mm:ss GMT), а атрибут Max-Age - ограничение по времени с момента установки cookie. Если Expire и Max-Age не установлены, браузер обрабатывает cookie как сеансовый и удаляет его при закрытии браузера. Если установлены, сохраняет cookie как постоянный на стороне клиента и удаляет в соответствии со значениями Expire и Max-Age (в зависимости от того, что наступит раньше).
2. Secure
Указывает, что cookie может передаваться только с использованием HTTPS-соединений и никогда не отправляется в открытом виде. Браузер не будет отправлять Secure cookie с запросами HTTP.
Атрибут Secure предназначен для защиты от атак типа «человек посередине» (MITM). Однако он защищает только конфиденциальность файла cookie, а не его целостность. Злоумышленник не получит cookie с сервера через незашифрованное соединение, но всё равно может отправить поддельный cookie на сервер в виде обычного текста.
3. Domain
Объявляет домен, на который будет отправлен cookie (а также все поддомены). Если атрибут Domain не установлен, cookie будет отправлен только на исходный хост (без поддоменов). Поэтому наиболее безопасный способ — не устанавливать атрибут Domain, если это не необходимо.
4. Path
URL-путь, по которому будет отправлен cookie (включая все подпути). По умолчанию - / (все URL-пути на сервере).
5. HttpOnly
Введён для предотвращения атак XSS. Браузер будет отправлять cookie с этим атрибутом только в ответ на HTTP-запросы, т.е. к ним нельзя будет получить доступ из клиентского кода JavaScript. Однако атрибут HttpOnly не защищает cookie от перезаписи. Браузер может хранить только ограниченное количество файлов cookie для домена. Злоумышленник может использовать атаку переполнения хранилища cookie, тем самым удаляя исходный cookie из памяти браузера и добавляя cookie с тем же именем без атрибута HttpOnly.
6. SameSite
Предписывает веб-браузерам отправлять cookie по-разному в зависимости от того, как посетитель взаимодействует с сайтом, установившим cookie. Используется для защиты от атак CSRF. Может иметь одно из следующих значений:
-
SameSite=Strict: cookie отправляется только, если вы в данный момент находитесь на сайте, который установил cookie. Если вы переходите с другого сайта (например, из результатов поиска в Google), такой cookie не отправляется с первым запросом.-
SameSite=Lax: файл куки отправляется с GET-запросами верхнего уровня, но не отправляется для встроенного контента (рисунки, CSS, JS).-
SameSite=None: ограничений нет.Внимание: если атрибут SameSite не установлен, можно ожидать разного поведения браузеров и разных версий одного браузера.
См. также Cookie и Управление Сессиями
Источник: https://www.invicti.com/learn/cookie-security-flags/
👍16