Empêcher les attaques de falsification de requête intersites (XSRF/CSRF) dans ASP.NET CorePrevent Cross-Site Request Forgery (XSRF/CSRF) attacks in ASP.NET Core

Par Rick Anderson, Fiyaz Hasanet Steve SmithBy Rick Anderson, Fiyaz Hasan, and Steve Smith

La falsification de requête intersite (également appelée XSRF ou CSRF) est une attaque contre les applications hébergées sur le Web, dans laquelle une application Web malveillante peut influencer l’interaction entre un navigateur client et une application Web qui approuve ce navigateur.Cross-site request forgery (also known as XSRF or CSRF) is an attack against web-hosted apps whereby a malicious web app can influence the interaction between a client browser and a web app that trusts that browser. Ces attaques sont possibles, car les navigateurs Web envoient automatiquement certains types de jetons d’authentification à chaque demande adressée à un site Web.These attacks are possible because web browsers send some types of authentication tokens automatically with every request to a website. Cette forme d’exploitation est également connue sous le nom d' attaque en un clic ou d’une session , car l’attaque tire parti de la session précédemment authentifiée de l’utilisateur.This form of exploit is also known as a one-click attack or session riding because the attack takes advantage of the user's previously authenticated session.

Exemple d’attaque CSRF :An example of a CSRF attack:

  1. Un utilisateur se connecte à www.good-banking-site.com à l’aide de l’authentification par formulaire.A user signs into www.good-banking-site.com using forms authentication. Le serveur authentifie l’utilisateur et émet une réponse qui comprend un cookie d’authentification.The server authenticates the user and issues a response that includes an authentication cookie. Le site est vulnérable aux attaques, car il approuve les demandes qu’il reçoit avec un cookie d’authentification valide.The site is vulnerable to attack because it trusts any request that it receives with a valid authentication cookie.

  2. L’utilisateur visite un site malveillant, www.bad-crook-site.com.The user visits a malicious site, www.bad-crook-site.com.

    Le site malveillant, www.bad-crook-site.com, contient un formulaire HTML similaire à ce qui suit :The malicious site, www.bad-crook-site.com, contains an HTML form similar to the following:

    <h1>Congratulations! You're a Winner!</h1>
    <form action="http://good-banking-site.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>
    

    Notez que le action du formulaire est publié sur le site vulnérable, et non sur le site malveillant.Notice that the form's action posts to the vulnerable site, not to the malicious site. Il s’agit de la partie « inter-sites » de CSRF.This is the "cross-site" part of CSRF.

  3. L’utilisateur sélectionne le bouton Envoyer.The user selects the submit button. Le navigateur effectue la demande et insère automatiquement le cookie d’authentification pour le domaine demandé, www.good-banking-site.com.The browser makes the request and automatically includes the authentication cookie for the requested domain, www.good-banking-site.com.

  4. La demande s’exécute sur le serveur de www.good-banking-site.com avec le contexte d’authentification de l’utilisateur et peut effectuer toute action qu’un utilisateur authentifié est autorisé à effectuer.The request runs on the www.good-banking-site.com server with the user's authentication context and can perform any action that an authenticated user is allowed to perform.

En plus du scénario dans lequel l’utilisateur sélectionne le bouton pour envoyer le formulaire, le site malveillant peut :In addition to the scenario where the user selects the button to submit the form, the malicious site could:

  • Exécutez un script qui envoie automatiquement le formulaire.Run a script that automatically submits the form.
  • Envoyer l’envoi de formulaire en tant que requête AJAX.Send the form submission as an AJAX request.
  • Masquez le formulaire en utilisant CSS.Hide the form using CSS.

Ces scénarios alternatifs ne nécessitent aucune action ou entrée de la part de l’utilisateur autre que la visite initiale du site malveillant.These alternative scenarios don't require any action or input from the user other than initially visiting the malicious site.

L’utilisation de HTTPs n’empêche pas une attaque CSRF.Using HTTPS doesn't prevent a CSRF attack. Le site malveillant peut envoyer une demande de https://www.good-banking-site.com/ tout aussi facilement qu’il peut envoyer une demande non sécurisée.The malicious site can send an https://www.good-banking-site.com/ request just as easily as it can send an insecure request.

Certaines attaques ciblent des points de terminaison qui répondent aux demandes d’extraction, auquel cas une balise d’image peut être utilisée pour effectuer l’action.Some attacks target endpoints that respond to GET requests, in which case an image tag can be used to perform the action. Cette forme d’attaque est courante sur les sites de forum qui autorisent les images, mais qui bloquent JavaScript.This form of attack is common on forum sites that permit images but block JavaScript. Les applications qui changent d’État sur les demandes d’extraction, où les variables ou les ressources sont modifiées, sont vulnérables aux attaques malveillantes.Apps that change state on GET requests, where variables or resources are altered, are vulnerable to malicious attacks. Demandes d’obtention dont l’état de modification n’est pas sécurisé. Une meilleure pratique consiste à ne jamais modifier l’état d’une requête d’extraction.GET requests that change state are insecure. A best practice is to never change state on a GET request.

Les attaques CSRF sont possibles pour les applications Web qui utilisent des cookies pour l’authentification, car :CSRF attacks are possible against web apps that use cookies for authentication because:

  • Les navigateurs stockent les cookies émis par une application Web.Browsers store cookies issued by a web app.
  • Les cookies stockés incluent des cookies de session pour les utilisateurs authentifiés.Stored cookies include session cookies for authenticated users.
  • Les navigateurs envoient tous les cookies associés à un domaine à l’application Web à chaque demande, quelle que soit la façon dont la demande à l’application a été générée dans le navigateur.Browsers send all of the cookies associated with a domain to the web app every request regardless of how the request to app was generated within the browser.

Toutefois, les attaques CSRF ne sont pas limitées à l’exploitation des cookies.However, CSRF attacks aren't limited to exploiting cookies. Par exemple, l’authentification de base et Digest est également vulnérable.For example, Basic and Digest authentication are also vulnerable. Une fois qu’un utilisateur se connecte avec l’authentification de base ou Digest, le navigateur envoie automatiquement les informations d’identification jusqu’à ce que la session† se termine.After a user signs in with Basic or Digest authentication, the browser automatically sends the credentials until the session† ends.

†dans ce contexte, session fait référence à la session côté client au cours de laquelle l’utilisateur est authentifié.†In this context, session refers to the client-side session during which the user is authenticated. Elle n’est pas liée aux sessions côté serveur ou aux intergiciels (middleware) de Session ASP.net Core.It's unrelated to server-side sessions or ASP.NET Core Session Middleware.

Les utilisateurs peuvent se protéger contre les vulnérabilités de CSRF en acceptant les précautions suivantes :Users can guard against CSRF vulnerabilities by taking precautions:

  • Déconnectez-vous de Web Apps une fois que vous avez fini de les utiliser.Sign off of web apps when finished using them.
  • Effacez régulièrement les cookies du navigateur.Clear browser cookies periodically.

Toutefois, les vulnérabilités CSRF sont fondamentalement un problème avec l’application Web, et non l’utilisateur final.However, CSRF vulnerabilities are fundamentally a problem with the web app, not the end user.

Notions de base de l’authentificationAuthentication fundamentals

L’authentification basée sur les cookies est une forme d’authentification courante.Cookie-based authentication is a popular form of authentication. Les systèmes d’authentification basés sur les jetons augmentent en popularité, en particulier pour les applications à page unique (SPAs).Token-based authentication systems are growing in popularity, especially for Single Page Applications (SPAs).

Lorsqu’un utilisateur s’authentifie à l’aide de son nom d’utilisateur et de son mot de passe, il reçoit un jeton qui contient un ticket d’authentification pouvant être utilisé pour l’authentification et l’autorisation.When a user authenticates using their username and password, they're issued a token, containing an authentication ticket that can be used for authentication and authorization. Le jeton est stocké sous la forme d’un cookie qui accompagne chaque requête du client.The token is stored as a cookie that accompanies every request the client makes. La génération et la validation de ce cookie sont effectuées par l’intergiciel (middleware) d’authentification des cookies.Generating and validating this cookie is performed by the Cookie Authentication Middleware. L' intergiciel sérialise un principal d’utilisateur dans un cookie chiffré.The middleware serializes a user principal into an encrypted cookie. Lors des demandes suivantes, l’intergiciel valide le cookie, recrée le principal et attribue le principal à la propriété User de HttpContext.On subsequent requests, the middleware validates the cookie, recreates the principal, and assigns the principal to the User property of HttpContext.

Authentification basée sur les jetonsToken-based authentication

Lorsqu’un utilisateur est authentifié, il reçoit un jeton (et non un jeton anti-contrefaçon).When a user is authenticated, they're issued a token (not an antiforgery token). Le jeton contient des informations utilisateur sous la forme de revendications ou d’un jeton de référence qui fait pointer l’application vers l’état utilisateur géré dans l’application.The token contains user information in the form of claims or a reference token that points the app to user state maintained in the app. Lorsqu’un utilisateur tente d’accéder à une ressource nécessitant une authentification, le jeton est envoyé à l’application avec un en-tête d’autorisation supplémentaire sous forme de jeton du porteur.When a user attempts to access a resource requiring authentication, the token is sent to the app with an additional authorization header in form of Bearer token. Cela rend l’application sans État.This makes the app stateless. Dans chaque requête suivante, le jeton est transmis dans la demande de validation côté serveur.In each subsequent request, the token is passed in the request for server-side validation. Ce jeton n’est pas chiffré. elle est encodée.This token isn't encrypted; it's encoded. Sur le serveur, le jeton est décodé pour accéder à ses informations.On the server, the token is decoded to access its information. Pour envoyer le jeton sur les demandes suivantes, stockez le jeton dans le stockage local du navigateur.To send the token on subsequent requests, store the token in the browser's local storage. Ne vous inquiétez pas de la vulnérabilité CSRF si le jeton est stocké dans le stockage local du navigateur.Don't be concerned about CSRF vulnerability if the token is stored in the browser's local storage. CSRF est un problème lorsque le jeton est stocké dans un cookie.CSRF is a concern when the token is stored in a cookie. Pour plus d’informations, consultez l’exemple de code GitHub problème Spa ajoute deux cookies.For more information, see the GitHub issue SPA code sample adds two cookies.

Plusieurs applications hébergées sur un domaineMultiple apps hosted at one domain

Les environnements d’hébergement partagés sont vulnérables au détournement de session, à la CSRF de connexion et à d’autres attaques.Shared hosting environments are vulnerable to session hijacking, login CSRF, and other attacks.

Bien que example1.contoso.net et example2.contoso.net soient des hôtes différents, il existe une relation d’approbation implicite entre les hôtes dans le domaine *.contoso.net.Although example1.contoso.net and example2.contoso.net are different hosts, there's an implicit trust relationship between hosts under the *.contoso.net domain. Cette relation d’approbation implicite permet aux hôtes potentiellement non fiables d’affecter les cookies de l’autre (les stratégies de même origine qui régissent les demandes AJAX ne s’appliquent pas nécessairement aux cookies HTTP).This implicit trust relationship allows potentially untrusted hosts to affect each other's cookies (the same-origin policies that govern AJAX requests don't necessarily apply to HTTP cookies).

Les attaques qui exploitent des cookies approuvés entre des applications hébergées sur le même domaine peuvent être évitées en ne partageant pas de domaines.Attacks that exploit trusted cookies between apps hosted on the same domain can be prevented by not sharing domains. Lorsque chaque application est hébergée sur son propre domaine, il n’existe aucune relation d’approbation de cookie implicite à exploiter.When each app is hosted on its own domain, there is no implicit cookie trust relationship to exploit.

Configuration de l’anti-contrefaçon ASP.NET CoreASP.NET Core antiforgery configuration

Avertissement

ASP.NET Core implémente l’anti-falsification à l’aide de la protection des données ASP.net Core.ASP.NET Core implements antiforgery using ASP.NET Core Data Protection. La pile de protection des données doit être configurée pour fonctionner dans une batterie de serveurs.The data protection stack must be configured to work in a server farm. Pour plus d’informations, consultez Configuration de la protection des données .See Configuring data protection for more information.

L’intergiciel anti-contrefaçon est ajouté au conteneur d' injection de dépendances lorsque l’une des API suivantes est appelée dans Startup.ConfigureServices:Antiforgery middleware is added to the Dependency injection container when one of the following APIs is called in Startup.ConfigureServices:

L’intergiciel anti-contrefaçon est ajouté au conteneur d' injection de dépendances lorsque AddMvc est appelé dans Startup.ConfigureServicesAntiforgery middleware is added to the Dependency injection container when AddMvc is called in Startup.ConfigureServices

Dans ASP.NET Core 2,0 ou version ultérieure, FormTagHelper injecte des jetons anti-contrefaçon dans des éléments de formulaire HTML.In ASP.NET Core 2.0 or later, the FormTagHelper injects antiforgery tokens into HTML form elements. Le balisage suivant dans un fichier Razor génère automatiquement des jetons anti-contrefaçon :The following markup in a Razor file automatically generates antiforgery tokens:

<form method="post">
    ...
</form>

De même, IHtmlHelper. BeginForm génère des jetons anti-contrefaçon par défaut si la méthode du formulaire n’est pas obtenue.Similarly, IHtmlHelper.BeginForm generates antiforgery tokens by default if the form's method isn't GET.

La génération automatique de jetons anti-contrefaçon pour les éléments de formulaire HTML se produit lorsque la balise <form> contient l’attribut method="post" et que l’une des conditions suivantes est remplie :The automatic generation of antiforgery tokens for HTML form elements happens when the <form> tag contains the method="post" attribute and either of the following are true:

  • L’attribut action est vide (action="").The action attribute is empty (action="").
  • L’attribut action n’est pas fourni (<form method="post">).The action attribute isn't supplied (<form method="post">).

La génération automatique de jetons anti-contrefaçon pour les éléments de formulaire HTML peut être désactivée :Automatic generation of antiforgery tokens for HTML form elements can be disabled:

  • Désactivez explicitement les jetons anti-contrefaçon avec l’attribut asp-antiforgery :Explicitly disable antiforgery tokens with the asp-antiforgery attribute:

    <form method="post" asp-antiforgery="false">
        ...
    </form>
    
  • L’élément de formulaire est exclu du balisage tag à l’aide du tag Helper ! symbol opt-out:The form element is opted-out of Tag Helpers by using the Tag Helper ! opt-out symbol:

    <!form method="post">
        ...
    </!form>
    
  • Supprimez le FormTagHelper de la vue.Remove the FormTagHelper from the view. La FormTagHelper peut être supprimée d’une vue en ajoutant la directive suivante à la vue Razor :The FormTagHelper can be removed from a view by adding the following directive to the Razor view:

    @removeTagHelper Microsoft.AspNetCore.Mvc.TagHelpers.FormTagHelper, Microsoft.AspNetCore.Mvc.TagHelpers
    

Notes

Les Razor pages sont automatiquement protégées à partir de XSRF/CSRF.Razor Pages are automatically protected from XSRF/CSRF. Pour plus d’informations, consultez XSRF/CSRF et Razor pages.For more information, see XSRF/CSRF and Razor Pages.

L’approche la plus courante pour la protection contre les attaques CSRF consiste à utiliser le modèle de jeton du synchronisateur (STP).The most common approach to defending against CSRF attacks is to use the Synchronizer Token Pattern (STP). Le protocole STP est utilisé lorsque l’utilisateur demande une page avec des données de formulaire :STP is used when the user requests a page with form data:

  1. Le serveur envoie un jeton associé à l’identité de l’utilisateur actuel au client.The server sends a token associated with the current user's identity to the client.
  2. Le client renvoie le jeton au serveur pour vérification.The client sends back the token to the server for verification.
  3. Si le serveur reçoit un jeton qui ne correspond pas à l’identité de l’utilisateur authentifié, la demande est rejetée.If the server receives a token that doesn't match the authenticated user's identity, the request is rejected.

Le jeton est unique et imprévisible.The token is unique and unpredictable. Le jeton peut également être utilisé pour garantir le séquencement correct d’une série de requêtes (par exemple, en vérifiant la séquence de demande de : page 1 – page 2 – page 3).The token can also be used to ensure proper sequencing of a series of requests (for example, ensuring the request sequence of: page 1 – page 2 – page 3). Toutes les formes dans ASP.NET Core modèles MVC et Razor Pages génèrent des jetons anti-contrefaçon.All of the forms in ASP.NET Core MVC and Razor Pages templates generate antiforgery tokens. Les deux exemples de vue suivants génèrent des jetons anti-contrefaçon :The following pair of view examples generate antiforgery tokens:

<form asp-controller="Manage" asp-action="ChangePassword" method="post">
    ...
</form>

@using (Html.BeginForm("ChangePassword", "Manage"))
{
    ...
}

Ajoutez explicitement un jeton anti-contrefaçon à un élément <form> sans utiliser de balise tag avec le @Html.AntiForgeryTokend’assistance HTML :Explicitly add an antiforgery token to a <form> element without using Tag Helpers with the HTML helper @Html.AntiForgeryToken:

<form action="/" method="post">
    @Html.AntiForgeryToken()
</form>

Dans chacun des cas précédents, ASP.NET Core ajoute un champ de formulaire masqué semblable au suivant :In each of the preceding cases, ASP.NET Core adds a hidden form field similar to the following:

<input name="__RequestVerificationToken" type="hidden" value="CfDJ8NrAkS ... s2-m9Yw">

ASP.NET Core comprend trois filtres pour l’utilisation des jetons anti-contrefaçon :ASP.NET Core includes three filters for working with antiforgery tokens:

Options anti-contrefaçonAntiforgery options

Personnaliser les options anti- contrefaçon dans Startup.ConfigureServices:Customize antiforgery options in Startup.ConfigureServices:

services.AddAntiforgery(options => 
{
    // Set Cookie properties using CookieBuilder properties†.
    options.FormFieldName = "AntiforgeryFieldname";
    options.HeaderName = "X-CSRF-TOKEN-HEADERNAME";
    options.SuppressXFrameOptionsHeader = false;
});

†définir les propriétés anti-contrefaçon Cookie à l’aide des propriétés de la classe CookieBuilder .†Set the antiforgery Cookie properties using the properties of the CookieBuilder class.

OptionOption DescriptionDescription
CookieCookie Détermine les paramètres utilisés pour créer les cookies anti-contrefaçon.Determines the settings used to create the antiforgery cookies.
FormFieldNameFormFieldName Nom du champ de formulaire masqué utilisé par le système anti-contrefaçon pour le rendu des jetons anti-contrefaçon dans les vues.The name of the hidden form field used by the antiforgery system to render antiforgery tokens in views.
HeaderNameHeaderName Nom de l’en-tête utilisé par le système anti-contrefaçon.The name of the header used by the antiforgery system. Si null, le système considère uniquement les données de formulaire.If null, the system considers only form data.
SuppressXFrameOptionsHeaderSuppressXFrameOptionsHeader Spécifie s’il faut supprimer la génération de l’en-tête X-Frame-Options.Specifies whether to suppress generation of the X-Frame-Options header. Par défaut, l’en-tête est généré avec la valeur « SAMEORIGIN ».By default, the header is generated with a value of "SAMEORIGIN". La valeur par défaut est false.Defaults to false.
services.AddAntiforgery(options => 
{
    options.CookieDomain = "contoso.com";
    options.CookieName = "X-CSRF-TOKEN-COOKIENAME";
    options.CookiePath = "Path";
    options.FormFieldName = "AntiforgeryFieldname";
    options.HeaderName = "X-CSRF-TOKEN-HEADERNAME";
    options.RequireSsl = false;
    options.SuppressXFrameOptionsHeader = false;
});
OptionOption DescriptionDescription
CookieCookie Détermine les paramètres utilisés pour créer les cookies anti-contrefaçon.Determines the settings used to create the antiforgery cookies.
CookieDomainCookieDomain Le domaine du cookie.The domain of the cookie. La valeur par défaut est null.Defaults to null. Cette propriété est obsolète et sera supprimée dans une version ultérieure.This property is obsolete and will be removed in a future version. L’alternative recommandée est cookie. domain.The recommended alternative is Cookie.Domain.
CookieNameCookieName Nom du cookie.The name of the cookie. Si la valeur n’est pas définie, le système génère un nom unique à partir de DefaultCookiePrefix (». AspNetCore. anti-contrefaçon.»).If not set, the system generates a unique name beginning with the DefaultCookiePrefix (".AspNetCore.Antiforgery."). Cette propriété est obsolète et sera supprimée dans une version ultérieure.This property is obsolete and will be removed in a future version. L’alternative recommandée est Cookie.Name.The recommended alternative is Cookie.Name.
CookiePathCookiePath Chemin d’accès défini sur le cookie.The path set on the cookie. Cette propriété est obsolète et sera supprimée dans une version ultérieure.This property is obsolete and will be removed in a future version. L’alternative recommandée est cookie. Path.The recommended alternative is Cookie.Path.
FormFieldNameFormFieldName Nom du champ de formulaire masqué utilisé par le système anti-contrefaçon pour le rendu des jetons anti-contrefaçon dans les vues.The name of the hidden form field used by the antiforgery system to render antiforgery tokens in views.
HeaderNameHeaderName Nom de l’en-tête utilisé par le système anti-contrefaçon.The name of the header used by the antiforgery system. Si null, le système considère uniquement les données de formulaire.If null, the system considers only form data.
RequireSslRequireSsl Spécifie si le système anti-contrefaçon exige le protocole HTTPs.Specifies whether HTTPS is required by the antiforgery system. Si true, les demandes non-HTTPs échouent.If true, non-HTTPS requests fail. La valeur par défaut est false.Defaults to false. Cette propriété est obsolète et sera supprimée dans une version ultérieure.This property is obsolete and will be removed in a future version. L’alternative recommandée consiste à définir cookie. SecurePolicy.The recommended alternative is to set Cookie.SecurePolicy.
SuppressXFrameOptionsHeaderSuppressXFrameOptionsHeader Spécifie s’il faut supprimer la génération de l’en-tête X-Frame-Options.Specifies whether to suppress generation of the X-Frame-Options header. Par défaut, l’en-tête est généré avec la valeur « SAMEORIGIN ».By default, the header is generated with a value of "SAMEORIGIN". La valeur par défaut est false.Defaults to false.

Pour plus d’informations, consultez CookieAuthenticationOptions.For more information, see CookieAuthenticationOptions.

Configurer des fonctionnalités anti-contrefaçon avec IAntiforgeryConfigure antiforgery features with IAntiforgery

IAntiforgery fournit l’API pour configurer les fonctionnalités anti-contrefaçon.IAntiforgery provides the API to configure antiforgery features. IAntiforgery peut être demandé dans la méthode Configure de la classe Startup.IAntiforgery can be requested in the Configure method of the Startup class. L’exemple suivant utilise l’intergiciel (middleware) de la page d’hébergement de l’application pour générer un jeton anti-contrefaçon et l’envoyer dans la réponse en tant que cookie (à l’aide de la Convention d’affectation de noms angulaire par défaut décrite plus loin dans cette rubrique) :The following example uses middleware from the app's home page to generate an antiforgery token and send it in the response as a cookie (using the default Angular naming convention described later in this topic):

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))
        {
            // The request token can be sent as a JavaScript-readable cookie, 
            // and Angular uses it by default.
            var tokens = antiforgery.GetAndStoreTokens(context);
            context.Response.Cookies.Append("XSRF-TOKEN", tokens.RequestToken, 
                new CookieOptions() { HttpOnly = false });
        }

        return next(context);
    });
}

Exiger une validation anti-contrefaçonRequire antiforgery validation

ValidateAntiForgeryToken est un filtre d’action qui peut être appliqué à une action individuelle, à un contrôleur ou globalement.ValidateAntiForgeryToken is an action filter that can be applied to an individual action, a controller, or globally. Les demandes adressées aux actions auxquelles ce filtre est appliqué sont bloquées, sauf si la demande comprend un jeton anti-contrefaçon valide.Requests made to actions that have this filter applied are blocked unless the request includes a valid antiforgery token.

[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 });
}

L’attribut ValidateAntiForgeryToken requiert un jeton pour les demandes aux méthodes d’action qu’il marque, y compris les requêtes HTTP d’extraction.The ValidateAntiForgeryToken attribute requires a token for requests to the action methods it marks, including HTTP GET requests. Si l’attribut ValidateAntiForgeryToken est appliqué sur les contrôleurs de l’application, il peut être substitué par l’attribut IgnoreAntiforgeryToken.If the ValidateAntiForgeryToken attribute is applied across the app's controllers, it can be overridden with the IgnoreAntiforgeryToken attribute.

Notes

ASP.NET Core ne prend pas en charge l’ajout de jetons anti-contrefaçon pour la récupération automatique des demandes.ASP.NET Core doesn't support adding antiforgery tokens to GET requests automatically.

Valider automatiquement les jetons anti-contrefaçon pour les méthodes HTTP non sécurisées uniquementAutomatically validate antiforgery tokens for unsafe HTTP methods only

ASP.NET Core applications ne génèrent pas de jetons anti-contrefaçon pour les méthodes HTTP sécurisées (obtenir, tête, OPTIONS et TRACE).ASP.NET Core apps don't generate antiforgery tokens for safe HTTP methods (GET, HEAD, OPTIONS, and TRACE). Au lieu d’appliquer globalement l’attribut ValidateAntiForgeryToken, puis de le remplacer par des attributs IgnoreAntiforgeryToken, l’attribut AutoValidateAntiforgeryToken peut être utilisé.Instead of broadly applying the ValidateAntiForgeryToken attribute and then overriding it with IgnoreAntiforgeryToken attributes, the AutoValidateAntiforgeryToken attribute can be used. Cet attribut fonctionne de la même façon que l’attribut ValidateAntiForgeryToken, sauf qu’il ne requiert pas de jetons pour les demandes effectuées à l’aide des méthodes HTTP suivantes :This attribute works identically to the ValidateAntiForgeryToken attribute, except that it doesn't require tokens for requests made using the following HTTP methods:

  • GETGET
  • HEADHEAD
  • OPTIONSOPTIONS
  • TRACETRACE

Nous vous recommandons d’utiliser AutoValidateAntiforgeryToken pour les scénarios non-API.We recommend use of AutoValidateAntiforgeryToken broadly for non-API scenarios. Cela garantit que les actions de publication sont protégées par défaut.This ensures POST actions are protected by default. L’alternative consiste à ignorer les jetons anti-contrefaçon par défaut, sauf si ValidateAntiForgeryToken est appliqué à des méthodes d’action individuelles.The alternative is to ignore antiforgery tokens by default, unless ValidateAntiForgeryToken is applied to individual action methods. Dans ce scénario, il est plus probable qu’une méthode d’action de publication reste non protégée par erreur, laissant l’application vulnérable aux attaques CSRF.It's more likely in this scenario for a POST action method to be left unprotected by mistake, leaving the app vulnerable to CSRF attacks. Toutes les publications doivent envoyer le jeton anti-contrefaçon.All POSTs should send the antiforgery token.

Les API ne disposent pas d’un mécanisme automatique pour l’envoi de la partie non-cookie du jeton.APIs don't have an automatic mechanism for sending the non-cookie part of the token. L’implémentation dépend probablement de l’implémentation du code client.The implementation probably depends on the client code implementation. Voici quelques exemples :Some examples are shown below:

Exemple de niveau de classe :Class-level example:

[Authorize]
[AutoValidateAntiforgeryToken]
public class ManageController : Controller
{

Exemple global :Global example:

services.AddMvc(options => 
    options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute()));

Remplacer les attributs globaux ou anti-contrefaçon de contrôleurOverride global or controller antiforgery attributes

Le filtre IgnoreAntiforgeryToken est utilisé pour éliminer la nécessité d’un jeton anti-contrefaçon pour une action donnée (ou un contrôleur).The IgnoreAntiforgeryToken filter is used to eliminate the need for an antiforgery token for a given action (or controller). Lorsqu’il est appliqué, ce filtre remplace les filtres ValidateAntiForgeryToken et AutoValidateAntiforgeryToken spécifiés à un niveau supérieur (globalement ou sur un contrôleur).When applied, this filter overrides ValidateAntiForgeryToken and AutoValidateAntiforgeryToken filters specified at a higher level (globally or on a controller).

[Authorize]
[AutoValidateAntiforgeryToken]
public class ManageController : Controller
{
    [HttpPost]
    [IgnoreAntiforgeryToken]
    public async Task<IActionResult> DoSomethingSafe(SomeViewModel model)
    {
        // no antiforgery token required
    }
}

Actualiser les jetons après l’authentificationRefresh tokens after authentication

Les jetons doivent être actualisés une fois l’utilisateur authentifié, en redirigeant l’utilisateur vers une page d’affichage ou de Razor Pages.Tokens should be refreshed after the user is authenticated by redirecting the user to a view or Razor Pages page.

JavaScript, AJAX et SPAsJavaScript, AJAX, and SPAs

Dans les applications HTML traditionnelles, les jetons anti-contrefaçon sont transmis au serveur à l’aide de champs de formulaire masqués.In traditional HTML-based apps, antiforgery tokens are passed to the server using hidden form fields. Dans les applications basées sur JavaScript modernes et en SPAs, de nombreuses demandes sont effectuées par programme.In modern JavaScript-based apps and SPAs, many requests are made programmatically. Ces demandes AJAX peuvent utiliser d’autres techniques (comme les en-têtes de demande ou les cookies) pour envoyer le jeton.These AJAX requests may use other techniques (such as request headers or cookies) to send the token.

Si les cookies sont utilisés pour stocker les jetons d’authentification et pour authentifier les demandes d’API sur le serveur, CSRF est un problème potentiel.If cookies are used to store authentication tokens and to authenticate API requests on the server, CSRF is a potential problem. Si le stockage local est utilisé pour stocker le jeton, la vulnérabilité CSRF peut être atténuée car les valeurs du stockage local ne sont pas envoyées automatiquement au serveur avec chaque demande.If local storage is used to store the token, CSRF vulnerability might be mitigated because values from local storage aren't sent automatically to the server with every request. Par conséquent, l’utilisation du stockage local pour stocker le jeton anti-contrefaçon sur le client et l’envoi du jeton en tant qu’en-tête de demande est une approche recommandée.Thus, using local storage to store the antiforgery token on the client and sending the token as a request header is a recommended approach.

JavaScriptJavaScript

À l’aide de JavaScript avec des vues, le jeton peut être créé à l’aide d’un service à partir de la vue.Using JavaScript with views, the token can be created using a service from within the view. Injectez le service Microsoft. AspNetCore. anticontrefaçon. IAntiforgery dans la vue et appelez GetAndStoreTokens:Inject the Microsoft.AspNetCore.Antiforgery.IAntiforgery service into the view and call 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>

Cette approche élimine le besoin de traiter directement les cookies du serveur ou de les lire à partir du client.This approach eliminates the need to deal directly with setting cookies from the server or reading them from the client.

L’exemple précédent utilise JavaScript pour lire la valeur du champ masqué pour l’en-tête de publication AJAX.The preceding example uses JavaScript to read the hidden field value for the AJAX POST header.

JavaScript peut également accéder à des jetons dans des cookies et utiliser le contenu du cookie pour créer un en-tête avec la valeur du jeton.JavaScript can also access tokens in cookies and use the cookie's contents to create a header with the token's value.

context.Response.Cookies.Append("CSRF-TOKEN", tokens.RequestToken, 
    new Microsoft.AspNetCore.Http.CookieOptions { HttpOnly = false });

En supposant que le script demande à envoyer le jeton dans un en-tête appelé X-CSRF-TOKEN, configurez le service anti-contrefaçon pour Rechercher l’en-tête X-CSRF-TOKEN :Assuming the script requests to send the token in a header called X-CSRF-TOKEN, configure the antiforgery service to look for the X-CSRF-TOKEN header:

services.AddAntiforgery(options => options.HeaderName = "X-CSRF-TOKEN");

L’exemple suivant utilise JavaScript pour effectuer une demande AJAX avec l’en-tête approprié :The following example uses JavaScript to make an AJAX request with the appropriate header:

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 == 200) {
            alert(xhttp.responseText);
        } else {
            alert('There was an error processing the AJAX request.');
        }
    }
};
xhttp.open('POST', '/api/password/changepassword', true);
xhttp.setRequestHeader("Content-type", "application/json");
xhttp.setRequestHeader("X-CSRF-TOKEN", csrfToken);
xhttp.send(JSON.stringify({ "newPassword": "ReallySecurePassword999$$$" }));

AngularJSAngularJS

AngularJS utilise une convention pour traiter CSRF.AngularJS uses a convention to address CSRF. Si le serveur envoie un cookie avec le nom XSRF-TOKEN, le service de $http AngularJS ajoute la valeur de cookie à un en-tête lorsqu’il envoie une demande au serveur.If the server sends a cookie with the name XSRF-TOKEN, the AngularJS $http service adds the cookie value to a header when it sends a request to the server. Ce processus est automatique.This process is automatic. L’en-tête n’a pas besoin d’être défini explicitement dans le client.The header doesn't need to be set in the client explicitly. Le nom d’en-tête est X-XSRF-TOKEN.The header name is X-XSRF-TOKEN. Le serveur doit détecter cet en-tête et valider son contenu.The server should detect this header and validate its contents.

Pour que ASP.NET Core API fonctionne avec cette Convention au démarrage de votre application :For ASP.NET Core API to work with this convention in your application startup:

  • Configurez votre application pour fournir un jeton dans un cookie appelé XSRF-TOKEN.Configure your app to provide a token in a cookie called XSRF-TOKEN.
  • Configurez le service anti-contrefaçon pour rechercher un en-tête nommé X-XSRF-TOKEN.Configure the antiforgery service to look for a header named X-XSRF-TOKEN.
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))
        {
            // The request token can be sent as a JavaScript-readable cookie, 
            // and Angular uses it by default.
            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)
{
    // Angular's default header name for sending the XSRF token.
    services.AddAntiforgery(options => options.HeaderName = "X-XSRF-TOKEN");
}

Affichez ou téléchargez l’exemple de code (procédure de téléchargement)View or download sample code (how to download)

Étendre l’anti-contrefaçonExtend antiforgery

Le type IAntiForgeryAdditionalDataProvider permet aux développeurs d’étendre le comportement du système anti-CSRF en arrondissant les données supplémentaires dans chaque jeton.The IAntiForgeryAdditionalDataProvider type allows developers to extend the behavior of the anti-CSRF system by round-tripping additional data in each token. La méthode GetAdditionalData est appelée chaque fois qu’un jeton de champ est généré, et la valeur de retour est incorporée dans le jeton généré.The GetAdditionalData method is called each time a field token is generated, and the return value is embedded within the generated token. Un responsable de l’implémentation peut retourner un horodateur, une valeur à usage unique ou toute autre valeur, puis appeler ValidateAdditionalData pour valider ces données lors de la validation du jeton.An implementer could return a timestamp, a nonce, or any other value and then call ValidateAdditionalData to validate this data when the token is validated. Le nom d’utilisateur du client étant déjà incorporé dans les jetons générés, il n’est pas nécessaire d’inclure ces informations.The client's username is already embedded in the generated tokens, so there's no need to include this information. Si un jeton contient des données supplémentaires, mais qu’aucune IAntiForgeryAdditionalDataProvider n’est configurée, les données supplémentaires ne sont pas validées.If a token includes supplemental data but no IAntiForgeryAdditionalDataProvider is configured, the supplemental data isn't validated.

Ressources supplémentairesAdditional resources