Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Подделка межсайтовой заявки — это атака на веб-приложения, в которых вредоносное веб-приложение может вмешиваться во взаимодействие между браузером клиента и веб-приложением, которое доверяет этому браузеру. Эти атаки возможны, так как веб-браузеры автоматически отправляют некоторые типы маркеров проверки подлинности с каждым запросом на веб-сайт. Эта форма эксплойта также называется атакой одним щелчком или сеансовым угоном, так как атака использует прошедший аутентификацию сеанс пользователя. Подделка межсайтовых запросов также называется XSRF или CSRF.
Пример атаки CSRF:
Пользователь входит в
www.good-banking-site.example.comсистему с помощью проверки подлинности форм. Сервер выполняет проверку подлинности пользователя и выдает ответ, содержащий проверку подлинности cookie. Сайт уязвим к атакам, поскольку сайт доверяет любому полученному запросу с допустимой аутентификацией cookie.Пользователь посещает вредоносный сайт.
www.bad-crook-site.example.comВредоносный сайт
www.bad-crook-site.example.comсодержит HTML-форму, аналогичную следующему примеру:<h1>Congratulations! You're a Winner!</h1> <form action="https://www.good-banking-site.example.com/api/account" method="post"> <input type="hidden" name="Transaction" value="withdraw" /> <input type="hidden" name="Amount" value="1000000" /> <input type="submit" value="Click to collect your prize!" /> </form>Обратите внимание, что отправка формы
actionпроисходит на уязвимый сайт, а не на вредоносный сайт. Это "межсайтовая" часть CSRF.Пользователь выбирает кнопку отправки. Браузер выполняет запрос и автоматически включает проверку подлинности cookie для запрошенного домена
www.good-banking-site.example.com.Запрос выполняется на сервере
www.good-banking-site.example.comс контекстом проверки подлинности пользователя и может выполнять любое действие, которое разрешено выполнить пользователю, прошедшему проверку подлинности.
Помимо сценария, когда пользователь выбирает кнопку для отправки формы, вредоносный сайт может:
- Запустите скрипт, который автоматически отправляет форму.
- Отправьте отправку формы в виде запроса AJAX.
- Скрытие формы с помощью CSS.
Эти альтернативные сценарии не требуют никаких действий или входных данных от пользователя, кроме первоначального посещения вредоносного сайта.
Использование HTTPS не предотвращает атаку CSRF. Вредоносный сайт может отправлять https://www.good-banking-site.example.com/ запрос так же легко, как он может отправлять небезопасный запрос.
Некоторые атаки предназначены для конечных точек, реагирующих на запросы GET, в этом случае тег изображения можно использовать для выполнения действия. Эта форма атаки распространена на сайтах форума, которые разрешают изображения, но блокируют JavaScript. Приложения, изменяющие состояние запросов GET, в которых переменные или ресурсы изменяются, уязвимы для вредоносных атак. Запросы GET, изменяющие состояние, небезопасны. Рекомендуется никогда не изменять состояние запроса GET.
Атаки CSRF возможны для веб-приложений, использующих файлы cookie для проверки подлинности, так как:
- Браузеры хранят файлы cookie, выданные веб-приложением.
- Сохраненные файлы cookie включают файлы cookie сеанса для пользователей, прошедших аутентификацию.
- Браузеры отправляют все файлы cookie, связанные с доменом, в веб-приложение каждый запрос независимо от того, как был создан запрос к приложению в браузере.
Однако атаки CSRF не ограничиваются использованием файлов cookie. Например, Базовая и Дайджест-аутентификация также уязвимы. После входа пользователя с помощью базовой или дайджест-проверки подлинности браузер автоматически отправляет учетные данные до окончания сеанса.
В этом контексте сеанс ссылается на сеанс на стороне клиента, в течение которого пользователь проходит проверку подлинности. Это не связано с сеансами на стороне сервера или промежуточным ПО сеансов ASP.NET Core.
Пользователи могут защищаться от уязвимостей CSRF, принимая меры предосторожности:
- Выйдите из веб-приложений после завершения работы с ними.
- Периодически очищать файлы cookie браузера.
Однако уязвимости CSRF являются основной проблемой веб-приложения, а не конечным пользователем.
Основы проверки подлинности
Аутентификация на основе Cookie является популярной формой проверки подлинности. Системы аутентификации на основе токенов становятся всё более популярными, особенно для одностраничных приложений (SPA).
Cookie-основанная аутентификация
Когда пользователь проходит проверку подлинности с помощью имени пользователя и пароля, им выдается токен, содержащий учетный талон аутентификации. Маркер можно использовать для проверки подлинности и авторизации. Маркер хранится как cookie, который отправляется с каждым запросом клиента. Генерация и проверка этого cookie выполняются промежуточным ПО cookie аутентификации. Промежуточное ПО
Проверка подлинности на основе токенов
Когда пользователь проходит проверку подлинности, ему выдается токен (а не антифальсификационный токен). Токен содержит информацию о пользователе в виде утверждений или ссылочного токена, который указывает приложению на состояние пользователя, сохраняемое в приложении. Когда пользователь пытается получить доступ к ресурсу, требующий проверки подлинности, маркер отправляется приложению с дополнительным заголовком авторизации в виде маркера Bearer . Такой подход делает приложение бессостоя́тельным. В каждом последующем запросе маркер передается в запросе на проверку на стороне сервера. Этот маркер не шифруется; он закодирован. На сервере маркер декодируется для доступа к его информации. Чтобы отправить маркер на последующие запросы, сохраните маркер в локальном хранилище браузера. Размещение маркера в локальном хранилище браузера и его извлечение и использование в качестве маркера носителя обеспечивает защиту от атак CSRF. Однако если приложение будет уязвимо для внедрения скриптов через XSS или скомпрометированный внешний файл JavaScript, кибератакующий может получить любое значение из локального хранилища и отправить его себе. ASP.NET Core кодирует все выходные данные на стороне сервера из переменных по умолчанию, что снижает риск XSS. При изменении этого поведения с помощью Html.Raw или пользовательского кода с непроверенными входными данными можно увеличить риск XSS.
Не беспокойтесь об уязвимости CSRF, если маркер хранится в локальном хранилище браузера. CSRF является проблемой, когда токен хранится в cookie. Для получения дополнительной информации см. проблему GitHub SPA code sample adds two cookies.
Несколько приложений, размещенных в одном домене
Среды общего хостинга уязвимы для угону сессий, CSRF-атакам при входе и других атак.
Хотя example1.contoso.net и example2.contoso.net являются разными узлами, существует неявная связь доверия между узлами в домене *.contoso.net . Эта неявная связь доверия позволяет потенциально ненадежным узлам влиять на файлы cookie друг друга (политики того же источника, которые управляют запросами AJAX, не обязательно применяются к файлам cookie HTTP).
Атаки, которые используют доверенные файлы cookie между приложениями, размещенными в одном домене, можно предотвратить, не предоставляя общий доступ к доменам. Если каждое приложение размещено в собственном домене, не существует неявных cookie отношений доверия для эксплойтов.
Получение заголовков метаданных
Современные браузеры добавляют к каждому запросу заголовки запроса Fetch Metadata — прежде всего Sec-Fetch-Site.
Sec-Fetch-Site описывает связь между источником, инициирующим запрос и запрашиваемым источником: same-origin определяет запрос, сделанный сайту, а также same-sitecross-site определяет запросы, инициированные другим источником. Заголовок Origin содержит инициирующий источник и используется как запасной вариант для браузеров, появившихся до Fetch Metadata.
Sec-Fetch-Site и Originзапрещены заголовки запросов: браузер задает их, и JavaScript, работающий на странице, не может переопределить или подделать их. Это делает их надёжным сигналом для того, чтобы отличать запросы самого сайта от межсайтовых запросов без выданного сервером токена.
Автоматическая защита CSRF, встроенная в ASP.NET Core, использует этот сигнал, чтобы отклонять межсайтовые отправки форм, если они не были явно признаны доверенными.
Автоматическая защита CSRF в ASP.NET Core
ASP.NET Core включает промежуточное ПО для автоматической защиты от CSRF, которое по умолчанию включено в приложениях, созданных с помощью WebApplication.CreateBuilder. В отличие от системы защиты от подделки запросов на основе токенов, это промежуточное ПО не выдает и не проверяет токены. Вместо этого он проверяет Sec-Fetch-Site и Originзаголовки метаданных Fetch и фиксирует результат проверки запроса. Компоненты, обрабатывающие отправленные данные формы, обеспечивают соблюдение этого решения, отклоняя межсайтовые отправки форм, если они не указаны явно как доверенные.
Для большинства приложений изменения в коде не требуются: браузерные запросы из того же источника, безопасные методы HTTP и небраузерные клиенты (curl, сервер-сервер, мобильные приложения) работают без изменений. Промежуточное ПО в основном влияет на приложения, которые принимают POST-запросы форм из других источников из браузера, например сайт, который отправляет форму в API с другим источником. В этих сценариях необходимо либо настроить CORS, чтобы указать доверенный источник, либо исключить эту конечную точку.
Это ПО промежуточного слоя является дополнением к системе антифоргерии на основе токенов. Две защиты сосуществуют и могут быть активными в одной конечной точке. Сравнение случаев применения каждого из них см. в разделе "Взаимодействие с антифоргерией на основе маркеров".
Принцип работы
По каждому запросу ПО промежуточного слоя оценивает короткую цепочку правил для достижения вердикта — разрешено или запрещено. Проверки выполняются в порядке, а первый матч выигрывает:
-
Безопасные методы HTTP всегда разрешены. Запросы
GET,HEAD,OPTIONSиTRACEпроходят. Это соответствует RFC 9110 §9.2.1 и согласуется с давно установленным правилом, согласно которому конечные точки не должны изменять состояние приGET. -
Sec-Fetch-Site: same-originилиSec-Fetch-Site: noneразрешено. Современные браузеры отправляютSec-Fetch-Siteс каждым запросом.same-originохватывает обычную навигацию в приложении и получение иnoneохватывает запросы, инициированные непосредственно пользователем (ввод URL-адреса с помощью закладки). Это наиболее распространенный путь кода — наиболее допустимый трафик браузера выходит здесь. - Разрешен надежный источник из CORS. Если запрос содержит заголовок
Origin, и определённая политика CORS конечной точки доверяет этому источнику, запрос разрешается. Промежуточное ПО определяет политику так же, как и промежуточное ПО CORS: сначала — политика для конечной точки из[EnableCors("name")], затем — политика по умолчанию, зарегистрированная с помощьюAddDefaultPolicy. См. раздел «Разрешение клиентов из других источников», где описаны важные ограничения этого правила. - Любое другое
Sec-Fetch-Siteзначение запрещено. ЕслиSec-Fetch-Siteимеет значениеcross-siteилиsame-siteи источник не является доверенным через CORS, запрос отклоняется. -
Нет
Sec-Fetch-Site, ноOriginприсутствует: промежуточный слой сравниваетOriginсscheme://host[:port], построенным на основе запроса. Если они совпадают, запрос разрешен; в противном случае это отрицается. Это резервный вариант для браузеров, появившихся до спецификации Fetch Metadata (опубликованной примерно в 2020 году). - Нет ни
Sec-Fetch-Site, ниOrigin: запрос разрешён. Браузеры всегда отправляют по крайней мере один из них в запросе на запись, поэтому запрос, в котором отсутствуют оба, почти наверняка исходит от небраузерного клиента, такого какcurl, Postman, мобильное приложение или клиент server-to-server. CSRF — это вектор атак, доступный только для браузера, поэтому эти запросы передаются.
ПО промежуточного слоя записывает этот вердикт по запросу, а не завершает сам запрос. Сведения о том, как и когда отклоненный вердикт превращается в HTTP-ответ 400 Bad Request , см. в разделе "Отложенная проверка".
Отложенная проверка
ПО промежуточного слоя не отклоняет запрос самостоятельно. Вместо этого он записывает свой вердикт в свойстве запроса IAntiforgeryValidationFeature — том же свойстве, которое использует система защиты от подделки запросов на основе токенов, — где отрицательный результат записывается как недействительный. Запрос передаётся дальше по конвейеру. Недействительный вердикт становится HTTP 400 Bad Request только тогда, когда компонент, обрабатывающий данные формы, обнаруживает это. Эта отсрочка соответствует тому, как уже работает система на основе токенов: решение выносится заранее, но применяется в момент отправки формы.
Следующие компоненты считывают IAntiforgeryValidationFeature и отклоняют запрос с кодом 400 - Bad Request, если записанный вердикт недействителен:
- Действия MVC, защищенные антифоргерией.
- Конечные точки минимального API, выполняющие привязку параметра формы.
- Blazor Эндпоинты SSR.
- Любой код, который непосредственно считывает форму запроса, выступающую в качестве резервной меры.
Каждый потребитель сначала убеждается, что промежуточный компонент защиты от подделки запросов или CSRF действительно был выполнен, прежде чем доверять его вердикту, поэтому конвейер без одного из этих компонентов промежуточного слоя не приводит к ложным отклонениям.
Следствием этой модели является то, что эндпоинт, который никогда не считывает данные формы, всё равно вызывается, даже если вердикт недействителен. Например, конечная точка JSON API, которая связывает тело запроса с JSON-данными, или обработчик, который игнорирует тело запроса, не отклоняется автоматически при межсайтовом запросе. Вердикт по-прежнему записывается в IAntiforgeryValidationFeature для кода, который хочет его проверить, но ничто не обеспечивает его выполнение. CSRF — это вектор атак через формы и cookie, поэтому конечные точки, которые обычно не принимают формы, отправляемые браузером, как правило, не требуют такого отклонения. Конечные точки, которые обрабатывают формы — Razor страницы, представления MVC, Blazor SSR и привязка форм в Minimal API, — автоматически получают защиту.
Поведение по умолчанию
Промежуточное ПО автоматически регистрируется с помощью WebApplication.CreateBuilder и выполняется после аутентификации и авторизации. Он проверяет каждый запрос с помощью зарегистрированной ICsrfProtection реализации, которая по умолчанию применяет правила, описанные в разделе "Как это работает". Можно заменить реализацию по умолчанию; см. раздел "Настройка: реализация ICsrfProtection". Чтобы полностью отключить промежуточное ПО, см. Глобальное отключение.
Результатом является то, что минимальное приложение с конечной точкой обработки форм, как показано ниже, уже защищено:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapPost("/widgets", ([FromForm] Widget w) =>
Results.Created($"/widgets/{w.Id}", w));
app.Run();
Браузер, выполняющий запрос с тем же источником POST /widgets , обычно достигает конечной точки. Браузер на https://attacker.example.com, отправляющий ту же форму, получает отказ при 400 - Bad Request, когда конечная точка выполняет привязку формы, до выполнения тела обработчика. Запрос curl без Sec-Fetch-Site или Origin разрешен.
Поскольку отклонение отложено до обработчиков данных формы, конечная точка, не считывающая данные формы, — например, API JSON, получающий тело запроса из JSON, — не отклоняется автоматически даже при межсайтовом запросе. Вердикт по-прежнему записывается в запросе на код, который хочет проверить его.
Промежуточный слой интегрируется с существующим механизмом защиты от подделки запросов:
-
Минимальные API: Вызов
.DisableAntiforgery()для конечной точки исключает эту конечную точку из как ПО промежуточного слоя на основе токенов, так и ПО промежуточного слоя защиты от CSRF. Один и тот же метаданный (IAntiforgeryMetadata { RequiresValidation = false }) проверяется обоими. -
Контроллеры и действия MVC:
[IgnoreAntiforgeryToken]также исключают конечную точку из-под действия обеих мер защиты.
Разрешение клиентов из других источников
Наиболее распространённый сценарий, требующий принятия мер, — это браузерный клиент, который отправляет междоменную форму, например сайт по адресу https://app.contoso.com, отправляющий форму в API по адресу https://api.contoso.com. Такие отправки формы по умолчанию отклоняются, потому что Sec-Fetch-Site — это same-site или cross-site, а не same-origin, и обработчик формы обеспечивает выполнение этого решения с помощью 400 - Bad Request.
Промежуточное ПО CSRF не имеет собственного списка доверенных источников. Он повторно использует ту же политику CORS, которую ПО промежуточного слоя CORS определяет для конечной точки: если эта политика разрешает Origin запроса, то ПО промежуточного слоя CSRF фиксирует, что запрос разрешён.
Политика выбирается для каждой конечной точки в этом порядке:
-
[EnableCors("api")](MVC) или.RequireCors("api")(минимальный API) → именованная политика"api". - В конечном узле отсутствуют метаданные CORS → используется политика по умолчанию, зарегистрированная в
AddDefaultPolicy. - Нет соответствующей политики (именованная политика не зарегистрирована, политика по умолчанию отсутствует или
services.AddCors()ни разу не вызывался) → доверие на основе CORS отсутствует. ПО промежуточногоSec-Fetch-Siteслоя переходит к правилам origin-vs-Host.
Минимальный пример использования политики по умолчанию и минимальной конечной точки API:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddDefaultPolicy(policy =>
policy.WithOrigins("https://app.contoso.com")
.AllowAnyHeader()
.AllowAnyMethod());
});
var app = builder.Build();
app.UseCors();
app.MapPost("/widgets", ([FromForm] Widget w) =>
Results.Created($"/widgets/{w.Id}", w));
app.Run();
Для именованной политики в одной конечной точке:
app.MapPost("/widgets", ([FromForm] Widget w) => Results.Created($"/widgets/{w.Id}", w))
.RequireCors("api");
Предупреждение
AllowAnyOrigin намеренно не учитывается как сигнал доверия CSRF.
AllowAnyOrigin означает, что любой браузер может прочитать этот ресурс, а это не то же самое, что «любой источник может изменять состояние от имени пользователя». Если считать AllowAnyOrigin доверенным, это превратило бы этот промежуточный слой в пустую операцию для межисточниковых операций записи. Приложения, которым требуется политика CORS с публичным доступом на чтение в сочетании с операциями записи, защищёнными от CSRF, должны явно перечислять доверенные источники записи с помощью WithOrigins или исключать конечные точки записи, если они не используют аутентификацию на основе cookie.
[DisableCors] для конечной точки не означает отключение защиты CSRF. При этом пропускается этап проверки доверия, основанный на CORS, и запрос по-прежнему должен удовлетворять требованиям Sec-Fetch-Site и правилам сопоставления Origin и Host. Чтобы отключить защиту CSRF, см. Исключение конечной точки.
Дополнительные сведения о настройке самой технологии CORS — AddCors, AddDefaultPolicy, AddPolicy, WithOrigins и остальной части API построения политики — см. в «Включение запросов между источниками (CORS) в ASP.NET Core».
Исключение конечной точки
Если конечная точка недоступна из браузера или защищена с помощью не-cookie механизма, например токена Bearer или ключа API, исключите её отдельно, а не отключайте промежуточное ПО глобально.
Минимальные API — вызовите DisableAntiforgery для конечной точки или группы:
app.MapPost("/api/webhook", (WebhookPayload p) => Results.Accepted())
.DisableAntiforgery();
Контроллеры MVC — примените [IgnoreAntiforgeryToken] к действию или контроллеру:
[ApiController]
[Route("api/[controller]")]
[IgnoreAntiforgeryToken]
public class WebhookController : ControllerBase
{
[HttpPost]
public IActionResult Post([FromBody] WebhookPayload payload) => Accepted();
}
Любой из этих подходов добавляет IAntiforgeryMetadata { RequiresValidation = false } к эндпоинту, поэтому middleware CSRF пропускает проверку.
Предупреждение
Отключать защиту CSRF для конечной точки следует только в тех случаях, когда эта конечная точка не уязвима для атак CSRF — например, если к ней нельзя обратиться из браузера или если она защищена аутентификацией, отличной от cookie, например с помощью bearer-токенов или ключей API. Не отключите защиту CSRF на конечных точках, доступных в браузере, которые используют файлы cookie для проверки подлинности.
Отключение глобально
ПО промежуточного слоя можно отключить во всем приложении с помощью DisableCsrfProtection ключа конфигурации. Это аварийный обходной механизм — предпочтительнее отключение на уровне отдельных конечных точек.
В appsettings.json:
{
"DisableCsrfProtection": true
}
Или в качестве переменной среды:
ASPNETCORE_DisableCsrfProtection=true
Если этот ключ имеет значение true, WebApplication пропускает регистрацию промежуточного ПО в конвейере обработки. Служба остается зарегистрированной ICsrfProtection , поэтому все, что разрешает ее напрямую, продолжает работать.
Предупреждение
Автоматический промежуточный компонент CSRF также отвечает требованиям защиты от подделки запросов для конечных точек, где требуется проверка, даже если приложение не вызывает app.UseAntiforgery(). Если приложение использует антифоргери, но не вызывает app.UseAntiforgery(), то при глобальном отключении ПО промежуточного слоя CSRF или при запуске на узле, не созданном с помощью WebApplication, где это ПО промежуточного слоя не внедряется, эти конечные точки остаются без ПО промежуточного слоя антифоргери. Запрос к такой конечной точке вызывает исключение. Вызовите app.UseAntiforgery() в этой конфигурации.
Поддержка веб-браузеров
Sec-Fetch-Site поддерживается всеми текущими версиями браузеров на основе Chromium, Firefox и Safari. Сведения об авторитетной таблице совместимости см. в справочнике MDN по Sec-Fetch-Site.
Старые браузеры, появившиеся до Fetch Metadata, не отправляют Sec-Fetch-Site. Для этих клиентов промежуточное ПО в качестве резервного варианта использует сравнение заголовка Origin со схемой и хостом запроса. Браузеры уже много лет отправляли Origin в межсайтовых запросах на запись, поэтому этот запасной механизм охватывает практически весь трафик устаревших браузеров.
Небраузерные клиенты — curl Postman, мобильные приложения, системы, выполняющие межсерверные вызовы, — обычно не отправляют ни Sec-Fetch-Site, ни Origin. Эти запросы разрешены, поскольку CSRF — это вектор атаки, характерный только для браузера, который основан на том, что браузер автоматически прикрепляет учетные данные среды, такие как файлы cookie. Клиент, отличный от браузера, который хочет атаковать API, не нуждается в CSRF; он может просто вызывать API напрямую с любыми учетными данными, которыми он обладает.
Настройка: реализуйте ICsrfProtection
Логика принятия решений находится за интерфейсом одного метода:
namespace Microsoft.AspNetCore.Antiforgery;
public interface ICsrfProtection
{
ValueTask<CsrfProtectionResult> ValidateAsync(HttpContext context);
}
Чтобы заменить реализацию по умолчанию, зарегистрируйте синглтон в DI. Так как платформа использует TryAddSingleton, явный AddSingleton вызов переопределяет значение по умолчанию:
builder.Services.AddSingleton<ICsrfProtection, AllowlistCsrfProtection>();
Пользовательская реализация полезна, когда модель доверия не соответствует CORS — например, когда предпочтителен фиксированный список разрешённых источников партнёров или когда требуются более строгие правила:
using Microsoft.AspNetCore.Antiforgery;
using Microsoft.AspNetCore.Http;
public sealed class AllowlistCsrfProtection : ICsrfProtection
{
private static readonly HashSet<string> SafeMethods =
new(StringComparer.OrdinalIgnoreCase) { "GET", "HEAD", "OPTIONS", "TRACE" };
private static readonly HashSet<string> TrustedOrigins =
new(StringComparer.OrdinalIgnoreCase)
{
"https://app.contoso.com",
"https://admin.contoso.com",
};
public ValueTask<CsrfProtectionResult> ValidateAsync(HttpContext context)
{
if (SafeMethods.Contains(context.Request.Method))
{
return ValueTask.FromResult(CsrfProtectionResult.Allowed());
}
var origin = context.Request.Headers.Origin.ToString();
var allowed = !string.IsNullOrEmpty(origin) && TrustedOrigins.Contains(origin);
return ValueTask.FromResult(
allowed ? CsrfProtectionResult.Allowed() : CsrfProtectionResult.Denied());
}
}
Промежуточное ПО по-прежнему учитывает .DisableAntiforgery() / [IgnoreAntiforgeryToken] независимо от того, какая реализация зарегистрирована, — отказ от участия обрабатывается самим промежуточным ПО до вызова ValidateAsync.
Взаимодействие с антифоргерией на основе токенов
Две защиты CSRF нацелены на разные слои и предназначены для совместного использования. Они также совместно используют одну и ту же функцию запроса: оба записывают результат IAntiforgeryValidationFeatureна, и потребители формы применяют любой вердикт.
| Аспект | На основе токенов AntiforgeryMiddleware |
Промежуточное ПО для автоматической защиты от CSRF |
|---|---|---|
| Внедрен | ASP.NET Core 2.0+ | .NET 11 |
| Activation | Согласие через app.UseAntiforgery() (или неявно)AddMvc / MapRazorPages / AddRazorComponents |
Автоматически добавлено через WebApplication.CreateBuilder |
| Валидирует | Синхронизированный маркер (поле формы и cookie пара) |
Sec-Fetch-Site
/
Origin Заголовки |
| Requires | обзор защиты данных ASP.NET Core для шифрования токенов | Нет токенов, нет состояния |
| Область браузера | Все браузеры, отправляющие файлы cookie | Все современные браузеры; Origin резервный вариант для устаревших браузеров |
| Отключение для каждой конечной точки | .DisableAntiforgery() / [IgnoreAntiforgeryToken] |
Одно и то же — оба учитывают одни и те же метаданные |
ПО промежуточного слоя на основе токенов специально защищает от классического шаблона атаки CSRF, в котором вредоносный сайт активирует форму POST на уязвимом сайте с помощью внешних файлов cookie пользователя. Автоматическое ПО промежуточного слоя CSRF устраняет ту же угрозу на уровне HTTP с помощью метаданных, предоставленных браузером. Оба приложения могут быть активными в одной конечной точке, и многие приложения будут использовать защиту в глубине:
- Razor Приложения Pages, MVC и Blazor SSR, которые уже используют систему маркеров, получают проверку на основе заголовков, которая выполняется перед проверкой маркеров, не изменяя поток маркеров.
-
Приложения на Minimal API, которые выполняют привязку форм, получают полезное поведение по умолчанию без необходимости вызывать
app.UseAntiforgery()или передаватьIAntiforgeryчерез конечные точки. - API, вызываемые из кросс-доменных SPA, могут полагаться на это промежуточное ПО в сочетании со списком разрешённых источников CORS и полностью обходиться без системы токенов, если API никогда не обслуживает HTML-формы.
Автоматический компонент промежуточного ПО CSRF заменяет систему на основе токенов во многих сценариях, поскольку оба механизма защищают одни и те же конечные точки обработки форм. Сохраняйте систему на основе токенов, когда:
- Приложение должно поддерживать браузеры, которые не отправляют
Sec-Fetch-Site. См. раздел поддержки браузера. - Приложение использует IAntiforgeryAdditionalDataProvider для обхода дополнительных данных внутри маркера.
- Проверка безопасности или требование соответствия предусматривает защиту токенов в качестве независимого уровня.
Дополнительные сведения о системе, основанной на токенах, включая интеграцию форм, сценарии AJAX, настройку с помощью API AntiforgeryOptions и IAntiforgery, см. в статье Antiforgery in ASP.NET Core.
Проверка токена выполняется в первую очередь
Когда приложение вызывает app.UseAntiforgery(), промежуточное ПО на основе токенов выполняется после автоматического промежуточного ПО CSRF. Промежуточный обработчик токена очищает любой вердикт, записанный промежуточным обработчиком CSRF, и заменяет его результатом проверки токена. Результат токена считается окончательным:
- Запрос, который промежуточный компонент CSRF пометил как недействительный, становится действительным, если содержит действительный токен.
- Запрос, пропущенный промежуточным ПО CSRF, помечается как недействительный, если его токен отсутствует или недействителен.
Это упорядочивание означает, что приложения, использующие систему маркеров, видят то же комплексное поведение, которое они имели до существования автоматического ПО промежуточного слоя, а приложения, которые не используют маркеры, возвращаются к вердикту ПО промежуточного слоя CSRF.
Blazor статический рендеринг на стороне сервера
Blazor эндпоинты статического серверного рендеринга (SSR) участвуют в той же модели отложенной обработки. Конечная точка Components Razor доверяет вердикту, записанному на IAntiforgeryValidationFeature вышестоящим промежуточным ПО, и возвращает 400 - Bad Request для отправки формы только в том случае, если этот вердикт недействителен. Конечная точка больше не проверяет сам запрос.
Поведение зависит от того, какое ПО промежуточного слоя выполняется:
- Приложения, которые вызывают
app.UseAntiforgery(), остаются без изменений. Промежуточное ПО, использующее токены, проверяет каждый запрос, а токены защиты от подделки запросов генерируются для отображаемых форм, как и раньше. - Приложения, которые не вызывают
app.UseAntiforgery(), вместо этого защищаются автоматическим промежуточным ПО CSRF. В этой конфигурации конечный узел пропускает генерацию токена защиты от подделки запроса, поскольку отсутствует компонент middleware, который мог бы проверить этот токен в последующем запросе.
Это изменение поведения статического SSR, который ранее удалял app.UseAntiforgery(): теперь они защищены промежуточным ПО CSRF, а не остаются незащищёнными, и перестают генерировать токены защиты от подделки запросов. Инструкции по миграции см. в разделе "Миграция с ASP.NET Core" в .NET 10 на ASP.NET Core .NET 11. Формальное уведомление о критическом изменении см. в разделе Blazor рендеринг на стороне сервера откладывает проверку защиты от подделки запросов до промежуточного ПО.
Troubleshooting
Симптом: Запросы с одинаковыми источниками из браузера успешно выполнены, но записи формы между источниками возвращаются 400 - Bad Request без текста.
Причина: Промежуточный компонент CSRF зафиксировал недопустимое решение для межсайтового запроса, а компонент обработки форм — например, действие MVC, привязка формы в Minimal API или Blazor отправка формы SSR — применил это решение с помощью 400 - Bad Request. Это ожидаемое поведение по умолчанию для конечных точек, обрабатывающих формы.
Разрешение: Выберите один из следующих вариантов в зависимости от сценария:
- Если вызывающий источник известен и доверен, разрешите его через CORS.
- Если конечная точка недоступна из браузера или не использует проверку подлинности cookie, исключите её с помощью
.DisableAntiforgery()или[IgnoreAntiforgeryToken]. - Если для всего приложения нужно отключить эту возможность (например, в период миграции), отключите на глобальном уровне.
Диагностика: Промежуточное ПО регистрирует каждый недопустимый вердикт на уровне Debug в категории Microsoft.AspNetCore.Antiforgery.CsrfProtectionMiddleware с именем события CsrfValidationFailed. Включите Debug журналирование для этой категории в appsettings.Development.json:
{
"Logging": {
"LogLevel": {
"Microsoft.AspNetCore.Antiforgery.CsrfProtectionMiddleware": "Debug"
}
}
}
Записанный вердикт отображается в журнале следующим образом:
dbug: Microsoft.AspNetCore.Antiforgery.CsrfProtectionMiddleware[1]
Cross-origin CSRF protection marked request POST /widgets from origin 'https://attacker.example.com' as invalid.
Локальное воспроизведение: Используйте curl с явным заголовком Origin для имитации межсайтового запроса браузера к конечной точке формы:
curl -i -X POST https://localhost:{PORT}/widgets \
-H "Origin: https://attacker.example.com" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "name=test"
Замените {PORT} локальным портом HTTPS приложения.
400 - Bad Request наблюдается, поскольку эндпоинт выполняет привязку формы, что обеспечивает выполнение зафиксированного вердикта. Эндпоинт, не связанный с формой, возвращает свой обычный ответ, поскольку никто не считывает вердикт. Без заголовка Origin тот же запрос разрешается, поскольку curl также не отправляет Sec-Fetch-Site, а запрос без обоих заголовков рассматривается как запрос от клиента, не являющегося браузером.
Система защиты от подделки на основе токенов, описанная в остальной части статьи, появилась раньше этого ПО промежуточного слоя и остается доступной. Для большинства приложений достаточно одной лишь автоматической защиты. Инструкции по поддержанию системы на основе токенов и способах миграции см. в разделе "Миграция с ASP.NET Core" в .NET 10 до ASP.NET Core в .NET 11.
Защита от подделок в ASP.NET Core
Предупреждение
ASP.NET Core реализует антифоргерию с помощью ASP.NET Core Data Protection. Стек защиты данных должен быть настроен для работы в ферме серверов. Дополнительные сведения см. в разделе "Настройка защиты данных".
Промежуточное программное обеспечение для защиты от подделок добавляется в контейнер внедрения зависимостей, если вызывается один из следующих API:
Дополнительные сведения см. в разделе Антифальсификация в минимальных API.
FormTagHelper вставляет маркеры защиты от подделки в элементы HTML-форм. Следующий тег в Razor файле автоматически создает антифальсификационные токены:
<form method="post">
<!-- ... -->
</form>
Аналогичным образом IHtmlHelper.BeginForm создаёт маркеры антифальсификации по умолчанию, если метод формы не является GET.
Автоматическое создание маркеров антиподделки для элементов формы HTML происходит, когда <form> тег содержит method="post" атрибут, и выполняется любое из следующих условий:
- Атрибут действия пуст (
action=""). - Атрибут действия не предоставляется (
<form method="post">).
Автоматическое создание маркеров антифоргерии для элементов формы HTML можно отключить:
Явно отключите антифальсификационные маркеры с помощью атрибута
asp-antiforgery.<form method="post" asp-antiforgery="false"> <!-- ... --> </form>Элемент формы исключен из вспомогательных тегов, используя символ выхода из тегов !.
<!form method="post"> <!-- ... --> </!form>Удалите
FormTagHelperиз представления.FormTagHelperможно удалить из представления, добавив следующую директиву в представление Razor.@removeTagHelper Microsoft.AspNetCore.Mvc.TagHelpers.FormTagHelper, Microsoft.AspNetCore.Mvc.TagHelpers
Примечание.
Razor Страницы автоматически защищены от XSRF/CSRF. Дополнительные сведения см. в разделе XSRF/CSRF и Razor Pages.
Наиболее распространенный подход к защите от атак CSRF — использовать шаблон токена синхронизатора (STP). STP используется, когда пользователь запрашивает страницу с данными формы:
- Сервер отправляет маркер, связанный с удостоверением текущего пользователя клиенту.
- Клиент отправляет маркер на сервер для проверки.
- Если сервер получает маркер, который не соответствует удостоверению пользователя, прошедшего проверку подлинности, запрос отклоняется.
Токен является уникальным и непредсказуемым. Маркер также можно использовать для обеспечения правильной последовательности запросов (например, обеспечения последовательности запросов: страницы 1 > страницы 2 > страницы 3). Все формы в ASP.NET шаблонах Core MVC и Razor Pages создают маркеры защиты от подделки. Следующая пара примеров представления создает маркеры антифоргерии:
<form asp-action="Index" asp-controller="Home" method="post">
<!-- ... -->
</form>
@using (Html.BeginForm("Index", "Home"))
{
<!-- ... -->
}
Явно добавьте токен антиподделки в элемент <form> без использования вспомогателей тегов с HTML-вспомогателем @Html.AntiForgeryToken.
<form asp-action="Index" asp-controller="Home" method="post">
@Html.AntiForgeryToken()
<!-- ... -->
</form>
В каждом из предыдущих случаев ASP.NET Core добавляет скрытое поле формы, аналогичное следующему примеру:
<input name="__RequestVerificationToken" type="hidden" value="CfDJ8NrAkS ... s2-m9Yw">
ASP.NET Core включает три фильтра для работы с маркерами защиты от подделки:
Защита от подделок с AddControllers
Вызов AddControllersне включает маркеры защиты от подделки. AddControllersWithViews должен быть вызван для включения встроенной поддержки маркеров защиты от подделки.
Несколько вкладок браузера и шаблон токена синхронизатора
Несколько вкладок, вошедших в систему как разные пользователи, или одна, вошедшая в систему как анонимный пользователь, не поддерживаются.
Настройка защиты от подделки с помощью AntiforgeryOptions
Настройте AntiforgeryOptions в файле приложения Program :
builder.Services.AddAntiforgery(options =>
{
// Set Cookie properties using CookieBuilder properties†.
options.FormFieldName = "AntiforgeryFieldname";
options.HeaderName = "X-CSRF-TOKEN-HEADERNAME";
options.SuppressXFrameOptionsHeader = false;
});
Установите свойства антиподделки cookie, используя свойства класса CookieBuilder, как показано в следующей таблице.
| Вариант | Описание |
|---|---|
| Cookie | Определяет параметры, используемые для создания файлов cookie антивзломной защиты. |
| FormFieldName | Имя скрытого поля формы, используемого системой защиты от подделки для отображения токенов в представлениях. |
| HeaderName | Имя заголовка, используемого антифоргерской системой. Если nullсистема рассматривает только данные формы. |
| SuppressXFrameOptionsHeader | Указывает, следует ли подавлять создание заголовка X-Frame-Options . По умолчанию заголовок создается со значением "SAMEORIGIN". По умолчанию — false. |
Некоторые браузеры не разрешают небезопасным конечным точкам устанавливать файлы cookie с флагом "безопасный" или перезаписывать файлы cookie, флаг безопасности которых установлен (дополнительные сведения см. в разделе "Нерекомендуемые изменения" файлов cookie из небезопасных источников). Так как сочетание безопасных и небезопасных конечных точек является общим сценарием в приложениях, ASP.NET Core смягчает ограничение на безопасную политику для некоторых файлов cookie, таких как antiforgery cookie, установив свойство cookie элемента SecurePolicy на CookieSecurePolicy.None. Даже если злоумышленник украдет маркер антифоргерии cookie, он также должен украсть сам маркер, который обычно отправляется через поле формы (более распространенное) или отдельный заголовок запроса (менее распространенный), а также маркер проверки подлинности cookie.
Cookies для проверки подлинности или авторизации используется более надежная политика, чем CookieSecurePolicy.None.
Кроме того, вы можете защитить механизм защиты от подделки cookie в средах, которые отличаются от Development, по протоколу HTTPS с использованием SSL, с помощью установки следующего параметра свойства в файле приложения AntiforgeryOptions.Cookie:
if (!builder.Environment.IsDevelopment())
{
builder.Services.AddAntiforgery(o =>
{
o.Cookie.SecurePolicy = CookieSecurePolicy.Always;
});
}
Дополнительные сведения см. в разделе CookieAuthenticationOptions.
Генерация маркеров защиты от подделки с помощью IAntiforgery
IAntiforgery предоставляет API для настройки функций антифоргерии.
IAntiforgery можно запросить Program.cs с помощью WebApplication.Services. В следующем примере используется промежуточное ПО (middleware) на главной странице приложения для создания маркера защиты от подделки и отправки его в ответ в виде cookie:
app.UseRouting();
app.UseAuthorization();
var antiforgery = app.Services.GetRequiredService<IAntiforgery>();
app.Use((context, next) =>
{
var requestPath = context.Request.Path.Value;
if (string.Equals(requestPath, "/", StringComparison.OrdinalIgnoreCase)
|| string.Equals(requestPath, "/index.html", StringComparison.OrdinalIgnoreCase))
{
var tokenSet = antiforgery.GetAndStoreTokens(context);
context.Response.Cookies.Append("XSRF-TOKEN", tokenSet.RequestToken!,
new CookieOptions { HttpOnly = false });
}
return next(context);
});
В предыдущем примере задается cookie, называемый XSRF-TOKEN. Клиент может прочитать это cookie и указать его значение в качестве заголовка, присоединенного к запросам AJAX. Например, Angular включает встроенную защиту XSRF, которая по умолчанию считывает cookie с именем cookieXSRF-TOKEN.
Требовать антифальсификационной проверки
Фильтр действий ValidateAntiForgeryToken можно применить к отдельному действию, контроллеру или глобально. Запросы, сделанные к действиям, к которым применяется этот фильтр, блокируются, если запрос не включает допустимый маркер антифоргерии.
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Index()
{
// ...
return RedirectToAction();
}
Атрибут ValidateAntiForgeryToken требует маркер для всех запросов к методам действия, которые он отмечает, включая запросы HTTP GET. Если атрибут ValidateAntiForgeryToken применяется ко всем контроллерам приложения, его можно переопределить с помощью атрибута IgnoreAntiforgeryToken.
Автоматическая проверка маркеров защиты от подделки только для небезопасных методов HTTP
Вместо широкого применения атрибута ValidateAntiForgeryToken и переопределения его атрибутами IgnoreAntiforgeryTokenможно использовать атрибут AutoValidateAntiforgeryToken . Этот атрибут работает идентично атрибуту ValidateAntiForgeryToken , за исключением того, что он не требует маркеров для запросов, выполненных с помощью следующих методов HTTP:
- ПОЛУЧИТЬ
- Заголовок
- ПАРАМЕТРЫ
- ТРАССИРОВКА
Рекомендуется использовать AutoValidateAntiforgeryToken широко для сценариев, отличных от API. Этот атрибут гарантирует, что действия POST защищены по умолчанию. Альтернативой является игнорирование маркеров антифоргерии по умолчанию, если ValidateAntiForgeryToken не применяется к отдельным методам действия. Скорее всего, в этом сценарии метод действия POST остается незащищенным по ошибке, оставляя приложение уязвимым к атакам CSRF. Все запросы POST должны отправлять антифорджери-токен.
API не имеют автоматического механизма для отправки той части токена, которая не является cookie. Реализация, вероятно, зависит от реализации клиентского кода. Ниже показаны некоторые примеры:
Пример уровня класса:
[AutoValidateAntiforgeryToken]
public class HomeController : Controller
Глобальный пример:
builder.Services.AddControllersWithViews(options =>
{
options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute());
});
Переопределение глобальных атрибутов или атрибутов защиты от подделки в контроллере
Фильтр IgnoreAntiforgeryToken используется для устранения необходимости в токене защиты от подделки для данного действия (или контроллера). При применении этот фильтр переопределяет фильтры ValidateAntiForgeryToken и AutoValidateAntiforgeryToken, указанные на более высоком уровне (глобально или на контроллере).
[IgnoreAntiforgeryToken]
public IActionResult IndexOverride()
{
// ...
return RedirectToAction();
}
Обновление токенов после аутентификации
Маркеры должны обновляться после проверки подлинности пользователя, перенаправляя пользователя на страницу представления или Razor страницы.
JavaScript, AJAX и SPA
В традиционных приложениях на основе HTML маркеры защиты от подмен передаются серверу с помощью скрытых полей формы. В современных приложениях и spAs на основе JavaScript многие запросы выполняются программными средствами. Эти запросы AJAX могут использовать другие методы, такие как заголовки запросов или cookies, для передачи токена.
Если файлы cookie используются для хранения маркеров проверки подлинности и проверки подлинности запросов API на сервере, CSRF является потенциальной проблемой. Если локальное хранилище используется для хранения маркера, уязвимость CSRF может быть устранена, так как значения из локального хранилища не отправляются автоматически на сервер с каждым запросом. Использование локального хранилища для хранения маркера защиты от подделки на клиенте и отправка маркера в качестве заголовка запроса рекомендуется.
Blazor
Для получения дополнительной информации см. раздел ASP.NET Core Blazor аутентификация и авторизация.
JavaScript
Используя JavaScript в представлениях, маркер можно создать через службу непосредственно в представлении. Внедрите службу IAntiforgery в представление и вызовите GetAndStoreTokens.
@inject Microsoft.AspNetCore.Antiforgery.IAntiforgery Antiforgery
@{
ViewData["Title"] = "JavaScript";
var requestToken = Antiforgery.GetAndStoreTokens(Context).RequestToken;
}
<input id="RequestVerificationToken" type="hidden" value="@requestToken" />
<button id="button" class="btn btn-primary">Submit with Token</button>
<div id="result" class="mt-2"></div>
@section Scripts {
<script>
document.addEventListener("DOMContentLoaded", () => {
const resultElement = document.getElementById("result");
document.getElementById("button").addEventListener("click", async () => {
const response = await fetch("@Url.Action("FetchEndpoint")", {
method: "POST",
headers: {
RequestVerificationToken:
document.getElementById("RequestVerificationToken").value
}
});
if (response.ok) {
resultElement.innerText = await response.text();
} else {
resultElement.innerText = `Request Failed: ${response.status}`
}
});
});
</script>
}
В предыдущем примере используется JavaScript для чтения значения скрытого поля для заголовка AJAX POST.
Этот подход устраняет необходимость непосредственной настройки файлов cookie с сервера или их чтения от клиента. Однако, если внедрение службы IAntiforgery невозможно, используйте JavaScript для доступа к маркерам в файлах cookie.
- Маркеры доступа в дополнительном запросе к серверу обычно
same-origin. - Используйте содержимое cookie, чтобы создать заголовок со значением токена.
Если скрипт отправляет маркер в заголовке запроса X-XSRF-TOKEN, настройте службу защиты от подделки для поиска заголовка X-XSRF-TOKEN :
builder.Services.AddAntiforgery(options => options.HeaderName = "X-XSRF-TOKEN");
В следующем примере добавляется защищенный конечный пункт, который записывает токен запроса в элемент cookie, доступный для считывания JavaScript.
app.UseAuthorization();
app.MapGet("antiforgery/token", (IAntiforgery forgeryService, HttpContext context) =>
{
var tokens = forgeryService.GetAndStoreTokens(context);
context.Response.Cookies.Append("XSRF-TOKEN", tokens.RequestToken!,
new CookieOptions { HttpOnly = false });
return Results.Ok();
}).RequireAuthorization();
В следующем примере JavaScript используется для выполнения запроса AJAX для получения маркера и выполнения другого запроса с соответствующим заголовком:
var response = await fetch("/antiforgery/token", {
method: "GET",
headers: { "Authorization": authorizationToken }
});
if (response.ok) {
// https://developer.mozilla.org/docs/web/api/document/cookie
const xsrfToken = document.cookie
.split("; ")
.find(row => row.startsWith("XSRF-TOKEN="))
.split("=")[1];
response = await fetch("/JavaScript/FetchEndpoint", {
method: "POST",
headers: { "X-XSRF-TOKEN": xsrfToken, "Authorization": authorizationToken }
});
if (response.ok) {
resultElement.innerText = await response.text();
} else {
resultElement.innerText = `Request Failed: ${response.status}`
}
} else {
resultElement.innerText = `Request Failed: ${response.status}`
}
Примечание.
Если антифальсификационный маркер указан как в заголовке запроса, так и в полезных данных формы, проверяется только маркер в заголовке.
Антифальсификация с минимальными интерфейсами API
Вызовите AddAntiforgery и UseAntiforgery(IApplicationBuilder), чтобы зарегистрировать службы защиты от подделки в DI. Маркеры антиподделки используются для предотвращения межсайтовых подделок запросов.
var builder = WebApplication.CreateBuilder();
builder.Services.AddAntiforgery();
var app = builder.Build();
app.UseAntiforgery();
app.MapGet("/", () => "Hello World!");
app.Run();
Промежуточное программное обеспечение для защиты от подделок:
- Прерывает ли выполнение оставшейся части конвейера запроса, если не.
- Задает IAntiforgeryValidationFeature в HttpContext.Features текущего запроса.
Токен антифальсификации проверяется только в том случае, если:
- Конечная точка содержит метаданные, реализующие IAntiforgeryMetadata, где
RequiresValidation=true. - Метод HTTP, связанный с конечной точкой, является соответствующим методом HTTP типа POST, PUT или PATCH.
- Запрос связан с допустимой конечной точкой.
Промежуточное ПО для защиты от подделки запросов не прерывает конвейер обработки запросов. Код конечной точки всегда выполняется, даже если проверка токена не удается. Чтобы проверить результат проверки маркера, устраните IAntiforgeryValidationFeature из HttpContext.Features и проверьте его свойство IsValid или свойство Error для получения сведений о сбое. Этот подход полезен, если конечные точки требуют настраиваемой обработки для неудачной проверки антифальсификации.
Примечание. При ручном включении промежуточное ПО для защиты от подделки должно выполняться после промежуточного ПО для проверки подлинности и авторизации, чтобы предотвратить чтение данных формы, если пользователь не аутентифицирован.
По умолчанию минимальные API, принимающие данные формы, требуют проверки токенов защиты от подделки и завершаются сбоем до выполнения кода приложения, если проверка токенов защиты от подделки не была успешной.
Рассмотрим следующий GenerateForm метод:
public static string GenerateForm(string action,
AntiforgeryTokenSet token, bool UseToken=true)
{
string tokenInput = "";
if (UseToken)
{
tokenInput = $@"<input name=""{token.FormFieldName}""
type=""hidden"" value=""{token.RequestToken}"" />";
}
return $@"
<html><body>
<form action=""{action}"" method=""POST"" enctype=""multipart/form-data"">
{tokenInput}
<input type=""text"" name=""name"" />
<input type=""date"" name=""dueDate"" />
<input type=""checkbox"" name=""isCompleted"" />
<input type=""submit"" />
</form>
</body></html>
";
}
Предыдущий код содержит три аргумента: действие, антифальсификационный маркер и bool, указывающий, следует ли использовать маркер.
Рассмотрим следующий пример:
using Microsoft.AspNetCore.Antiforgery;
using Microsoft.AspNetCore.Mvc;
var builder = WebApplication.CreateBuilder();
builder.Services.AddAntiforgery();
var app = builder.Build();
app.UseAntiforgery();
// Pass token
app.MapGet("/", (HttpContext context, IAntiforgery antiforgery) =>
{
var token = antiforgery.GetAndStoreTokens(context);
return Results.Content(MyHtml.GenerateForm("/todo", token), "text/html");
});
// Don't pass a token, fails
app.MapGet("/SkipToken", (HttpContext context, IAntiforgery antiforgery) =>
{
var token = antiforgery.GetAndStoreTokens(context);
return Results.Content(MyHtml.GenerateForm("/todo",token, false ), "text/html");
});
// Post to /todo2. DisableAntiforgery on that endpoint so no token needed.
app.MapGet("/DisableAntiforgery", (HttpContext context, IAntiforgery antiforgery) =>
{
var token = antiforgery.GetAndStoreTokens(context);
return Results.Content(MyHtml.GenerateForm("/todo2", token, false), "text/html");
});
app.MapPost("/todo", ([FromForm] Todo todo) => Results.Ok(todo));
app.MapPost("/todo2", ([FromForm] Todo todo) => Results.Ok(todo))
.DisableAntiforgery();
app.Run();
class Todo
{
public required string Name { get; set; }
public bool IsCompleted { get; set; }
public DateTime DueDate { get; set; }
}
public static class MyHtml
{
public static string GenerateForm(string action,
AntiforgeryTokenSet token, bool UseToken=true)
{
string tokenInput = "";
if (UseToken)
{
tokenInput = $@"<input name=""{token.FormFieldName}""
type=""hidden"" value=""{token.RequestToken}"" />";
}
return $@"
<html><body>
<form action=""{action}"" method=""POST"" enctype=""multipart/form-data"">
{tokenInput}
<input type=""text"" name=""name"" />
<input type=""date"" name=""dueDate"" />
<input type=""checkbox"" name=""isCompleted"" />
<input type=""submit"" />
</form>
</body></html>
";
}
}
В приведенном выше коде данные отправляются в:
-
/todoтребует допустимого маркера защиты от подделки. -
/todo2Не нужен действительный токен защиты от подделки, так как DisableAntiforgery вызывается.
app.MapPost("/todo", ([FromForm] Todo todo) => Results.Ok(todo));
app.MapPost("/todo2", ([FromForm] Todo todo) => Results.Ok(todo))
.DisableAntiforgery();
Предупреждение
Вызов .DisableAntiforgery() отключает защиту от межсайтовой подделки запросов (CSRF) для конечной точки. Это следует использовать только в том случае, если конечная точка не уязвима для атак CSRF, например:
- Конечные точки, которые не вызываются из браузера (например, внутренние API)
- Конечные точки, защищенные с использованием не-cookie аутентификации (например, токены носителя или API-ключи)
- Внутренние или инфраструктурные конечные точки, которые не зависят от файлов cookie пользователя
Не отключайте проверку на подделку для конечных точек, к которым имеется доступ из браузера и которые используют файлы cookie для аутентификации или обрабатывают данные, отправленные пользователями через формы, так как это подвергает ваше приложение атакам CSRF.
POST-запрос к:
-
/todoиз формы, созданной конечной/точкой, успешно проходит, так как токен защиты от подделки действителен. -
/todoиз формы, созданной/SkipToken, не удается, потому что механизм защиты от подделки не включён. -
/todo2из формы, созданной конечной/DisableAntiforgery, завершается успешно, так как антифальсификационная защита не требуется.
app.MapPost("/todo", ([FromForm] Todo todo) => Results.Ok(todo));
app.MapPost("/todo2", ([FromForm] Todo todo) => Results.Ok(todo))
.DisableAntiforgery();
При отправке формы без действительного маркера антифальсификации:
- В среде
Developmentвыбрасывается исключение. - В среде
Productionрегистрируется сообщение.
Ограничения метода HTTP и взаимодействие с HttpMethodOverrideMiddleware
Для варианта защиты от подделки запросов на основе ПО промежуточного слоя AntiforgeryMiddleware и UseAntiforgery() проверяют токены защиты от подделки только для HTTP-запросов POST, PUT и PATCH. Другие методы HTTP, такие как DELETE, не проверяются автоматически.
Чтобы проверять токены защиты от подделки запросов для других методов HTTP, получите IAntiforgery из DI и явно вызовите ValidateRequestAsync или IsRequestValidAsync:
app.MapDelete("/item/{id}", async (int id, IAntiforgery antiforgery, HttpContext context) =>
{
await antiforgery.ValidateRequestAsync(context);
// Process the DELETE request
});
Предупреждение
Когда HttpMethodOverrideMiddleware настроен с использованием FormFieldName (режим поля формы) и размещён перед AntiforgeryMiddleware, POST-запрос можно переопределить как DELETE (или другой непроверяемый метод). Так как AntiforgeryMiddleware проверяет только POST, PUT и PATCH, переопределенный запрос проходит проверку антифоргерии.
Чтобы защитить эти конечные точки, выполните следующие действия.
- Предпочтительно размещать
HttpMethodOverrideMiddlewareпосле проверки подлинности запроса, если это позволяет конвейер обработки. - Избегайте переопределения значений полей формы для конечных точек, использующих проверку антиподделки.
- Если переопределение поля формы должно выполняться сначала, проверьте маркер антифоргерии явным образом с помощью
IAntiforgery.ValidateRequestAsync.
Сведения о настройке см. в разделе ПО промежуточной обработки ASP.NET Core.
файлы cookie аутентификации Windows и защиты от подделки
При использовании проверки подлинности Windows конечные точки приложений должны быть защищены от атак CSRF так же, как и для файлов cookie. Браузер неявно отправляет контекст проверки подлинности серверу и конечным точкам, которые необходимо защитить от атак CSRF.
Расширить защиту от подделок
Тип IAntiforgeryAdditionalDataProvider позволяет разработчикам расширить поведение системы защиты от CSRF путем обхода дополнительных данных в каждом токене. Метод GetAdditionalData вызывается каждый раз при создании маркера поля, а возвращаемое значение внедрено в созданный маркер. Реализующий может возвращать метку времени, nonce или любое другое значение, а затем вызывать ValidateAdditionalData для проверки этих данных при проверке этого токена. Имя пользователя клиента уже внедрено в созданные маркеры, поэтому не нужно включать эти сведения. Если в маркере содержатся дополнительные данные, но IAntiForgeryAdditionalDataProvider не настроен, то дополнительные данные не проверяются.
Дополнительные ресурсы
Межсайтовая подделка запросов (также известная как XSRF или CSRF) — это атака на веб-приложения, посредством которых вредоносное веб-приложение может влиять на взаимодействие между клиентским браузером и веб-приложением, которое доверяет этому браузеру. Эти атаки возможны, так как веб-браузеры автоматически отправляют некоторые типы маркеров проверки подлинности с каждым запросом на веб-сайт. Эта форма эксплойта также называется атакой одним щелчком или сеансовым угоном, так как атака использует прошедший аутентификацию сеанс пользователя.
Пример атаки CSRF:
Пользователь входит в
www.good-banking-site.example.comсистему с помощью проверки подлинности форм. Сервер выполняет проверку подлинности пользователя и выдает ответ, содержащий проверку подлинности cookie. Сайт уязвим к атакам, поскольку сайт доверяет любому полученному запросу с допустимой аутентификацией cookie.Пользователь посещает вредоносный сайт.
www.bad-crook-site.example.comВредоносный сайт
www.bad-crook-site.example.comсодержит HTML-форму, аналогичную следующему примеру:<h1>Congratulations! You're a Winner!</h1> <form action="https://www.good-banking-site.example.com/api/account" method="post"> <input type="hidden" name="Transaction" value="withdraw" /> <input type="hidden" name="Amount" value="1000000" /> <input type="submit" value="Click to collect your prize!" /> </form>Обратите внимание, что отправка формы
actionпроисходит на уязвимый сайт, а не на вредоносный сайт. Это "межсайтовая" часть CSRF.Пользователь выбирает кнопку отправки. Браузер выполняет запрос и автоматически включает проверку подлинности cookie для запрошенного домена
www.good-banking-site.example.com.Запрос выполняется на сервере
www.good-banking-site.example.comс контекстом проверки подлинности пользователя и может выполнять любое действие, которое разрешено выполнить пользователю, прошедшему проверку подлинности.
Помимо сценария, когда пользователь выбирает кнопку для отправки формы, вредоносный сайт может:
- Запустите скрипт, который автоматически отправляет форму.
- Отправьте отправку формы в виде запроса AJAX.
- Скрытие формы с помощью CSS.
Эти альтернативные сценарии не требуют никаких действий или входных данных от пользователя, кроме первоначального посещения вредоносного сайта.
Использование HTTPS не предотвращает атаку CSRF. Вредоносный сайт может отправлять https://www.good-banking-site.example.com/ запрос так же легко, как он может отправлять небезопасный запрос.
Некоторые атаки предназначены для конечных точек, реагирующих на запросы GET, в этом случае тег изображения можно использовать для выполнения действия. Эта форма атаки распространена на сайтах форума, которые разрешают изображения, но блокируют JavaScript. Приложения, изменяющие состояние запросов GET, в которых переменные или ресурсы изменяются, уязвимы для вредоносных атак. Запросы GET, изменяющие состояние, небезопасны. Рекомендуется никогда не изменять состояние запроса GET.
Атаки CSRF возможны для веб-приложений, использующих файлы cookie для проверки подлинности, так как:
- Браузеры хранят файлы cookie, выданные веб-приложением.
- Сохраненные файлы cookie включают файлы cookie сеанса для пользователей, прошедших аутентификацию.
- Браузеры отправляют все файлы cookie, связанные с доменом, в веб-приложение каждый запрос независимо от того, как был создан запрос к приложению в браузере.
Однако атаки CSRF не ограничиваются использованием файлов cookie. Например, Базовая и Дайджест-аутентификация также уязвимы. После входа пользователя с помощью базовой или дайджест-проверки подлинности браузер автоматически отправляет учетные данные до окончания сеанса.
В этом контексте сеанс ссылается на сеанс на стороне клиента, в течение которого пользователь проходит проверку подлинности. Это не связано с сеансами на стороне сервера или промежуточным ПО сеансов ASP.NET Core.
Пользователи могут защищаться от уязвимостей CSRF, принимая меры предосторожности:
- Выйдите из веб-приложений после завершения работы с ними.
- Периодически очищать файлы cookie браузера.
Однако уязвимости CSRF являются основной проблемой веб-приложения, а не конечным пользователем.
Основы проверки подлинности
Аутентификация на основе Cookie является популярной формой проверки подлинности. Системы аутентификации на основе токенов становятся всё более популярными, особенно для одностраничных приложений (SPA).
Cookie-основанная аутентификация
Когда пользователь проходит аутентификацию с помощью имени пользователя и пароля, ему выдается токен, содержащий аутентификационный билет, который используется для аутентификации и авторизации. Маркер хранится как cookie, который отправляется с каждым запросом клиента. Создание и проверка этого cookie выполняются промежуточным ПО cookie аутентификации. Промежуточное ПО
Проверка подлинности на основе токенов
Когда пользователь проходит проверку подлинности, ему выдается токен (а не антифальсификационный токен). Токен содержит информацию о пользователе в виде утверждений или ссылочного токена, который указывает приложению на состояние пользователя, сохраняемое в приложении. Когда пользователь пытается получить доступ к ресурсу, требующий проверки подлинности, маркер отправляется приложению с дополнительным заголовком авторизации в виде маркера Bearer . Такой подход делает приложение бессостоя́тельным. В каждом последующем запросе маркер передается в запросе на проверку на стороне сервера. Этот маркер не шифруется; он закодирован. На сервере маркер декодируется для доступа к его информации. Чтобы отправить маркер на последующие запросы, сохраните маркер в локальном хранилище браузера. Размещение маркера в локальном хранилище браузера и его извлечение и использование в качестве маркера носителя обеспечивает защиту от атак CSRF. Тем не менее, если приложение будет уязвимо для внедрения скриптов через XSS или скомпрометированный внешний файл javascript, кибератакующий сможет извлечь любое значение из локального хранилища и отправить его себе. ASP.NET Core кодирует все выходные данные на стороне сервера из переменных по умолчанию, что снижает риск XSS. При изменении этого поведения с помощью Html.Raw или пользовательского кода с непроверенными входными данными можно увеличить риск XSS.
Не беспокойтесь об уязвимости CSRF, если маркер хранится в локальном хранилище браузера. CSRF является проблемой, когда токен хранится в cookie. Для получения дополнительной информации см. проблему GitHub SPA code sample adds two cookies.
Несколько приложений, размещенных в одном домене
Среды общего размещения уязвимы к перехвату сеанса, CSRF-атакам при входе и другим видам атак.
Хотя example1.contoso.net и example2.contoso.net являются разными узлами, существует неявная связь доверия между узлами в домене *.contoso.net . Эта неявная связь доверия позволяет потенциально ненадежным узлам влиять на файлы cookie друг друга (политики того же источника, которые управляют запросами AJAX, не обязательно применяются к файлам cookie HTTP).
Атаки, которые используют доверенные файлы cookie между приложениями, размещенными в одном домене, можно предотвратить, не предоставляя общий доступ к доменам. Если каждое приложение размещено в собственном домене, не существует неявных cookie отношений доверия для эксплойтов.
Защита от подделок в ASP.NET Core
Предупреждение
ASP.NET Core реализует антифоргерию с помощью ASP.NET Core Data Protection. Стек защиты данных должен быть настроен для работы в ферме серверов. Дополнительные сведения см. в разделе "Настройка защиты данных".
Промежуточное программное обеспечение для защиты от подделок добавляется в контейнер внедрения зависимостей, если вызывается один из следующих API:
FormTagHelper вставляет маркеры защиты от подделки в элементы HTML-форм. Следующий тег в Razor файле автоматически создает антифальсификационные токены:
<form method="post">
<!-- ... -->
</form>
Аналогичным образом IHtmlHelper.BeginForm создаёт маркеры антифальсификации по умолчанию, если метод формы не является GET.
Автоматическое создание маркеров антиподделки для элементов формы HTML происходит, когда <form> тег содержит method="post" атрибут, и выполняется любое из следующих условий:
- Атрибут действия пуст (
action=""). - Атрибут действия не предоставляется (
<form method="post">).
Автоматическое создание маркеров антифоргерии для элементов формы HTML можно отключить:
Явно отключите антифальсификационные маркеры с помощью атрибута
asp-antiforgery.<form method="post" asp-antiforgery="false"> <!-- ... --> </form>Элемент формы исключен из вспомогательных тегов, используя символ выхода из тегов !.
<!form method="post"> <!-- ... --> </!form>Удалите
FormTagHelperиз представления.FormTagHelperможно удалить из представления, добавив следующую директиву в представление Razor.@removeTagHelper Microsoft.AspNetCore.Mvc.TagHelpers.FormTagHelper, Microsoft.AspNetCore.Mvc.TagHelpers
Примечание.
Razor Страницы автоматически защищены от XSRF/CSRF. Дополнительные сведения см. в разделе XSRF/CSRF и Razor Pages.
Наиболее распространенный подход к защите от атак CSRF — использовать шаблон токена синхронизатора (STP). STP используется, когда пользователь запрашивает страницу с данными формы:
- Сервер отправляет маркер, связанный с удостоверением текущего пользователя клиенту.
- Клиент отправляет маркер на сервер для проверки.
- Если сервер получает маркер, который не соответствует удостоверению пользователя, прошедшего проверку подлинности, запрос отклоняется.
Токен является уникальным и непредсказуемым. Маркер также можно использовать для обеспечения правильной последовательности запросов (например, обеспечения последовательности запросов: страницы 1 > страницы 2 > страницы 3). Все формы в ASP.NET шаблонах Core MVC и Razor Pages создают маркеры защиты от подделки. Следующая пара примеров представления создает маркеры антифоргерии:
<form asp-action="Index" asp-controller="Home" method="post">
<!-- ... -->
</form>
@using (Html.BeginForm("Index", "Home"))
{
<!-- ... -->
}
Явно добавьте токен антиподделки в элемент <form> без использования вспомогателей тегов с HTML-вспомогателем @Html.AntiForgeryToken.
<form asp-action="Index" asp-controller="Home" method="post">
@Html.AntiForgeryToken()
<!-- ... -->
</form>
В каждом из предыдущих случаев ASP.NET Core добавляет скрытое поле формы, аналогичное следующему примеру:
<input name="__RequestVerificationToken" type="hidden" value="CfDJ8NrAkS ... s2-m9Yw">
ASP.NET Core включает три фильтра для работы с маркерами защиты от подделки:
Защита от подделок с AddControllers
Вызов AddControllersне включает маркеры защиты от подделки. AddControllersWithViews должен быть вызван для включения встроенной поддержки маркеров защиты от подделки.
Несколько вкладок браузера и шаблон токена синхронизатора
С помощью шаблона токена синхронизатора только последняя загруженная страница содержит допустимый токен защиты от подделки. Использование нескольких вкладок может быть проблематичным. Например, если пользователь открывает несколько вкладок:
- Только последняя загруженная вкладка содержит допустимый маркер антифальсификации.
- Запросы, сделанные из ранее загруженных вкладок, завершаются ошибкой:
Antiforgery token validation failed. The antiforgery cookie token and request token do not match
Если это представляет проблему, рассмотрите альтернативные шаблоны защиты CSRF.
Настройка защиты от подделки с помощью AntiforgeryOptions
Настройте AntiforgeryOptions в файле приложения Program :
builder.Services.AddAntiforgery(options =>
{
// Set Cookie properties using CookieBuilder properties†.
options.FormFieldName = "AntiforgeryFieldname";
options.HeaderName = "X-CSRF-TOKEN-HEADERNAME";
options.SuppressXFrameOptionsHeader = false;
});
Установите свойства антиподделки cookie, используя свойства класса CookieBuilder, как показано в следующей таблице.
| Вариант | Описание |
|---|---|
| Cookie | Определяет параметры, используемые для создания файлов cookie антивзломной защиты. |
| FormFieldName | Имя скрытого поля формы, используемого системой защиты от подделки для отображения токенов в представлениях. |
| HeaderName | Имя заголовка, используемого антифоргерской системой. Если nullсистема рассматривает только данные формы. |
| SuppressXFrameOptionsHeader | Указывает, следует ли подавлять создание заголовка X-Frame-Options . По умолчанию заголовок создается со значением "SAMEORIGIN". По умолчанию — false. |
Некоторые браузеры не разрешают небезопасным конечным точкам устанавливать файлы cookie с флагом "безопасный" или перезаписывать файлы cookie, флаг безопасности которых установлен (дополнительные сведения см. в разделе "Нерекомендуемые изменения" файлов cookie из небезопасных источников). Так как сочетание безопасных и небезопасных конечных точек является общим сценарием в приложениях, ASP.NET Core смягчает ограничение на безопасную политику для некоторых файлов cookie, таких как antiforgery cookie, установив свойство cookie элемента SecurePolicy на CookieSecurePolicy.None. Даже если злоумышленник украдет маркер антифоргерии cookie, он также должен украсть сам маркер, который обычно отправляется через поле формы (более распространенное) или отдельный заголовок запроса (менее распространенный), а также маркер проверки подлинности cookie.
Cookies для проверки подлинности или авторизации используется более надежная политика, чем CookieSecurePolicy.None.
Кроме того, вы можете защитить механизм защиты от подделки cookie в средах, которые отличаются от Development, по протоколу HTTPS с использованием SSL, с помощью установки следующего параметра свойства в файле приложения AntiforgeryOptions.Cookie:
if (!builder.Environment.IsDevelopment())
{
builder.Services.AddAntiforgery(o =>
{
o.Cookie.SecurePolicy = CookieSecurePolicy.Always;
});
}
Дополнительные сведения см. в разделе CookieAuthenticationOptions.
Генерация маркеров защиты от подделки с помощью IAntiforgery
IAntiforgery предоставляет API для настройки функций антифоргерии.
IAntiforgery можно запросить Program.cs с помощью WebApplication.Services. В следующем примере используется промежуточное ПО (middleware) на главной странице приложения для создания маркера защиты от подделки и отправки его в ответ в виде cookie:
app.UseRouting();
app.UseAuthorization();
var antiforgery = app.Services.GetRequiredService<IAntiforgery>();
app.Use((context, next) =>
{
var requestPath = context.Request.Path.Value;
if (string.Equals(requestPath, "/", StringComparison.OrdinalIgnoreCase)
|| string.Equals(requestPath, "/index.html", StringComparison.OrdinalIgnoreCase))
{
var tokenSet = antiforgery.GetAndStoreTokens(context);
context.Response.Cookies.Append("XSRF-TOKEN", tokenSet.RequestToken!,
new CookieOptions { HttpOnly = false });
}
return next(context);
});
В предыдущем примере задается cookie, называемый XSRF-TOKEN. Клиент может прочитать это cookie и указать его значение в качестве заголовка, присоединенного к запросам AJAX. Например, Angular включает встроенную защиту XSRF, которая по умолчанию считывает cookie с именем cookieXSRF-TOKEN.
Требовать антифальсификационной проверки
Фильтр действий ValidateAntiForgeryToken можно применить к отдельному действию, контроллеру или глобально. Запросы, сделанные к действиям, к которым применяется этот фильтр, блокируются, если запрос не включает допустимый маркер антифоргерии.
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Index()
{
// ...
return RedirectToAction();
}
Атрибут ValidateAntiForgeryToken требует маркер для всех запросов к методам действия, которые он отмечает, включая запросы HTTP GET. Если атрибут ValidateAntiForgeryToken применяется ко всем контроллерам приложения, его можно переопределить с помощью атрибута IgnoreAntiforgeryToken.
Автоматическая проверка маркеров защиты от подделки только для небезопасных методов HTTP
Вместо широкого применения атрибута ValidateAntiForgeryToken и переопределения его атрибутами IgnoreAntiforgeryTokenможно использовать атрибут AutoValidateAntiforgeryToken . Этот атрибут работает идентично атрибуту ValidateAntiForgeryToken , за исключением того, что он не требует маркеров для запросов, выполненных с помощью следующих методов HTTP:
- ПОЛУЧИТЬ
- Заголовок
- ПАРАМЕТРЫ
- ТРАССИРОВКА
Рекомендуется использовать AutoValidateAntiforgeryToken широко для сценариев, отличных от API. Этот атрибут гарантирует, что действия POST защищены по умолчанию. Альтернативой является игнорирование маркеров антифоргерии по умолчанию, если ValidateAntiForgeryToken не применяется к отдельным методам действия. Скорее всего, в этом сценарии метод действия POST остается незащищенным по ошибке, оставляя приложение уязвимым к атакам CSRF. Все запросы POST должны отправлять антифорджери-токен.
API не имеют автоматического механизма для отправки той части токена, которая не является cookie. Реализация, вероятно, зависит от реализации клиентского кода. Ниже показаны некоторые примеры:
Пример уровня класса:
[AutoValidateAntiforgeryToken]
public class HomeController : Controller
Глобальный пример:
builder.Services.AddControllersWithViews(options =>
{
options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute());
});
Переопределение глобальных атрибутов или атрибутов защиты от подделки в контроллере
Фильтр IgnoreAntiforgeryToken используется для устранения необходимости в токене защиты от подделки для данного действия (или контроллера). При применении этот фильтр переопределяет фильтры ValidateAntiForgeryToken и AutoValidateAntiforgeryToken, указанные на более высоком уровне (глобально или на контроллере).
[IgnoreAntiforgeryToken]
public IActionResult IndexOverride()
{
// ...
return RedirectToAction();
}
Обновление токенов после аутентификации
Маркеры должны обновляться после проверки подлинности пользователя, перенаправляя пользователя на страницу представления или Razor страницы.
JavaScript, AJAX и SPA
В традиционных приложениях на основе HTML маркеры защиты от подмен передаются серверу с помощью скрытых полей формы. В современных приложениях и spAs на основе JavaScript многие запросы выполняются программными средствами. Эти запросы AJAX могут использовать другие методы (например, заголовки запросов или файлы cookie) для отправки маркера.
Если файлы cookie используются для хранения маркеров проверки подлинности и проверки подлинности запросов API на сервере, CSRF является потенциальной проблемой. Если локальное хранилище используется для хранения маркера, уязвимость CSRF может быть устранена, так как значения из локального хранилища не отправляются автоматически на сервер с каждым запросом. Использование локального хранилища для хранения маркера защиты от подделки на клиенте и отправка маркера в качестве заголовка запроса рекомендуется.
JavaScript
Используя JavaScript в представлениях, маркер можно создать через службу непосредственно в представлении. Внедрите службу IAntiforgery в представление и вызовите GetAndStoreTokens.
@inject Microsoft.AspNetCore.Antiforgery.IAntiforgery Antiforgery
@{
ViewData["Title"] = "JavaScript";
var requestToken = Antiforgery.GetAndStoreTokens(Context).RequestToken;
}
<input id="RequestVerificationToken" type="hidden" value="@requestToken" />
<button id="button" class="btn btn-primary">Submit with Token</button>
<div id="result" class="mt-2"></div>
@section Scripts {
<script>
document.addEventListener("DOMContentLoaded", () => {
const resultElement = document.getElementById("result");
document.getElementById("button").addEventListener("click", async () => {
const response = await fetch("@Url.Action("FetchEndpoint")", {
method: "POST",
headers: {
RequestVerificationToken:
document.getElementById("RequestVerificationToken").value
}
});
if (response.ok) {
resultElement.innerText = await response.text();
} else {
resultElement.innerText = `Request Failed: ${response.status}`
}
});
});
</script>
}
В предыдущем примере используется JavaScript для чтения значения скрытого поля для заголовка AJAX POST.
Этот подход устраняет необходимость непосредственной настройки файлов cookie с сервера или их чтения от клиента. Однако, если внедрение службы IAntiforgery невозможно, используйте JavaScript для доступа к маркерам в файлах cookie.
- Маркеры доступа в дополнительном запросе к серверу обычно
same-origin. - Используйте содержимое cookie, чтобы создать заголовок со значением токена.
Если скрипт отправляет маркер в заголовке запроса X-XSRF-TOKEN, настройте службу защиты от подделки для поиска заголовка X-XSRF-TOKEN :
builder.Services.AddAntiforgery(options => options.HeaderName = "X-XSRF-TOKEN");
В следующем примере добавляется защищенный конечный пункт, который записывает токен запроса в элемент cookie, доступный для считывания JavaScript.
app.UseAuthorization();
app.MapGet("antiforgery/token", (IAntiforgery forgeryService, HttpContext context) =>
{
var tokens = forgeryService.GetAndStoreTokens(context);
context.Response.Cookies.Append("XSRF-TOKEN", tokens.RequestToken!,
new CookieOptions { HttpOnly = false });
return Results.Ok();
}).RequireAuthorization();
В следующем примере JavaScript используется для выполнения запроса AJAX для получения маркера и выполнения другого запроса с соответствующим заголовком:
var response = await fetch("/antiforgery/token", {
method: "GET",
headers: { "Authorization": authorizationToken }
});
if (response.ok) {
// https://developer.mozilla.org/docs/web/api/document/cookie
const xsrfToken = document.cookie
.split("; ")
.find(row => row.startsWith("XSRF-TOKEN="))
.split("=")[1];
response = await fetch("/JavaScript/FetchEndpoint", {
method: "POST",
headers: { "X-XSRF-TOKEN": xsrfToken, "Authorization": authorizationToken }
});
if (response.ok) {
resultElement.innerText = await response.text();
} else {
resultElement.innerText = `Request Failed: ${response.status}`
}
} else {
resultElement.innerText = `Request Failed: ${response.status}`
}
Примечание.
Если антифальсификационный маркер указан как в заголовке запроса, так и в полезных данных формы, проверяется только маркер в заголовке.
Антифальсификация с минимальными интерфейсами API
Minimal APIs не поддерживает использование включенных фильтров (ValidateAntiForgeryToken, AutoValidateAntiforgeryToken, IgnoreAntiforgeryTokenоднако), IAntiforgery предоставляет необходимые API для проверки запроса.
В следующем примере создается фильтр, проверяющий антиконтрафактный маркер:
internal static class AntiForgeryExtensions
{
public static TBuilder ValidateAntiforgery<TBuilder>(this TBuilder builder) where TBuilder : IEndpointConventionBuilder
{
return builder.AddEndpointFilter(routeHandlerFilter: async (context, next) =>
{
try
{
var antiForgeryService = context.HttpContext.RequestServices.GetRequiredService<IAntiforgery>();
await antiForgeryService.ValidateRequestAsync(context.HttpContext);
}
catch (AntiforgeryValidationException)
{
return Results.BadRequest("Antiforgery token validation failed.");
}
return await next(context);
});
}
}
Затем фильтр можно применить к конечной точке:
app.MapPost("api/upload", (IFormFile name) => Results.Accepted())
.RequireAuthorization()
.ValidateAntiforgery();
файлы cookie аутентификации Windows и защиты от подделки
При использовании проверки подлинности Windows конечные точки приложений должны быть защищены от атак CSRF так же, как и для файлов cookie. Браузер неявно отправляет контекст проверки подлинности серверу и конечным точкам, которые необходимо защитить от атак CSRF.
Расширить защиту от подделок
Тип IAntiforgeryAdditionalDataProvider позволяет разработчикам расширить поведение системы защиты от CSRF путем обхода дополнительных данных в каждом токене. Метод GetAdditionalData вызывается каждый раз при создании маркера поля, а возвращаемое значение внедрено в созданный маркер. Реализующий может возвращать метку времени, nonce или любое другое значение, а затем вызывать ValidateAdditionalData для проверки этих данных при проверке этого токена. Имя пользователя клиента уже внедрено в созданные маркеры, поэтому не нужно включать эти сведения. Если в маркере содержатся дополнительные данные, но IAntiForgeryAdditionalDataProvider не настроен, то дополнительные данные не проверяются.
Дополнительные ресурсы
Межсайтовая подделка запросов (также известная как XSRF или CSRF) — это атака на веб-приложения, посредством которых вредоносное веб-приложение может влиять на взаимодействие между клиентским браузером и веб-приложением, которое доверяет этому браузеру. Эти атаки возможны, так как веб-браузеры автоматически отправляют некоторые типы маркеров проверки подлинности с каждым запросом на веб-сайт. Эта форма эксплойта также называется атакой одним щелчком или сеансовым угоном, так как атака использует прошедший аутентификацию сеанс пользователя.
Пример атаки CSRF:
Пользователь входит в
www.good-banking-site.example.comсистему с помощью проверки подлинности форм. Сервер выполняет проверку подлинности пользователя и выдает ответ, содержащий проверку подлинности cookie. Сайт уязвим к атакам, поскольку сайт доверяет любому полученному запросу с допустимой аутентификацией cookie.Пользователь посещает вредоносный сайт.
www.bad-crook-site.example.comВредоносный сайт
www.bad-crook-site.example.comсодержит HTML-форму, аналогичную следующему примеру:<h1>Congratulations! You're a Winner!</h1> <form action="https://www.good-banking-site.example.com/api/account" method="post"> <input type="hidden" name="Transaction" value="withdraw" /> <input type="hidden" name="Amount" value="1000000" /> <input type="submit" value="Click to collect your prize!" /> </form>Обратите внимание, что отправка формы
actionпроисходит на уязвимый сайт, а не на вредоносный сайт. Это "межсайтовая" часть CSRF.Пользователь выбирает кнопку отправки. Браузер выполняет запрос и автоматически включает проверку подлинности cookie для запрошенного домена
www.good-banking-site.example.com.Запрос выполняется на сервере
www.good-banking-site.example.comс контекстом проверки подлинности пользователя и может выполнять любое действие, которое разрешено выполнить пользователю, прошедшему проверку подлинности.
Помимо сценария, когда пользователь выбирает кнопку для отправки формы, вредоносный сайт может:
- Запустите скрипт, который автоматически отправляет форму.
- Отправьте отправку формы в виде запроса AJAX.
- Скрытие формы с помощью CSS.
Эти альтернативные сценарии не требуют никаких действий или входных данных от пользователя, кроме первоначального посещения вредоносного сайта.
Использование HTTPS не предотвращает атаку CSRF. Вредоносный сайт может отправлять https://www.good-banking-site.example.com/ запрос так же легко, как он может отправлять небезопасный запрос.
Некоторые атаки предназначены для конечных точек, реагирующих на запросы GET, в этом случае тег изображения можно использовать для выполнения действия. Эта форма атаки распространена на сайтах форума, которые разрешают изображения, но блокируют JavaScript. Приложения, изменяющие состояние запросов GET, в которых переменные или ресурсы изменяются, уязвимы для вредоносных атак. Запросы GET, изменяющие состояние, небезопасны. Рекомендуется никогда не изменять состояние запроса GET.
Атаки CSRF возможны для веб-приложений, использующих файлы cookie для проверки подлинности, так как:
- Браузеры хранят файлы cookie, выданные веб-приложением.
- Сохраненные файлы cookie включают файлы cookie сеанса для пользователей, прошедших аутентификацию.
- Браузеры отправляют все файлы cookie, связанные с доменом, в веб-приложение каждый запрос независимо от того, как был создан запрос к приложению в браузере.
Однако атаки CSRF не ограничиваются использованием файлов cookie. Например, Базовая и Дайджест-аутентификация также уязвимы. После входа пользователя с помощью базовой или дайджест-проверки подлинности браузер автоматически отправляет учетные данные до окончания сеанса.
В этом контексте сеанс ссылается на сеанс на стороне клиента, в течение которого пользователь проходит проверку подлинности. Это не связано с сеансами на стороне сервера или промежуточным ПО сеансов ASP.NET Core.
Пользователи могут защищаться от уязвимостей CSRF, принимая меры предосторожности:
- Выйдите из веб-приложений после завершения работы с ними.
- Периодически очищать файлы cookie браузера.
Однако уязвимости CSRF являются основной проблемой веб-приложения, а не конечным пользователем.
Основы проверки подлинности
Аутентификация на основе Cookie является популярной формой проверки подлинности. Системы аутентификации на основе токенов становятся всё более популярными, особенно для одностраничных приложений (SPA).
Cookie-основанная аутентификация
Когда пользователь проходит аутентификацию с помощью имени пользователя и пароля, ему выдается токен, содержащий аутентификационный билет, который используется для аутентификации и авторизации. Маркер хранится как cookie, который отправляется с каждым запросом клиента. Создание и проверка этого cookie выполняются промежуточным ПО cookie аутентификации. Промежуточное ПО
Проверка подлинности на основе токенов
Когда пользователь проходит проверку подлинности, ему выдается токен (а не антифальсификационный токен). Токен содержит информацию о пользователе в виде утверждений или ссылочного токена, который указывает приложению на состояние пользователя, сохраняемое в приложении. Когда пользователь пытается получить доступ к ресурсу, требующий проверки подлинности, маркер отправляется приложению с дополнительным заголовком авторизации в виде маркера Bearer . Такой подход делает приложение бессостоя́тельным. В каждом последующем запросе маркер передается в запросе на проверку на стороне сервера. Этот маркер не шифруется; он закодирован. На сервере маркер декодируется для доступа к его информации. Чтобы отправить маркер на последующие запросы, сохраните маркер в локальном хранилище браузера. Не беспокойтесь об уязвимости CSRF, если маркер хранится в локальном хранилище браузера. CSRF является проблемой, когда токен хранится в cookie. Для получения дополнительной информации см. проблему GitHub SPA code sample adds two cookies.
Несколько приложений, размещенных в одном домене
Среды общего размещения уязвимы к перехвату сеанса, CSRF-атакам при входе и другим видам атак.
Хотя example1.contoso.net и example2.contoso.net являются разными узлами, существует неявная связь доверия между узлами в домене *.contoso.net . Эта неявная связь доверия позволяет потенциально ненадежным узлам влиять на файлы cookie друг друга (политики того же источника, которые управляют запросами AJAX, не обязательно применяются к файлам cookie HTTP).
Атаки, которые используют доверенные файлы cookie между приложениями, размещенными в одном домене, можно предотвратить, не предоставляя общий доступ к доменам. Если каждое приложение размещено в собственном домене, не существует неявных cookie отношений доверия для эксплойтов.
Защита от подделок в ASP.NET Core
Предупреждение
ASP.NET Core реализует антифоргерию с помощью ASP.NET Core Data Protection. Стек защиты данных должен быть настроен для работы в ферме серверов. Дополнительные сведения см. в разделе "Настройка защиты данных".
Промежуточное программное обеспечение для защиты от подделок добавляется в контейнер внедрения зависимостей, если вызывается один из следующих API:
FormTagHelper вставляет маркеры защиты от подделки в элементы HTML-форм. Следующий тег в Razor файле автоматически создает антифальсификационные токены:
<form method="post">
<!-- ... -->
</form>
Аналогичным образом IHtmlHelper.BeginForm создаёт маркеры антифальсификации по умолчанию, если метод формы не является GET.
Автоматическое создание маркеров антиподделки для элементов формы HTML происходит, когда <form> тег содержит method="post" атрибут, и выполняется любое из следующих условий:
- Атрибут действия пуст (
action=""). - Атрибут действия не предоставляется (
<form method="post">).
Автоматическое создание маркеров антифоргерии для элементов формы HTML можно отключить:
Явно отключите антифальсификационные маркеры с помощью атрибута
asp-antiforgery.<form method="post" asp-antiforgery="false"> <!-- ... --> </form>Элемент формы исключен из вспомогательных тегов, используя символ выхода из тегов !.
<!form method="post"> <!-- ... --> </!form>Удалите
FormTagHelperиз представления.FormTagHelperможно удалить из представления, добавив следующую директиву в представление Razor.@removeTagHelper Microsoft.AspNetCore.Mvc.TagHelpers.FormTagHelper, Microsoft.AspNetCore.Mvc.TagHelpers
Примечание.
Razor Страницы автоматически защищены от XSRF/CSRF. Дополнительные сведения см. в разделе XSRF/CSRF и Razor Pages.
Наиболее распространенный подход к защите от атак CSRF — использовать шаблон токена синхронизатора (STP). STP используется, когда пользователь запрашивает страницу с данными формы:
- Сервер отправляет маркер, связанный с удостоверением текущего пользователя клиенту.
- Клиент отправляет маркер на сервер для проверки.
- Если сервер получает маркер, который не соответствует удостоверению пользователя, прошедшего проверку подлинности, запрос отклоняется.
Токен является уникальным и непредсказуемым. Маркер также можно использовать для обеспечения правильной последовательности запросов (например, обеспечения последовательности запросов: страницы 1 > страницы 2 > страницы 3). Все формы в ASP.NET шаблонах Core MVC и Razor Pages создают маркеры защиты от подделки. Следующая пара примеров представления создает маркеры антифоргерии:
<form asp-action="Index" asp-controller="Home" method="post">
<!-- ... -->
</form>
@using (Html.BeginForm("Index", "Home"))
{
<!-- ... -->
}
Явно добавьте токен антиподделки в элемент <form> без использования вспомогателей тегов с HTML-вспомогателем @Html.AntiForgeryToken.
<form asp-action="Index" asp-controller="Home" method="post">
@Html.AntiForgeryToken()
<!-- ... -->
</form>
В каждом из предыдущих случаев ASP.NET Core добавляет скрытое поле формы, аналогичное следующему примеру:
<input name="__RequestVerificationToken" type="hidden" value="CfDJ8NrAkS ... s2-m9Yw">
ASP.NET Core включает три фильтра для работы с маркерами защиты от подделки:
Защита от подделок с AddControllers
Вызов AddControllersне включает маркеры защиты от подделки. AddControllersWithViews должен быть вызван для включения встроенной поддержки маркеров защиты от подделки.
Несколько вкладок браузера и шаблон токена синхронизатора
С помощью шаблона токена синхронизатора только последняя загруженная страница содержит допустимый токен защиты от подделки. Использование нескольких вкладок может быть проблематичным. Например, если пользователь открывает несколько вкладок:
- Только последняя загруженная вкладка содержит допустимый маркер антифальсификации.
- Запросы, сделанные из ранее загруженных вкладок, завершаются ошибкой:
Antiforgery token validation failed. The antiforgery cookie token and request token do not match
Если это представляет проблему, рассмотрите альтернативные шаблоны защиты CSRF.
Настройка защиты от подделки с помощью AntiforgeryOptions
Настройте AntiforgeryOptions в файле приложения Program :
builder.Services.AddAntiforgery(options =>
{
// Set Cookie properties using CookieBuilder properties†.
options.FormFieldName = "AntiforgeryFieldname";
options.HeaderName = "X-CSRF-TOKEN-HEADERNAME";
options.SuppressXFrameOptionsHeader = false;
});
Установите свойства антиподделки cookie, используя свойства класса CookieBuilder, как показано в следующей таблице.
| Вариант | Описание |
|---|---|
| Cookie | Определяет параметры, используемые для создания файлов cookie антивзломной защиты. |
| FormFieldName | Имя скрытого поля формы, используемого системой защиты от подделки для отображения токенов в представлениях. |
| HeaderName | Имя заголовка, используемого антифоргерской системой. Если nullсистема рассматривает только данные формы. |
| SuppressXFrameOptionsHeader | Указывает, следует ли подавлять создание заголовка X-Frame-Options . По умолчанию заголовок создается со значением "SAMEORIGIN". По умолчанию — false. |
Некоторые браузеры не разрешают небезопасным конечным точкам устанавливать файлы cookie с флагом "безопасный" или перезаписывать файлы cookie, флаг безопасности которых установлен (дополнительные сведения см. в разделе "Нерекомендуемые изменения" файлов cookie из небезопасных источников). Так как сочетание безопасных и небезопасных конечных точек является общим сценарием в приложениях, ASP.NET Core смягчает ограничение на безопасную политику для некоторых файлов cookie, таких как antiforgery cookie, установив свойство cookie элемента SecurePolicy на CookieSecurePolicy.None. Даже если злоумышленник украдет маркер антифоргерии cookie, он также должен украсть сам маркер, который обычно отправляется через поле формы (более распространенное) или отдельный заголовок запроса (менее распространенный), а также маркер проверки подлинности cookie.
Cookies для проверки подлинности или авторизации используется более надежная политика, чем CookieSecurePolicy.None.
Кроме того, вы можете защитить механизм защиты от подделки cookie в средах, которые отличаются от Development, по протоколу HTTPS с использованием SSL, с помощью установки следующего параметра свойства в файле приложения AntiforgeryOptions.Cookie:
if (!builder.Environment.IsDevelopment())
{
builder.Services.AddAntiforgery(o =>
{
o.Cookie.SecurePolicy = CookieSecurePolicy.Always;
});
}
Дополнительные сведения см. в разделе CookieAuthenticationOptions.
Генерация маркеров защиты от подделки с помощью IAntiforgery
IAntiforgery предоставляет API для настройки функций антифоргерии.
IAntiforgery можно запросить Program.cs с помощью WebApplication.Services. В следующем примере используется промежуточное ПО (middleware) на главной странице приложения для создания маркера защиты от подделки и отправки его в ответ в виде cookie:
app.UseRouting();
app.UseAuthorization();
var antiforgery = app.Services.GetRequiredService<IAntiforgery>();
app.Use((context, next) =>
{
var requestPath = context.Request.Path.Value;
if (string.Equals(requestPath, "/", StringComparison.OrdinalIgnoreCase)
|| string.Equals(requestPath, "/index.html", StringComparison.OrdinalIgnoreCase))
{
var tokenSet = antiforgery.GetAndStoreTokens(context);
context.Response.Cookies.Append("XSRF-TOKEN", tokenSet.RequestToken!,
new CookieOptions { HttpOnly = false });
}
return next(context);
});
В предыдущем примере задается cookie, называемый XSRF-TOKEN. Клиент может прочитать это cookie и указать его значение в качестве заголовка, присоединенного к запросам AJAX. Например, Angular включает встроенную защиту XSRF, которая по умолчанию считывает cookie с именем cookieXSRF-TOKEN.
Требовать антифальсификационной проверки
Фильтр действий ValidateAntiForgeryToken можно применить к отдельному действию, контроллеру или глобально. Запросы, сделанные к действиям, к которым применяется этот фильтр, блокируются, если запрос не включает допустимый маркер антифоргерии.
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Index()
{
// ...
return RedirectToAction();
}
Атрибут ValidateAntiForgeryToken требует маркер для всех запросов к методам действия, которые он отмечает, включая запросы HTTP GET. Если атрибут ValidateAntiForgeryToken применяется ко всем контроллерам приложения, его можно переопределить с помощью атрибута IgnoreAntiforgeryToken.
Автоматическая проверка маркеров защиты от подделки только для небезопасных методов HTTP
Вместо широкого применения атрибута ValidateAntiForgeryToken и переопределения его атрибутами IgnoreAntiforgeryTokenможно использовать атрибут AutoValidateAntiforgeryToken . Этот атрибут работает идентично атрибуту ValidateAntiForgeryToken , за исключением того, что он не требует маркеров для запросов, выполненных с помощью следующих методов HTTP:
- ПОЛУЧИТЬ
- Заголовок
- ПАРАМЕТРЫ
- ТРАССИРОВКА
Рекомендуется использовать AutoValidateAntiforgeryToken широко для сценариев, отличных от API. Этот атрибут гарантирует, что действия POST защищены по умолчанию. Альтернативой является игнорирование маркеров антифоргерии по умолчанию, если ValidateAntiForgeryToken не применяется к отдельным методам действия. Скорее всего, в этом сценарии метод действия POST остается незащищенным по ошибке, оставляя приложение уязвимым к атакам CSRF. Все запросы POST должны отправлять антифорджери-токен.
API не имеют автоматического механизма для отправки той части токена, которая не является cookie. Реализация, вероятно, зависит от реализации клиентского кода. Ниже показаны некоторые примеры:
Пример уровня класса:
[AutoValidateAntiforgeryToken]
public class HomeController : Controller
Глобальный пример:
builder.Services.AddControllersWithViews(options =>
{
options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute());
});
Переопределение глобальных атрибутов или атрибутов защиты от подделки в контроллере
Фильтр IgnoreAntiforgeryToken используется для устранения необходимости в токене защиты от подделки для данного действия (или контроллера). При применении этот фильтр переопределяет фильтры ValidateAntiForgeryToken и AutoValidateAntiforgeryToken, указанные на более высоком уровне (глобально или на контроллере).
[IgnoreAntiforgeryToken]
public IActionResult IndexOverride()
{
// ...
return RedirectToAction();
}
Обновление токенов после аутентификации
Маркеры должны обновляться после проверки подлинности пользователя, перенаправляя пользователя на страницу представления или Razor страницы.
JavaScript, AJAX и SPA
В традиционных приложениях на основе HTML маркеры защиты от подмен передаются серверу с помощью скрытых полей формы. В современных приложениях и spAs на основе JavaScript многие запросы выполняются программными средствами. Эти запросы AJAX могут использовать другие методы (например, заголовки запросов или файлы cookie) для отправки маркера.
Если файлы cookie используются для хранения маркеров проверки подлинности и проверки подлинности запросов API на сервере, CSRF является потенциальной проблемой. Если локальное хранилище используется для хранения маркера, уязвимость CSRF может быть устранена, так как значения из локального хранилища не отправляются автоматически на сервер с каждым запросом. Использование локального хранилища для хранения маркера защиты от подделки на клиенте и отправка маркера в качестве заголовка запроса рекомендуется.
JavaScript
Используя JavaScript в представлениях, маркер можно создать через службу непосредственно в представлении. Внедрите службу IAntiforgery в представление и вызовите GetAndStoreTokens.
@inject Microsoft.AspNetCore.Antiforgery.IAntiforgery Antiforgery
@{
ViewData["Title"] = "JavaScript";
var requestToken = Antiforgery.GetAndStoreTokens(Context).RequestToken;
}
<input id="RequestVerificationToken" type="hidden" value="@requestToken" />
<button id="button" class="btn btn-primary">Submit with Token</button>
<div id="result" class="mt-2"></div>
@section Scripts {
<script>
document.addEventListener("DOMContentLoaded", () => {
const resultElement = document.getElementById("result");
document.getElementById("button").addEventListener("click", async () => {
const response = await fetch("@Url.Action("FetchEndpoint")", {
method: "POST",
headers: {
RequestVerificationToken:
document.getElementById("RequestVerificationToken").value
}
});
if (response.ok) {
resultElement.innerText = await response.text();
} else {
resultElement.innerText = `Request Failed: ${response.status}`
}
});
});
</script>
}
В предыдущем примере используется JavaScript для чтения значения скрытого поля для заголовка AJAX POST.
Этот подход устраняет необходимость непосредственной настройки файлов cookie с сервера или их чтения от клиента. Однако когда внедрение службы IAntiforgery невозможно, JavaScript также может получить доступ к токену в файлах cookie, полученных из дополнительного запроса к серверу (обычно same-origin), и использовать содержимое cookie для создания заголовка со значением токена.
Если скрипт отправляет маркер в заголовке запроса X-XSRF-TOKEN, настройте службу защиты от подделки для поиска заголовка X-XSRF-TOKEN :
builder.Services.AddAntiforgery(options => options.HeaderName = "X-XSRF-TOKEN");
В следующем примере добавляется защищенная конечная точка, которая будет записывать маркер запроса в читаемый JavaScript cookie.
app.UseAuthorization();
app.MapGet("antiforgery/token", (IAntiforgery forgeryService, HttpContext context) =>
{
var tokens = forgeryService.GetAndStoreTokens(context);
context.Response.Cookies.Append("XSRF-TOKEN", tokens.RequestToken!,
new CookieOptions { HttpOnly = false });
return Results.Ok();
}).RequireAuthorization();
В следующем примере JavaScript используется для выполнения запроса AJAX для получения маркера и выполнения другого запроса с соответствующим заголовком:
var response = await fetch("/antiforgery/token", {
method: "GET",
headers: { "Authorization": authorizationToken }
});
if (response.ok) {
// https://developer.mozilla.org/docs/web/api/document/cookie
const xsrfToken = document.cookie
.split("; ")
.find(row => row.startsWith("XSRF-TOKEN="))
.split("=")[1];
response = await fetch("/JavaScript/FetchEndpoint", {
method: "POST",
headers: { "X-XSRF-TOKEN": xsrfToken, "Authorization": authorizationToken }
});
if (response.ok) {
resultElement.innerText = await response.text();
} else {
resultElement.innerText = `Request Failed: ${response.status}`
}
} else {
resultElement.innerText = `Request Failed: ${response.status}`
}
файлы cookie аутентификации Windows и защиты от подделки
При использовании проверки подлинности Windows конечные точки приложений должны быть защищены от атак CSRF так же, как и для файлов cookie. Браузер неявно отправляет контекст проверки подлинности серверу и поэтому конечные точки должны быть защищены от атак CSRF.
Расширить защиту от подделок
Тип IAntiforgeryAdditionalDataProvider позволяет разработчикам расширить поведение системы защиты от CSRF путем обхода дополнительных данных в каждом токене. Метод GetAdditionalData вызывается каждый раз при создании маркера поля, а возвращаемое значение внедрено в созданный маркер. Реализующий может возвращать метку времени, nonce или любое другое значение, а затем вызывать ValidateAdditionalData для проверки этих данных при проверке этого токена. Имя пользователя клиента уже внедрено в созданные маркеры, поэтому не нужно включать эти сведения. Если в маркере содержатся дополнительные данные, но IAntiForgeryAdditionalDataProvider не настроен, то дополнительные данные не проверяются.
Дополнительные ресурсы
Межсайтовая подделка запросов (также известная как XSRF или CSRF) — это атака на веб-приложения, посредством которых вредоносное веб-приложение может влиять на взаимодействие между клиентским браузером и веб-приложением, которое доверяет этому браузеру. Эти атаки возможны, так как веб-браузеры автоматически отправляют некоторые типы маркеров проверки подлинности с каждым запросом на веб-сайт. Эта форма эксплойта также называется атакой одним щелчком или сеансовым угоном, так как атака использует прошедший аутентификацию сеанс пользователя.
Пример атаки CSRF:
Пользователь входит в
www.good-banking-site.example.comсистему с помощью проверки подлинности форм. Сервер выполняет проверку подлинности пользователя и выдает ответ, содержащий проверку подлинности cookie. Сайт уязвим к атакам, поскольку сайт доверяет любому полученному запросу с допустимой аутентификацией cookie.Пользователь посещает вредоносный сайт.
www.bad-crook-site.example.comВредоносный сайт
www.bad-crook-site.example.comсодержит HTML-форму, аналогичную следующему примеру:<h1>Congratulations! You're a Winner!</h1> <form action="https://www.good-banking-site.example.com/api/account" method="post"> <input type="hidden" name="Transaction" value="withdraw" /> <input type="hidden" name="Amount" value="1000000" /> <input type="submit" value="Click to collect your prize!" /> </form>Обратите внимание, что отправка формы
actionпроисходит на уязвимый сайт, а не на вредоносный сайт. Это "межсайтовая" часть CSRF.Пользователь выбирает кнопку отправки. Браузер выполняет запрос и автоматически включает проверку подлинности cookie для запрошенного домена
www.good-banking-site.example.com.Запрос выполняется на сервере
www.good-banking-site.example.comс контекстом проверки подлинности пользователя и может выполнять любое действие, которое разрешено выполнить пользователю, прошедшему проверку подлинности.
Помимо сценария, когда пользователь выбирает кнопку для отправки формы, вредоносный сайт может:
- Запустите скрипт, который автоматически отправляет форму.
- Отправьте отправку формы в виде запроса AJAX.
- Скрытие формы с помощью CSS.
Эти альтернативные сценарии не требуют никаких действий или входных данных от пользователя, кроме первоначального посещения вредоносного сайта.
Использование HTTPS не предотвращает атаку CSRF. Вредоносный сайт может отправлять https://www.good-banking-site.example.com/ запрос так же легко, как он может отправлять небезопасный запрос.
Некоторые атаки предназначены для конечных точек, реагирующих на запросы GET, в этом случае тег изображения можно использовать для выполнения действия. Эта форма атаки распространена на сайтах форума, которые разрешают изображения, но блокируют JavaScript. Приложения, изменяющие состояние запросов GET, в которых переменные или ресурсы изменяются, уязвимы для вредоносных атак. Запросы GET, изменяющие состояние, небезопасны. Рекомендуется никогда не изменять состояние запроса GET.
Атаки CSRF возможны для веб-приложений, использующих файлы cookie для проверки подлинности, так как:
- Браузеры хранят файлы cookie, выданные веб-приложением.
- Сохраненные файлы cookie включают файлы cookie сеанса для пользователей, прошедших аутентификацию.
- Браузеры отправляют все файлы cookie, связанные с доменом, в веб-приложение каждый запрос независимо от того, как был создан запрос к приложению в браузере.
Однако атаки CSRF не ограничиваются использованием файлов cookie. Например, Базовая и Дайджест-аутентификация также уязвимы. После входа пользователя с помощью базовой или дайджест-проверки подлинности браузер автоматически отправляет учетные данные до окончания сеанса.
В этом контексте сеанс ссылается на сеанс на стороне клиента, в течение которого пользователь проходит проверку подлинности. Это не связано с сеансами на стороне сервера или промежуточным ПО сеансов ASP.NET Core.
Пользователи могут защищаться от уязвимостей CSRF, принимая меры предосторожности:
- Выйдите из веб-приложений после завершения работы с ними.
- Периодически очищать файлы cookie браузера.
Однако уязвимости CSRF являются основной проблемой веб-приложения, а не конечным пользователем.
Основы проверки подлинности
Аутентификация на основе Cookie является популярной формой проверки подлинности. Системы аутентификации на основе токенов становятся всё более популярными, особенно для одностраничных приложений (SPA).
Cookie-основанная аутентификация
Когда пользователь проходит аутентификацию с помощью имени пользователя и пароля, ему выдается токен, содержащий аутентификационный билет, который используется для аутентификации и авторизации. Маркер хранится как cookie, который отправляется с каждым запросом клиента. Создание и проверка этого cookie выполняются промежуточным ПО cookie аутентификации. Промежуточное ПО
Проверка подлинности на основе токенов
Когда пользователь проходит проверку подлинности, ему выдается токен (а не антифальсификационный токен). Токен содержит информацию о пользователе в виде утверждений или ссылочного токена, который указывает приложению на состояние пользователя, сохраняемое в приложении. Когда пользователь пытается получить доступ к ресурсу, требующий проверки подлинности, маркер отправляется приложению с дополнительным заголовком авторизации в виде маркера Bearer . Такой подход делает приложение бессостоя́тельным. В каждом последующем запросе маркер передается в запросе на проверку на стороне сервера. Этот маркер не шифруется; он закодирован. На сервере маркер декодируется для доступа к его информации. Чтобы отправить маркер на последующие запросы, сохраните маркер в локальном хранилище браузера. Не беспокойтесь об уязвимости CSRF, если маркер хранится в локальном хранилище браузера. CSRF является проблемой, когда токен хранится в cookie. Для получения дополнительной информации см. проблему GitHub SPA code sample adds two cookies.
Несколько приложений, размещенных в одном домене
Среды общего размещения уязвимы к перехвату сеанса, CSRF-атакам при входе и другим видам атак.
Хотя example1.contoso.net и example2.contoso.net являются разными узлами, существует неявная связь доверия между узлами в домене *.contoso.net . Эта неявная связь доверия позволяет потенциально ненадежным узлам влиять на файлы cookie друг друга (политики того же источника, которые управляют запросами AJAX, не обязательно применяются к файлам cookie HTTP).
Атаки, которые используют доверенные файлы cookie между приложениями, размещенными в одном домене, можно предотвратить, не предоставляя общий доступ к доменам. Если каждое приложение размещено в собственном домене, не существует неявных cookie отношений доверия для эксплойтов.
конфигурация antiforgery в ASP.NET Core
Предупреждение
ASP.NET Core реализует антифоргерию с помощью ASP.NET Core Data Protection. Стек защиты данных должен быть настроен для работы в ферме серверов. Дополнительные сведения см. в разделе "Настройка защиты данных".
Промежуточное программное обеспечение для защиты от подделок добавляется в контейнер внедрения зависимостей, если вызывается один из следующих API:
В ASP.NET Core 2.0 или более поздней версии FormTagHelper внедряет маркеры антифоргерии в элементы формы HTML. Следующий тег в Razor файле автоматически создает антифальсификационные токены:
<form method="post">
...
</form>
Аналогичным образом IHtmlHelper.BeginForm создаёт маркеры антифальсификации по умолчанию, если метод формы не является GET.
Автоматическое создание маркеров антиподделки для элементов формы HTML происходит, когда <form> тег содержит method="post" атрибут, и выполняется любое из следующих условий:
- Атрибут действия пуст (
action=""). - Атрибут действия не предоставляется (
<form method="post">).
Автоматическое создание маркеров антифоргерии для элементов формы HTML можно отключить:
Явно отключите антифальсификационные маркеры с помощью атрибута
asp-antiforgery.<form method="post" asp-antiforgery="false"> ... </form>Элемент формы исключен из вспомогательных тегов, используя символ выхода из тегов !.
<!form method="post"> ... </!form>Удалите
FormTagHelperиз представления.FormTagHelperможно удалить из представления, добавив следующую директиву в представление Razor.@removeTagHelper Microsoft.AspNetCore.Mvc.TagHelpers.FormTagHelper, Microsoft.AspNetCore.Mvc.TagHelpers
Примечание.
Razor Страницы автоматически защищены от XSRF/CSRF. Дополнительные сведения см. в разделе XSRF/CSRF и Razor Pages.
Наиболее распространенный подход к защите от атак CSRF — использовать шаблон токена синхронизатора (STP). STP используется, когда пользователь запрашивает страницу с данными формы:
- Сервер отправляет маркер, связанный с удостоверением текущего пользователя клиенту.
- Клиент отправляет маркер на сервер для проверки.
- Если сервер получает маркер, который не соответствует удостоверению пользователя, прошедшего проверку подлинности, запрос отклоняется.
Токен является уникальным и непредсказуемым. Маркер также можно использовать для обеспечения правильной последовательности запросов (например, обеспечения последовательности запросов: страницы 1 > страницы 2 > страницы 3). Все формы в ASP.NET шаблонах Core MVC и Razor Pages создают маркеры защиты от подделки. Следующая пара примеров представления создает маркеры антифоргерии:
<form asp-controller="Todo" asp-action="Create" method="post">
...
</form>
@using (Html.BeginForm("Create", "Todo"))
{
...
}
Явно добавьте токен антиподделки в элемент <form> без использования вспомогателей тегов с HTML-вспомогателем @Html.AntiForgeryToken.
<form action="/" method="post">
@Html.AntiForgeryToken()
</form>
В каждом из предыдущих случаев ASP.NET Core добавляет скрытое поле формы, аналогичное следующему примеру:
<input name="__RequestVerificationToken" type="hidden" value="CfDJ8NrAkS ... s2-m9Yw">
ASP.NET Core включает три фильтра для работы с маркерами защиты от подделки:
Параметры защиты от подделок
Настройка AntiforgeryOptions в Startup.ConfigureServices:
services.AddAntiforgery(options =>
{
options.FormFieldName = "AntiforgeryFieldname";
options.HeaderName = "X-CSRF-TOKEN-HEADERNAME";
options.SuppressXFrameOptionsHeader = false;
});
Установите свойства антиподделки cookie, используя свойства класса CookieBuilder, как показано в следующей таблице.
| Вариант | Описание |
|---|---|
| Cookie | Определяет параметры, используемые для создания файлов cookie антивзломной защиты. |
| FormFieldName | Имя скрытого поля формы, используемого системой защиты от подделки для отображения токенов в представлениях. |
| HeaderName | Имя заголовка, используемого антифоргерской системой. Если nullсистема рассматривает только данные формы. |
| SuppressXFrameOptionsHeader | Указывает, следует ли подавлять создание заголовка X-Frame-Options . По умолчанию заголовок создается со значением "SAMEORIGIN". По умолчанию — false. |
Некоторые браузеры не разрешают небезопасным конечным точкам устанавливать файлы cookie с флагом "безопасный" или перезаписывать файлы cookie, флаг безопасности которых установлен (дополнительные сведения см. в разделе "Нерекомендуемые изменения" файлов cookie из небезопасных источников). Так как сочетание безопасных и небезопасных конечных точек является общим сценарием в приложениях, ASP.NET Core смягчает ограничение на безопасную политику для некоторых файлов cookie, таких как antiforgery cookie, установив свойство cookie элемента SecurePolicy на CookieSecurePolicy.None. Даже если злоумышленник украдет маркер антифоргерии cookie, он также должен украсть сам маркер, который обычно отправляется через поле формы (более распространенное) или отдельный заголовок запроса (менее распространенный), а также маркер проверки подлинности cookie.
Cookies для проверки подлинности или авторизации используется более надежная политика, чем CookieSecurePolicy.None.
Кроме того, вы можете защитить от подделки cookie в средах, отличных от Development, используя SSL исключительно по HTTPS с помощью следующей настройки свойства в классе приложения AntiforgeryOptions.Cookie:
public class Startup
{
public Startup(IConfiguration configuration, IHostEnvironment environment)
{
Configuration = configuration;
Environment = environment;
}
public IConfiguration Configuration { get; }
public IHostEnvironment Environment { get; }
public void ConfigureServices(IServiceCollection services)
{
// Other services are registered here
if (!Environment.IsDevelopment())
{
services.AddAntiforgery(o =>
{
o.Cookie.SecurePolicy = CookieSecurePolicy.Always;
});
}
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
// Request processing pipeline
}
}
Дополнительные сведения см. в разделе CookieAuthenticationOptions.
Настройка функций антифальсификации с помощью IAntiforgery
IAntiforgery предоставляет API для настройки функций антифоргерии.
IAntiforgery можно запросить в Configure методе Startup класса.
В следующем примере :
- Промежуточное ПО в приложении используется для создания маркера защиты от подделки и отправки его в ответ как cookie.
- Маркер запроса отправляется как cookie доступный для чтения JavaScript с соглашением по умолчанию об именовании Angular, описанным в разделе AngularJS.
public void Configure(IApplicationBuilder app, IAntiforgery antiforgery)
{
app.Use(next => context =>
{
string path = context.Request.Path.Value;
if (string.Equals(path, "/", StringComparison.OrdinalIgnoreCase) ||
string.Equals(path, "/index.html", StringComparison.OrdinalIgnoreCase))
{
var tokens = antiforgery.GetAndStoreTokens(context);
context.Response.Cookies.Append("XSRF-TOKEN", tokens.RequestToken,
new CookieOptions() { HttpOnly = false });
}
return next(context);
});
}
Требовать антифальсификационной проверки
ValidateAntiForgeryToken — это фильтр действий, который можно применить к отдельному действию, контроллеру или глобально. Запросы, направленные к действиям с этим фильтром, блокируются, если не содержат действительный маркер антифальсификации.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> RemoveLogin(RemoveLoginViewModel account)
{
ManageMessageId? message = ManageMessageId.Error;
var user = await GetCurrentUserAsync();
if (user != null)
{
var result =
await _userManager.RemoveLoginAsync(
user, account.LoginProvider, account.ProviderKey);
if (result.Succeeded)
{
await _signInManager.SignInAsync(user, isPersistent: false);
message = ManageMessageId.RemoveLoginSuccess;
}
}
return RedirectToAction(nameof(ManageLogins), new { Message = message });
}
Атрибут ValidateAntiForgeryToken требует маркер для всех запросов к методам действия, которые он отмечает, включая запросы HTTP GET. Если атрибут ValidateAntiForgeryToken применяется ко всем контроллерам приложения, его можно переопределить с помощью атрибута IgnoreAntiforgeryToken.
Примечание.
ASP.NET Core не поддерживает автоматическое добавление маркеров защиты от подделки в запросы GET.
Автоматическая проверка маркеров защиты от подделки только для небезопасных методов HTTP
ASP.NET приложения Core не создают маркеры защиты от подделки для безопасных методов HTTP (GET, HEAD, OPTIONS и TRACE). Вместо широкого применения атрибута ValidateAntiForgeryToken и переопределения его атрибутами IgnoreAntiforgeryTokenможно использовать атрибут AutoValidateAntiforgeryToken . Этот атрибут работает идентично атрибуту ValidateAntiForgeryToken , за исключением того, что он не требует маркеров для запросов, выполненных с помощью следующих методов HTTP:
- ПОЛУЧИТЬ
- Заголовок
- ПАРАМЕТРЫ
- ТРАССИРОВКА
Рекомендуется использовать AutoValidateAntiforgeryToken широко для сценариев, отличных от API. Этот атрибут гарантирует, что действия POST защищены по умолчанию. Альтернативой является игнорирование маркеров антифоргерии по умолчанию, если ValidateAntiForgeryToken не применяется к отдельным методам действия. Скорее всего, в этом сценарии метод действия POST остается незащищенным по ошибке, оставляя приложение уязвимым к атакам CSRF. Все запросы POST должны отправлять антифорджери-токен.
API не имеют автоматического механизма для отправки той части токена, которая не является cookie. Реализация, вероятно, зависит от реализации клиентского кода. Ниже показаны некоторые примеры:
Пример уровня класса:
[Authorize]
[AutoValidateAntiforgeryToken]
public class ManageController : Controller
{
Глобальный пример:
services.AddControllersWithViews(options =>
options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute()));
Переопределение глобальных атрибутов или атрибутов защиты от подделки в контроллере
Фильтр IgnoreAntiforgeryToken используется для устранения необходимости в токене защиты от подделки для данного действия (или контроллера). При применении этот фильтр переопределяет фильтры ValidateAntiForgeryToken и AutoValidateAntiforgeryToken, указанные на более высоком уровне (глобально или на контроллере).
[Authorize]
[AutoValidateAntiforgeryToken]
public class ManageController : Controller
{
[HttpPost]
[IgnoreAntiforgeryToken]
public async Task<IActionResult> DoSomethingSafe(SomeViewModel model)
{
// no antiforgery token required
}
}
Обновление токенов после аутентификации
Маркеры должны обновляться после проверки подлинности пользователя, перенаправляя пользователя на страницу представления или Razor страницы.
JavaScript, AJAX и SPA
В традиционных приложениях на основе HTML маркеры защиты от подмен передаются серверу с помощью скрытых полей формы. В современных приложениях и spAs на основе JavaScript многие запросы выполняются программными средствами. Эти запросы AJAX могут использовать другие методы (например, заголовки запросов или файлы cookie) для отправки маркера.
Если файлы cookie используются для хранения маркеров проверки подлинности и проверки подлинности запросов API на сервере, CSRF является потенциальной проблемой. Если локальное хранилище используется для хранения маркера, уязвимость CSRF может быть устранена, так как значения из локального хранилища не отправляются автоматически на сервер с каждым запросом. Использование локального хранилища для хранения маркера защиты от подделки на клиенте и отправка маркера в качестве заголовка запроса рекомендуется.
JavaScript
Используя JavaScript в представлениях, маркер можно создать через службу непосредственно в представлении. Внедрите службу IAntiforgery в представление и вызовите GetAndStoreTokens.
@{
ViewData["Title"] = "AJAX Demo";
}
@inject Microsoft.AspNetCore.Antiforgery.IAntiforgery Xsrf
@functions{
public string GetAntiXsrfRequestToken()
{
return Xsrf.GetAndStoreTokens(Context).RequestToken;
}
}
<input type="hidden" id="RequestVerificationToken"
name="RequestVerificationToken" value="@GetAntiXsrfRequestToken()">
<h2>@ViewData["Title"].</h2>
<h3>@ViewData["Message"]</h3>
<div class="row">
<p><input type="button" id="antiforgery" value="Antiforgery"></p>
<script>
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (xhttp.readyState == XMLHttpRequest.DONE) {
if (xhttp.status == 200) {
alert(xhttp.responseText);
} else {
alert('There was an error processing the AJAX request.');
}
}
};
document.addEventListener('DOMContentLoaded', function() {
document.getElementById("antiforgery").onclick = function () {
xhttp.open('POST', '@Url.Action("Antiforgery", "Home")', true);
xhttp.setRequestHeader("RequestVerificationToken",
document.getElementById('RequestVerificationToken').value);
xhttp.send();
}
});
</script>
</div>
Этот подход устраняет необходимость непосредственной настройки файлов cookie с сервера или их чтения от клиента.
В предыдущем примере используется JavaScript для чтения значения скрытого поля для заголовка AJAX POST.
JavaScript также может получить доступ к токенам в файлах cookie и использовать содержимое cookie для создания заголовка с токеном.
context.Response.Cookies.Append("CSRF-TOKEN", tokens.RequestToken,
new Microsoft.AspNetCore.Http.CookieOptions { HttpOnly = false });
Если скрипт запрашивает отправку маркера в заголовке с именем X-CSRF-TOKEN, настройте службу защиты от подделки для поиска заголовка X-CSRF-TOKEN :
services.AddAntiforgery(options => options.HeaderName = "X-CSRF-TOKEN");
В следующем примере используется JavaScript для выполнения запроса AJAX с соответствующим заголовком:
function getCookie(cname) {
var name = cname + "=";
var decodedCookie = decodeURIComponent(document.cookie);
var ca = decodedCookie.split(';');
for (var i = 0; i < ca.length; i++) {
var c = ca[i];
while (c.charAt(0) === ' ') {
c = c.substring(1);
}
if (c.indexOf(name) === 0) {
return c.substring(name.length, c.length);
}
}
return "";
}
var csrfToken = getCookie("CSRF-TOKEN");
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function () {
if (xhttp.readyState === XMLHttpRequest.DONE) {
if (xhttp.status === 204) {
alert('Todo item is created successfully.');
} else {
alert('There was an error processing the AJAX request.');
}
}
};
xhttp.open('POST', '/api/items', true);
xhttp.setRequestHeader("Content-type", "application/json");
xhttp.setRequestHeader("X-CSRF-TOKEN", csrfToken);
xhttp.send(JSON.stringify({ "name": "Learn C#" }));
AngularJS
AngularJS использует стандартный метод для решения проблемы CSRF. Если сервер отправляет cookie с именем XSRF-TOKEN, сервис AngularJS $http добавляет значение cookie в заголовок при отправке запроса на сервер. Этот процесс автоматический. Клиенту не нужно явно задавать заголовок. Имя заголовка — X-XSRF-TOKEN. Сервер должен обнаружить этот заголовок и проверить его содержимое.
Чтобы ASP.NET Core API работал с этим соглашением при запуске приложения:
- Настройте приложение для передачи токена в cookie, называемом
XSRF-TOKEN. - Настройте службу защиты от подделок для поиска заголовка с именем
X-XSRF-TOKEN, которая используется в Angular по умолчанию для отправки XSRF-токена.
public void Configure(IApplicationBuilder app, IAntiforgery antiforgery)
{
app.Use(next => context =>
{
string path = context.Request.Path.Value;
if (
string.Equals(path, "/", StringComparison.OrdinalIgnoreCase) ||
string.Equals(path, "/index.html", StringComparison.OrdinalIgnoreCase))
{
var tokens = antiforgery.GetAndStoreTokens(context);
context.Response.Cookies.Append("XSRF-TOKEN", tokens.RequestToken,
new CookieOptions() { HttpOnly = false });
}
return next(context);
});
}
public void ConfigureServices(IServiceCollection services)
{
services.AddAntiforgery(options => options.HeaderName = "X-XSRF-TOKEN");
}
Примечание.
Если антифальсификационный маркер указан как в заголовке запроса, так и в полезных данных формы, проверяется только маркер в заголовке.
файлы cookie аутентификации Windows и защиты от подделки
При использовании проверки подлинности Windows конечные точки приложений должны быть защищены от атак CSRF так же, как и для файлов cookie. Браузер неявно отправляет контекст проверки подлинности серверу и поэтому конечные точки должны быть защищены от атак CSRF.
Расширить защиту от подделок
Тип IAntiforgeryAdditionalDataProvider позволяет разработчикам расширить поведение системы защиты от CSRF путем обхода дополнительных данных в каждом токене. Метод GetAdditionalData вызывается каждый раз при создании маркера поля, а возвращаемое значение внедрено в созданный маркер. Реализующий может возвращать метку времени, nonce или любое другое значение, а затем вызывать ValidateAdditionalData для проверки этих данных при проверке этого токена. Имя пользователя клиента уже внедрено в созданные маркеры, поэтому не нужно включать эти сведения. Если в маркере содержатся дополнительные данные, но IAntiForgeryAdditionalDataProvider не настроен, то дополнительные данные не проверяются.
Дополнительные ресурсы
ASP.NET Core