День 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