События
Чемпионат мира Power BI DataViz
14 февр., 16 - 31 мар., 16
С 4 шансами войти, вы можете выиграть пакет конференции и сделать его в LIVE Grand Finale в Лас-Вегасе
ПодробнееЭтот браузер больше не поддерживается.
Выполните обновление до Microsoft Edge, чтобы воспользоваться новейшими функциями, обновлениями для системы безопасности и технической поддержкой.
Подделка межсайтовых запросов — это атака на веб-приложения, в которых вредоносное веб-приложение может повлиять на взаимодействие между клиентским браузером и веб-приложением, которое доверяет браузеру. Эти атаки возможны, так как веб-браузеры автоматически отправляют некоторые типы маркеров проверки подлинности с каждым запросом на веб-сайт. Эта форма эксплойта также называется атакой одного щелчка или ездой на сеансе, так как атака использует ранее прошедший проверку подлинности сеанс пользователя. Подделка межсайтовых запросов также называется 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
с контекстом проверки подлинности пользователя и может выполнять любое действие, которое разрешено выполнить пользователю, прошедшему проверку подлинности.
Помимо сценария, когда пользователь выбирает кнопку для отправки формы, вредоносный сайт может:
Эти альтернативные сценарии не требуют никаких действий или входных данных от пользователя, кроме первоначального посещения вредоносного сайта.
Использование HTTPS не предотвращает атаку CSRF. Вредоносный сайт может отправлять https://www.good-banking-site.example.com/
запрос так же легко, как он может отправлять небезопасный запрос.
Некоторые атаки предназначены для конечных точек, реагирующих на запросы GET, в этом случае тег изображения можно использовать для выполнения действия. Эта форма атаки распространена на сайтах форума, которые разрешают изображения, но блокируют JavaScript. Приложения, изменяющие состояние запросов GET, в которых переменные или ресурсы изменяются, уязвимы для вредоносных атак. Запросы GET, изменяющие состояние, небезопасны. Рекомендуется никогда не изменять состояние запроса GET.
Атаки CSRF возможны для веб-приложений, использующих файлы cookie для проверки подлинности, так как:
Однако атаки CSRF не ограничиваются использованием файлов cookie. Например, обычная и дайджест-проверка подлинности также уязвимы. После входа пользователя с помощью базовой или дайджест-проверки подлинности браузер автоматически отправляет учетные данные до окончания сеанса.
В этом контексте сеанс ссылается на сеанс на стороне клиента, в течение которого пользователь проходит проверку подлинности. Он не связан с сеансами на стороне сервера или по промежуточному слоям основных сеансов ASP.NET.
Пользователи могут защищаться от уязвимостей CSRF, принимая меры предосторожности:
Однако уязвимости CSRF являются основной проблемой веб-приложения, а не конечным пользователем.
CookieПроверка подлинности на основе — это популярная форма проверки подлинности. Системы проверки подлинности на основе маркеров растут в популярности, особенно для одностраничных приложений (SPAs).
Когда пользователь проходит проверку подлинности с помощью имени пользователя и пароля, он выдает маркер, содержащий билет проверки подлинности. Маркер можно использовать для проверки подлинности и авторизации. Маркер хранится в виде отправленного cookie с каждым запросом клиента. Создание и проверка этого cookie выполняется с помощью ПО промежуточного Cookie слоя проверки подлинности. ПО промежуточного слоя сериализует субъект-пользователя в зашифрованный cookie. В последующих запросах ПО промежуточного слоя проверяет cookie, повторно создает субъект и назначает субъекту свойству HttpContext.User .
Когда пользователь проходит проверку подлинности, он выдает маркер (а не маркер антифоргерии). Маркер содержит сведения о пользователях в виде утверждений или маркера ссылки, который указывает приложению на состояние пользователя, поддерживаемое в приложении. Когда пользователь пытается получить доступ к ресурсу, требующий проверки подлинности, маркер отправляется приложению с дополнительным заголовком авторизации в виде маркера носителя. Такой подход делает приложение без отслеживания состояния. В каждом последующем запросе маркер передается в запросе на проверку на стороне сервера. Этот маркер не шифруется; он закодирован. На сервере маркер декодируется для доступа к его информации. Чтобы отправить маркер на последующие запросы, сохраните маркер в локальном хранилище браузера. Размещение маркера в локальном хранилище браузера и его извлечение и использование в качестве маркера носителя обеспечивает защиту от атак CSRF. Однако если приложение будет уязвимо для внедрения скриптов через XSS или скомпрометированный внешний файл JavaScript, кибератака может получить любое значение из локального хранилища и отправить его в себя. ASP.NET Core кодирует все выходные данные на стороне сервера из переменных по умолчанию, что снижает риск XSS. При переопределении этого поведения с помощью Html.Raw или пользовательского кода с ненадежными входными данными можно увеличить риск XSS.
Не беспокойтесь об уязвимости CSRF, если маркер хранится в локальном хранилище браузера. CSRF является проблемой, когда маркер хранится в объекте cookie. Дополнительные сведения см. в примере кода SPA проблемы GitHub с двумя файлами cookie.
Общие среды размещения уязвимы для перехвата сеансов, входа в CSRF и других атак.
Хотя example1.contoso.net
и example2.contoso.net
являются разными узлами, существует неявная связь доверия между узлами в домене *.contoso.net
. Эта неявная связь доверия позволяет потенциально ненадежным узлам влиять на файлы cookie друг друга (политики того же источника, которые управляют запросами AJAX, не обязательно применяются к файлам cookie HTTP).
Атаки, которые используют доверенные файлы cookie между приложениями, размещенными в одном домене, можно предотвратить, не предоставляя общий доступ к доменам. Если каждое приложение размещено в собственном домене, не существует неявных cookie отношений доверия для эксплойтов.
Предупреждение
ASP.NET Core реализует антифоргерию с помощью ASP.NET Core Data Protection. Стек защиты данных должен быть настроен для работы в ферме серверов. Дополнительные сведения см. в разделе "Настройка защиты данных".
По промежуточному слоям защиты добавляется в контейнер внедрения зависимостей при вызове одного из следующих API:Program.cs
Дополнительные сведения см. в разделе "Антифоргерия с минимальными API".
FormTagHelper вставляет маркеры защиты от подделки в элементы HTML-форм. Следующая разметка в Razor файле автоматически создает маркеры антифоргерии:
<form method="post">
<!-- ... -->
</form>
Аналогичным образом создается маркеры антифоргерии по умолчанию, IHtmlHelper.BeginForm если метод формы не является GET.
Автоматическое создание маркеров антифоргерии для элементов формы HTML происходит, когда <form>
тег содержит method="post"
атрибут, и любой из следующих значений имеет значение true:
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.AntiForgeryToken
HTML:
<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 не включает маркеры защиты от подделки. AddControllersWithViews Необходимо вызвать встроенную поддержку маркеров защиты от подделки.
Несколько вкладок, вошедших в систему как разные пользователи, или одна, вошедшая в систему как анонимный пользователь, не поддерживаются.
Настройка AntiforgeryOptions в Program.cs
:
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 . |
Дополнительные сведения см. в разделе CookieAuthenticationOptions.
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);
});
В предыдущем примере задается именованный cookieXSRF-TOKEN
. Клиент может прочитать это cookie и указать его значение в качестве заголовка, присоединенного к запросам AJAX. Например, Angular включает встроенную защиту XSRF, которая считывает именованный cookieXSRF-TOKEN
по умолчанию.
Фильтр действий ValidateAntiForgeryToken можно применить к отдельному действию, контроллеру или глобально. Запросы, сделанные к действиям, которые применяются с этим фильтром, блокируются, если запрос не содержит допустимый маркер антифоргерии:
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Index()
{
// ...
return RedirectToAction();
}
Атрибуту ValidateAntiForgeryToken
требуется маркер для запросов к методам действия, которые он помечает, включая HTTP-запросы GET.
ValidateAntiForgeryToken
Если атрибут применяется к контроллерам приложения, его можно переопределить атрибутомIgnoreAntiforgeryToken
.
Вместо широкого применения атрибута ValidateAntiForgeryToken
и переопределения его атрибутами IgnoreAntiforgeryToken
можно использовать атрибут AutoValidateAntiforgeryToken . Этот атрибут работает идентично атрибуту ValidateAntiForgeryToken
, за исключением того, что он не требует маркеров для запросов, выполненных с помощью следующих методов HTTP:
Рекомендуется использовать AutoValidateAntiforgeryToken
широко для сценариев, отличных от API. Этот атрибут гарантирует, что действия POST защищены по умолчанию. Альтернативой является игнорировать маркеры антифоргерии по умолчанию, если ValidateAntiForgeryToken
к отдельным методам действия не применяется. Скорее всего, в этом сценарии метод действия POST остается незащищенным по ошибке, оставляя приложение уязвимым к атакам CSRF. Все POS-адреса должны отправлять маркер антифоргерии.
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 страницы.
В традиционных приложениях на основе HTML маркеры антифоргерии передаются серверу с помощью скрытых полей формы. В современных приложениях и spAs на основе JavaScript многие запросы выполняются программными средствами. Эти запросы AJAX могут использовать другие методы, такие как заголовки запросов или файлы cookie, для отправки маркера.
Если файлы cookie используются для хранения маркеров проверки подлинности и проверки подлинности запросов API на сервере, CSRF является потенциальной проблемой. Если локальное хранилище используется для хранения маркера, уязвимость CSRF может быть устранена, так как значения из локального хранилища не отправляются автоматически на сервер с каждым запросом. Использование локального хранилища для хранения маркера защиты от подделки на клиенте и отправка маркера в качестве заголовка запроса рекомендуется.
Дополнительные сведения см. в разделе Blazor Core.
С помощью 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
.Если скрипт отправляет маркер в заголовке запроса 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}`
}
Примечание
Если маркер антифоргерии указан как в заголовке запроса, так и в полезных данных формы, проверяется только маркер в заголовке.
Вызов AddAntiforgery и UseAntiforgery(IApplicationBuilder) регистрацию служб защиты от подделки в DI. Маркеры антифоргерии используются для устранения атак на подделку межсайтовых запросов.
var builder = WebApplication.CreateBuilder();
builder.Services.AddAntiforgery();
var app = builder.Build();
app.UseAntiforgery();
app.MapGet("/", () => "Hello World!");
app.Run();
По промежуточному слоям защиты:
Маркер антифоргерии проверяется только в том случае, если:
RequiresValidation=true
.Примечание. При включении вручную ПО промежуточного слоя защиты от подделки должно выполняться после проверки подлинности и ПО промежуточного слоя авторизации, чтобы предотвратить чтение данных формы, если пользователь не прошел проверку подлинности.
По умолчанию минимальные 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();
Post to:
/todo
из формы, созданной конечной /
точкой, успешно выполнена, так как маркер антифоргерии действителен./todo
из формы, созданной /SkipToken
сбоем, потому что антифоргерия не включена./todo2
из формы, созданной конечной /DisableAntiforgery
точкой, завершается успешно, так как антифоргерия не требуется.app.MapPost("/todo", ([FromForm] Todo todo) => Results.Ok(todo));
app.MapPost("/todo2", ([FromForm] Todo todo) => Results.Ok(todo))
.DisableAntiforgery();
При отправке формы без допустимого маркера антифоргерии:
При использовании проверки подлинности 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
с контекстом проверки подлинности пользователя и может выполнять любое действие, которое разрешено выполнить пользователю, прошедшему проверку подлинности.
Помимо сценария, когда пользователь выбирает кнопку для отправки формы, вредоносный сайт может:
Эти альтернативные сценарии не требуют никаких действий или входных данных от пользователя, кроме первоначального посещения вредоносного сайта.
Использование HTTPS не предотвращает атаку CSRF. Вредоносный сайт может отправлять https://www.good-banking-site.example.com/
запрос так же легко, как он может отправлять небезопасный запрос.
Некоторые атаки предназначены для конечных точек, реагирующих на запросы GET, в этом случае тег изображения можно использовать для выполнения действия. Эта форма атаки распространена на сайтах форума, которые разрешают изображения, но блокируют JavaScript. Приложения, изменяющие состояние запросов GET, в которых переменные или ресурсы изменяются, уязвимы для вредоносных атак. Запросы GET, изменяющие состояние, небезопасны. Рекомендуется никогда не изменять состояние запроса GET.
Атаки CSRF возможны для веб-приложений, использующих файлы cookie для проверки подлинности, так как:
Однако атаки CSRF не ограничиваются использованием файлов cookie. Например, обычная и дайджест-проверка подлинности также уязвимы. После входа пользователя с помощью базовой или дайджест-проверки подлинности браузер автоматически отправляет учетные данные до окончания сеанса.
В этом контексте сеанс ссылается на сеанс на стороне клиента, в течение которого пользователь проходит проверку подлинности. Он не связан с сеансами на стороне сервера или по промежуточному слоям основных сеансов ASP.NET.
Пользователи могут защищаться от уязвимостей CSRF, принимая меры предосторожности:
Однако уязвимости CSRF являются основной проблемой веб-приложения, а не конечным пользователем.
CookieПроверка подлинности на основе — это популярная форма проверки подлинности. Системы проверки подлинности на основе маркеров растут в популярности, особенно для одностраничных приложений (SPAs).
Когда пользователь проходит проверку подлинности с помощью имени пользователя и пароля, он выдает маркер, содержащий билет проверки подлинности, который можно использовать для проверки подлинности и авторизации. Маркер хранится в виде отправленного cookie с каждым запросом клиента. Создание и проверка этого cookie выполняется ПО промежуточного Cookie слоя проверки подлинности. ПО промежуточного слоя сериализует субъект-пользователя в зашифрованный cookie. В последующих запросах ПО промежуточного слоя проверяет cookie, повторно создает субъект и назначает субъекту свойству HttpContext.User .
Когда пользователь проходит проверку подлинности, он выдает маркер (а не маркер антифоргерии). Маркер содержит сведения о пользователях в виде утверждений или маркера ссылки, который указывает приложению на состояние пользователя, поддерживаемое в приложении. Когда пользователь пытается получить доступ к ресурсу, требующий проверки подлинности, маркер отправляется приложению с дополнительным заголовком авторизации в виде маркера носителя. Такой подход делает приложение без отслеживания состояния. В каждом последующем запросе маркер передается в запросе на проверку на стороне сервера. Этот маркер не шифруется; он закодирован. На сервере маркер декодируется для доступа к его информации. Чтобы отправить маркер на последующие запросы, сохраните маркер в локальном хранилище браузера. Размещение маркера в локальном хранилище браузера и его извлечение и использование в качестве маркера носителя обеспечивает защиту от атак CSRF. Тем не менее, если приложение будет уязвимо для внедрения скриптов через XSS или скомпрометированный внешний файл javascript, кибератака может получить любое значение из локального хранилища и отправить его в себя. ASP.NET Core кодирует все выходные данные на стороне сервера из переменных по умолчанию, что снижает риск XSS. При переопределении этого поведения с помощью Html.Raw или пользовательского кода с ненадежными входными данными можно увеличить риск XSS.
Не беспокойтесь об уязвимости CSRF, если маркер хранится в локальном хранилище браузера. CSRF является проблемой, когда маркер хранится в объекте cookie. Дополнительные сведения см. в примере кода SPA проблемы GitHub с двумя файлами cookie.
Среды общего размещения уязвимы для перехвата сеанса, входа CSRF и других атак.
Хотя example1.contoso.net
и example2.contoso.net
являются разными узлами, существует неявная связь доверия между узлами в домене *.contoso.net
. Эта неявная связь доверия позволяет потенциально ненадежным узлам влиять на файлы cookie друг друга (политики того же источника, которые управляют запросами AJAX, не обязательно применяются к файлам cookie HTTP).
Атаки, которые используют доверенные файлы cookie между приложениями, размещенными в одном домене, можно предотвратить, не предоставляя общий доступ к доменам. Если каждое приложение размещено в собственном домене, не существует неявных cookie отношений доверия для эксплойтов.
Предупреждение
ASP.NET Core реализует антифоргерию с помощью ASP.NET Core Data Protection. Стек защиты данных должен быть настроен для работы в ферме серверов. Дополнительные сведения см. в разделе "Настройка защиты данных".
По промежуточному слоям защиты добавляется в контейнер внедрения зависимостей при вызове одного из следующих API:Program.cs
FormTagHelper вставляет маркеры защиты от подделки в элементы HTML-форм. Следующая разметка в Razor файле автоматически создает маркеры антифоргерии:
<form method="post">
<!-- ... -->
</form>
Аналогичным образом создается маркеры антифоргерии по умолчанию, IHtmlHelper.BeginForm если метод формы не является GET.
Автоматическое создание маркеров антифоргерии для элементов формы HTML происходит, когда <form>
тег содержит method="post"
атрибут, и любой из следующих значений имеет значение true:
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.AntiForgeryToken
HTML:
<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 не включает маркеры защиты от подделки. AddControllersWithViews Необходимо вызвать встроенную поддержку маркеров защиты от подделки.
С помощью шаблона маркера синхронизатора только последняя загруженная страница содержит допустимый маркер антифоргерии. Использование нескольких вкладок может быть проблематичным. Например, если пользователь открывает несколько вкладок:
Antiforgery token validation failed. The antiforgery cookie token and request token do not match
Если это представляет проблему, рассмотрите альтернативные шаблоны защиты CSRF.
Настройка AntiforgeryOptions в Program.cs
:
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 . |
Дополнительные сведения см. в разделе CookieAuthenticationOptions.
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);
});
В предыдущем примере задается именованный cookieXSRF-TOKEN
. Клиент может прочитать это cookie и указать его значение в качестве заголовка, присоединенного к запросам AJAX. Например, Angular включает встроенную защиту XSRF, которая считывает именованный cookieXSRF-TOKEN
по умолчанию.
Фильтр действий ValidateAntiForgeryToken можно применить к отдельному действию, контроллеру или глобально. Запросы, сделанные к действиям, которые применяются с этим фильтром, блокируются, если запрос не содержит допустимый маркер антифоргерии:
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Index()
{
// ...
return RedirectToAction();
}
Атрибуту ValidateAntiForgeryToken
требуется маркер для запросов к методам действия, которые он помечает, включая HTTP-запросы GET.
ValidateAntiForgeryToken
Если атрибут применяется к контроллерам приложения, его можно переопределить атрибутомIgnoreAntiforgeryToken
.
Вместо широкого применения атрибута ValidateAntiForgeryToken
и переопределения его атрибутами IgnoreAntiforgeryToken
можно использовать атрибут AutoValidateAntiforgeryToken . Этот атрибут работает идентично атрибуту ValidateAntiForgeryToken
, за исключением того, что он не требует маркеров для запросов, выполненных с помощью следующих методов HTTP:
Рекомендуется использовать AutoValidateAntiforgeryToken
широко для сценариев, отличных от API. Этот атрибут гарантирует, что действия POST защищены по умолчанию. Альтернативой является игнорировать маркеры антифоргерии по умолчанию, если ValidateAntiForgeryToken
к отдельным методам действия не применяется. Скорее всего, в этом сценарии метод действия POST остается незащищенным по ошибке, оставляя приложение уязвимым к атакам CSRF. Все POS-адреса должны отправлять маркер антифоргерии.
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 страницы.
В традиционных приложениях на основе HTML маркеры антифоргерии передаются серверу с помощью скрытых полей формы. В современных приложениях и spAs на основе JavaScript многие запросы выполняются программными средствами. Эти запросы AJAX могут использовать другие методы (например, заголовки запросов или файлы cookie) для отправки маркера.
Если файлы cookie используются для хранения маркеров проверки подлинности и проверки подлинности запросов API на сервере, CSRF является потенциальной проблемой. Если локальное хранилище используется для хранения маркера, уязвимость CSRF может быть устранена, так как значения из локального хранилища не отправляются автоматически на сервер с каждым запросом. Использование локального хранилища для хранения маркера защиты от подделки на клиенте и отправка маркера в качестве заголовка запроса рекомендуется.
С помощью 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
.Если скрипт отправляет маркер в заголовке запроса 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}`
}
Примечание
Если маркер антифоргерии указан как в заголовке запроса, так и в полезных данных формы, проверяется только маркер в заголовке.
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();
При использовании проверки подлинности 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
с контекстом проверки подлинности пользователя и может выполнять любое действие, которое разрешено выполнить пользователю, прошедшему проверку подлинности.
Помимо сценария, когда пользователь выбирает кнопку для отправки формы, вредоносный сайт может:
Эти альтернативные сценарии не требуют никаких действий или входных данных от пользователя, кроме первоначального посещения вредоносного сайта.
Использование HTTPS не предотвращает атаку CSRF. Вредоносный сайт может отправлять https://www.good-banking-site.example.com/
запрос так же легко, как он может отправлять небезопасный запрос.
Некоторые атаки предназначены для конечных точек, реагирующих на запросы GET, в этом случае тег изображения можно использовать для выполнения действия. Эта форма атаки распространена на сайтах форума, которые разрешают изображения, но блокируют JavaScript. Приложения, изменяющие состояние запросов GET, в которых переменные или ресурсы изменяются, уязвимы для вредоносных атак. Запросы GET, изменяющие состояние, небезопасны. Рекомендуется никогда не изменять состояние запроса GET.
Атаки CSRF возможны для веб-приложений, использующих файлы cookie для проверки подлинности, так как:
Однако атаки CSRF не ограничиваются использованием файлов cookie. Например, обычная и дайджест-проверка подлинности также уязвимы. После входа пользователя с помощью базовой или дайджест-проверки подлинности браузер автоматически отправляет учетные данные до окончания сеанса.
В этом контексте сеанс ссылается на сеанс на стороне клиента, в течение которого пользователь проходит проверку подлинности. Он не связан с сеансами на стороне сервера или по промежуточному слоям основных сеансов ASP.NET.
Пользователи могут защищаться от уязвимостей CSRF, принимая меры предосторожности:
Однако уязвимости CSRF являются основной проблемой веб-приложения, а не конечным пользователем.
CookieПроверка подлинности на основе — это популярная форма проверки подлинности. Системы проверки подлинности на основе маркеров растут в популярности, особенно для одностраничных приложений (SPAs).
Когда пользователь проходит проверку подлинности с помощью имени пользователя и пароля, он выдает маркер, содержащий билет проверки подлинности, который можно использовать для проверки подлинности и авторизации. Маркер хранится в виде отправленного cookie с каждым запросом клиента. Создание и проверка этого cookie выполняется ПО промежуточного Cookie слоя проверки подлинности. ПО промежуточного слоя сериализует субъект-пользователя в зашифрованный cookie. В последующих запросах ПО промежуточного слоя проверяет cookie, повторно создает субъект и назначает субъекту свойству HttpContext.User .
Когда пользователь проходит проверку подлинности, он выдает маркер (а не маркер антифоргерии). Маркер содержит сведения о пользователях в виде утверждений или маркера ссылки, который указывает приложению на состояние пользователя, поддерживаемое в приложении. Когда пользователь пытается получить доступ к ресурсу, требующий проверки подлинности, маркер отправляется приложению с дополнительным заголовком авторизации в виде маркера носителя. Такой подход делает приложение без отслеживания состояния. В каждом последующем запросе маркер передается в запросе на проверку на стороне сервера. Этот маркер не шифруется; он закодирован. На сервере маркер декодируется для доступа к его информации. Чтобы отправить маркер на последующие запросы, сохраните маркер в локальном хранилище браузера. Не беспокойтесь об уязвимости CSRF, если маркер хранится в локальном хранилище браузера. CSRF является проблемой, когда маркер хранится в объекте cookie. Дополнительные сведения см. в примере кода SPA проблемы GitHub с двумя файлами cookie.
Среды общего размещения уязвимы для перехвата сеанса, входа CSRF и других атак.
Хотя example1.contoso.net
и example2.contoso.net
являются разными узлами, существует неявная связь доверия между узлами в домене *.contoso.net
. Эта неявная связь доверия позволяет потенциально ненадежным узлам влиять на файлы cookie друг друга (политики того же источника, которые управляют запросами AJAX, не обязательно применяются к файлам cookie HTTP).
Атаки, которые используют доверенные файлы cookie между приложениями, размещенными в одном домене, можно предотвратить, не предоставляя общий доступ к доменам. Если каждое приложение размещено в собственном домене, не существует неявных cookie отношений доверия для эксплойтов.
Предупреждение
ASP.NET Core реализует антифоргерию с помощью ASP.NET Core Data Protection. Стек защиты данных должен быть настроен для работы в ферме серверов. Дополнительные сведения см. в разделе "Настройка защиты данных".
По промежуточному слоям защиты добавляется в контейнер внедрения зависимостей при вызове одного из следующих API:Program.cs
FormTagHelper вставляет маркеры защиты от подделки в элементы HTML-форм. Следующая разметка в Razor файле автоматически создает маркеры антифоргерии:
<form method="post">
<!-- ... -->
</form>
Аналогичным образом создается маркеры антифоргерии по умолчанию, IHtmlHelper.BeginForm если метод формы не является GET.
Автоматическое создание маркеров антифоргерии для элементов формы HTML происходит, когда <form>
тег содержит method="post"
атрибут, и любой из следующих значений имеет значение true:
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.AntiForgeryToken
HTML:
<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 не включает маркеры защиты от подделки. AddControllersWithViews Необходимо вызвать встроенную поддержку маркеров защиты от подделки.
С помощью шаблона маркера синхронизатора только последняя загруженная страница содержит допустимый маркер антифоргерии. Использование нескольких вкладок может быть проблематичным. Например, если пользователь открывает несколько вкладок:
Antiforgery token validation failed. The antiforgery cookie token and request token do not match
Если это представляет проблему, рассмотрите альтернативные шаблоны защиты CSRF.
Настройка AntiforgeryOptions в Program.cs
:
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 . |
Дополнительные сведения см. в разделе CookieAuthenticationOptions.
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);
});
В предыдущем примере задается именованный cookieXSRF-TOKEN
. Клиент может прочитать это cookie и указать его значение в качестве заголовка, присоединенного к запросам AJAX. Например, Angular включает встроенную защиту XSRF, которая считывает именованный cookieXSRF-TOKEN
по умолчанию.
Фильтр действий ValidateAntiForgeryToken можно применить к отдельному действию, контроллеру или глобально. Запросы, сделанные к действиям, которые применяются с этим фильтром, блокируются, если запрос не содержит допустимый маркер антифоргерии:
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Index()
{
// ...
return RedirectToAction();
}
Атрибуту ValidateAntiForgeryToken
требуется маркер для запросов к методам действия, которые он помечает, включая HTTP-запросы GET.
ValidateAntiForgeryToken
Если атрибут применяется к контроллерам приложения, его можно переопределить атрибутомIgnoreAntiforgeryToken
.
Вместо широкого применения атрибута ValidateAntiForgeryToken
и переопределения его атрибутами IgnoreAntiforgeryToken
можно использовать атрибут AutoValidateAntiforgeryToken . Этот атрибут работает идентично атрибуту ValidateAntiForgeryToken
, за исключением того, что он не требует маркеров для запросов, выполненных с помощью следующих методов HTTP:
Рекомендуется использовать AutoValidateAntiforgeryToken
широко для сценариев, отличных от API. Этот атрибут гарантирует, что действия POST защищены по умолчанию. Альтернативой является игнорировать маркеры антифоргерии по умолчанию, если ValidateAntiForgeryToken
к отдельным методам действия не применяется. Скорее всего, в этом сценарии метод действия POST остается незащищенным по ошибке, оставляя приложение уязвимым к атакам CSRF. Все POS-адреса должны отправлять маркер антифоргерии.
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 страницы.
В традиционных приложениях на основе HTML маркеры антифоргерии передаются серверу с помощью скрытых полей формы. В современных приложениях и spAs на основе JavaScript многие запросы выполняются программными средствами. Эти запросы AJAX могут использовать другие методы (например, заголовки запросов или файлы cookie) для отправки маркера.
Если файлы cookie используются для хранения маркеров проверки подлинности и проверки подлинности запросов API на сервере, CSRF является потенциальной проблемой. Если локальное хранилище используется для хранения маркера, уязвимость CSRF может быть устранена, так как значения из локального хранилища не отправляются автоматически на сервер с каждым запросом. Использование локального хранилища для хранения маркера защиты от подделки на клиенте и отправка маркера в качестве заголовка запроса рекомендуется.
С помощью 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}`
}
При использовании проверки подлинности 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
с контекстом проверки подлинности пользователя и может выполнять любое действие, которое разрешено выполнить пользователю, прошедшему проверку подлинности.
Помимо сценария, когда пользователь выбирает кнопку для отправки формы, вредоносный сайт может:
Эти альтернативные сценарии не требуют никаких действий или входных данных от пользователя, кроме первоначального посещения вредоносного сайта.
Использование HTTPS не предотвращает атаку CSRF. Вредоносный сайт может отправлять https://www.good-banking-site.example.com/
запрос так же легко, как он может отправлять небезопасный запрос.
Некоторые атаки предназначены для конечных точек, реагирующих на запросы GET, в этом случае тег изображения можно использовать для выполнения действия. Эта форма атаки распространена на сайтах форума, которые разрешают изображения, но блокируют JavaScript. Приложения, изменяющие состояние запросов GET, в которых переменные или ресурсы изменяются, уязвимы для вредоносных атак. Запросы GET, изменяющие состояние, небезопасны. Рекомендуется никогда не изменять состояние запроса GET.
Атаки CSRF возможны для веб-приложений, использующих файлы cookie для проверки подлинности, так как:
Однако атаки CSRF не ограничиваются использованием файлов cookie. Например, обычная и дайджест-проверка подлинности также уязвимы. После входа пользователя с помощью базовой или дайджест-проверки подлинности браузер автоматически отправляет учетные данные до окончания сеанса.
В этом контексте сеанс ссылается на сеанс на стороне клиента, в течение которого пользователь проходит проверку подлинности. Он не связан с сеансами на стороне сервера или по промежуточному слоям основных сеансов ASP.NET.
Пользователи могут защищаться от уязвимостей CSRF, принимая меры предосторожности:
Однако уязвимости CSRF являются основной проблемой веб-приложения, а не конечным пользователем.
CookieПроверка подлинности на основе — это популярная форма проверки подлинности. Системы проверки подлинности на основе маркеров растут в популярности, особенно для одностраничных приложений (SPAs).
Когда пользователь проходит проверку подлинности с помощью имени пользователя и пароля, он выдает маркер, содержащий билет проверки подлинности, который можно использовать для проверки подлинности и авторизации. Маркер хранится в виде отправленного cookie с каждым запросом клиента. Создание и проверка этого cookie выполняется ПО промежуточного Cookie слоя проверки подлинности. ПО промежуточного слоя сериализует субъект-пользователя в зашифрованный cookie. В последующих запросах ПО промежуточного слоя проверяет cookie, повторно создает субъект и назначает субъекту свойству HttpContext.User .
Когда пользователь проходит проверку подлинности, он выдает маркер (а не маркер антифоргерии). Маркер содержит сведения о пользователях в виде утверждений или маркера ссылки, который указывает приложению на состояние пользователя, поддерживаемое в приложении. Когда пользователь пытается получить доступ к ресурсу, требующий проверки подлинности, маркер отправляется приложению с дополнительным заголовком авторизации в виде маркера носителя. Такой подход делает приложение без отслеживания состояния. В каждом последующем запросе маркер передается в запросе на проверку на стороне сервера. Этот маркер не шифруется; он закодирован. На сервере маркер декодируется для доступа к его информации. Чтобы отправить маркер на последующие запросы, сохраните маркер в локальном хранилище браузера. Не беспокойтесь об уязвимости CSRF, если маркер хранится в локальном хранилище браузера. CSRF является проблемой, когда маркер хранится в объекте cookie. Дополнительные сведения см. в примере кода SPA проблемы GitHub с двумя файлами cookie.
Среды общего размещения уязвимы для перехвата сеанса, входа CSRF и других атак.
Хотя example1.contoso.net
и example2.contoso.net
являются разными узлами, существует неявная связь доверия между узлами в домене *.contoso.net
. Эта неявная связь доверия позволяет потенциально ненадежным узлам влиять на файлы cookie друг друга (политики того же источника, которые управляют запросами AJAX, не обязательно применяются к файлам cookie HTTP).
Атаки, которые используют доверенные файлы cookie между приложениями, размещенными в одном домене, можно предотвратить, не предоставляя общий доступ к доменам. Если каждое приложение размещено в собственном домене, не существует неявных cookie отношений доверия для эксплойтов.
Предупреждение
ASP.NET Core реализует антифоргерию с помощью ASP.NET Core Data Protection. Стек защиты данных должен быть настроен для работы в ферме серверов. Дополнительные сведения см. в разделе "Настройка защиты данных".
По промежуточному слоям защиты добавляется в контейнер внедрения зависимостей при вызове одного из следующих API:Startup.ConfigureServices
В ASP.NET Core 2.0 или более поздней версии FormTagHelper внедряет маркеры антифоргерии в элементы формы HTML. Следующая разметка в Razor файле автоматически создает маркеры антифоргерии:
<form method="post">
...
</form>
Аналогичным образом создается маркеры антифоргерии по умолчанию, IHtmlHelper.BeginForm если метод формы не является GET.
Автоматическое создание маркеров антифоргерии для элементов формы HTML происходит, когда <form>
тег содержит method="post"
атрибут, и любой из следующих значений имеет значение true:
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.AntiForgeryToken
HTML:
<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 . |
Дополнительные сведения см. в разделе CookieAuthenticationOptions.
IAntiforgery предоставляет API для настройки функций антифоргерии.
IAntiforgery
можно запросить в Configure
методе Startup
класса.
В следующем примере :
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.
ASP.NET приложения Core не создают маркеры защиты от подделки для безопасных методов HTTP (GET, HEAD, OPTIONS и TRACE). Вместо широкого применения атрибута ValidateAntiForgeryToken
и переопределения его атрибутами IgnoreAntiforgeryToken
можно использовать атрибут AutoValidateAntiforgeryToken . Этот атрибут работает идентично атрибуту ValidateAntiForgeryToken
, за исключением того, что он не требует маркеров для запросов, выполненных с помощью следующих методов HTTP:
Рекомендуется использовать AutoValidateAntiforgeryToken
широко для сценариев, отличных от API. Этот атрибут гарантирует, что действия POST защищены по умолчанию. Альтернативой является игнорировать маркеры антифоргерии по умолчанию, если ValidateAntiForgeryToken
к отдельным методам действия не применяется. Скорее всего, в этом сценарии метод действия POST остается незащищенным по ошибке, оставляя приложение уязвимым к атакам CSRF. Все POS-адреса должны отправлять маркер антифоргерии.
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 страницы.
В традиционных приложениях на основе HTML маркеры антифоргерии передаются серверу с помощью скрытых полей формы. В современных приложениях и spAs на основе JavaScript многие запросы выполняются программными средствами. Эти запросы AJAX могут использовать другие методы (например, заголовки запросов или файлы cookie) для отправки маркера.
Если файлы cookie используются для хранения маркеров проверки подлинности и проверки подлинности запросов API на сервере, CSRF является потенциальной проблемой. Если локальное хранилище используется для хранения маркера, уязвимость CSRF может быть устранена, так как значения из локального хранилища не отправляются автоматически на сервер с каждым запросом. Использование локального хранилища для хранения маркера защиты от подделки на клиенте и отправка маркера в качестве заголовка запроса рекомендуется.
С помощью 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 использует соглашение для решения CSRF. Если сервер отправляет cookie имя XSRF-TOKEN
, служба AngularJS $http
добавляет cookie значение в заголовок при отправке запроса на сервер. Этот процесс автоматический. Клиенту не нужно явно задавать заголовок. Имя заголовка — X-XSRF-TOKEN
. Сервер должен обнаружить этот заголовок и проверить его содержимое.
Чтобы ASP.NET Core API работал с этим соглашением в запуске приложения:
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");
}
Примечание
Если маркер антифоргерии указан как в заголовке запроса, так и в полезных данных формы, проверяется только маркер в заголовке.
При использовании проверки подлинности Windows конечные точки приложений должны быть защищены от атак CSRF так же, как и для файлов cookie. Браузер неявно отправляет контекст проверки подлинности серверу и поэтому конечные точки должны быть защищены от атак CSRF.
Тип IAntiforgeryAdditionalDataProvider позволяет разработчикам расширить поведение системы защиты от CSRF путем обхода дополнительных данных в каждом токене. Метод GetAdditionalData вызывается каждый раз при создании маркера поля, а возвращаемое значение внедрено в созданный маркер. Реализующий может возвращать метку времени, nonce или любое другое значение, а затем вызывать ValidateAdditionalData проверку этих данных при проверке маркера. Имя пользователя клиента уже внедрено в созданные маркеры, поэтому не нужно включать эти сведения. Если маркер содержит дополнительные данные, но не IAntiForgeryAdditionalDataProvider
настроен, дополнительные данные не проверяются.
Отзыв о ASP.NET Core
ASP.NET Core — это проект с открытым исходным кодом. Выберите ссылку, чтобы оставить отзыв:
События
Чемпионат мира Power BI DataViz
14 февр., 16 - 31 мар., 16
С 4 шансами войти, вы можете выиграть пакет конференции и сделать его в LIVE Grand Finale в Лас-Вегасе
ПодробнееОбучение
Модуль
Защита веб-приложения .NET с помощью платформы удостоверений ASP.NET Core - Training
Узнайте, как добавить проверку подлинности и авторизацию в веб-приложение .NET с помощью платформы ASP.NET Core Identity.
Документация
Предотвращение атак с подделкой межсайтовых запросов (CSRF) в ASP.NET MVC
Описывается атака с подделкой межсайтовых запросов (CSRF) и реализация мер по борьбе с CSRF в ASP.NET Web MVC.
Предотвращение межсайтовых сценариев (XSS) в ASP.NET Core
Узнайте о межсайтовых скриптах (XSS) и методах решения этой уязвимости в приложении ASP.NET Core.
Предоставляет сведения о правиле анализа кода CA5391, включая причины нарушений и способы их устранения, а также условия отключения правила.