Attaques empêcher Cross-Site Request Forgery (XSRF/CSRF) dans ASP.NET CorePrevent Cross-Site Request Forgery (XSRF/CSRF) attacks in ASP.NET Core

Par Steve Smith, Fiyaz Hasan, et Rick AndersonBy Steve Smith, Fiyaz Hasan, and Rick Anderson

Falsification de requête intersites (également appelé XSRF ou CSRF, prononcé et navigation voir) est une attaque contre les applications hébergées sur le web par lequel une application web malveillant peut influencer l’interaction entre un navigateur client et une application web qui fait confiance à qui Navigateur.Cross-site request forgery (also known as XSRF or CSRF, pronounced see-surf) 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 certains types de jetons d’authentification automatiquement avec chaque demande à 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 de code malveillant est également appelé un clic attaque ou par vol de session , car l’attaque tire parti de l’utilisateur d’authentifié précédemment session.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.

Un exemple d’une 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 inclut 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 fait confiance à toute demande 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 formulaire action publications sur le site vulnérable, et non vers 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 « cross-site » de falsification de requête Intersites.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 inclut 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 requête s’exécute sur le www.good-banking-site.com serveur avec un contexte de l’authentification de l’utilisateur et peut exécuter toute action pour laquelle 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.

Outre le scénario où l’utilisateur sélectionne le bouton Envoyer le formulaire, le site malveillant pourrait :In addition to the scenario where the user selects the button to submit the form, the malicious site could:

  • Exécuter un script qui envoie automatiquement le formulaire.Run a script that automatically submits the form.
  • Envoyer l’envoi du formulaire sous la forme d’une requête AJAX.Send the form submission as an AJAX request.
  • Masquer le formulaire à l’aide de CSS.Hide the form using CSS.

Ces scénarios alternatifs ne nécessitent aucune action ou une entrée de l’utilisateur autre qu’initialement visitant le site malveillant.These alternative scenarios don't require any action or input from the user other than initially visiting the malicious site.

À l’aide de HTTPS n’empêche pas une attaque CSRF.Using HTTPS doesn't prevent a CSRF attack. Le site malveillant peut envoyer un https://www.good-banking-site.com/ demander tout aussi facilement qu’il peut envoyer une requête 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 les points de terminaison qui répondent aux demandes GET, 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. Ce type d’attaque est courant sur les sites de forum qui permettent des images mais bloquent JavaScript.This form of attack is common on forum sites that permit images but block JavaScript. Les applications qui modifient l’état sur les demandes GET, où les variables ou les ressources sont modifiés, sont vulnérables aux attaques malveillantes.Apps that change state on GET requests, where variables or resources are altered, are vulnerable to malicious attacks. Les requêtes GET qui changent d’état sont non sécurisés. Une bonne pratique consiste à ne jamais changer l’état sur une requête GET.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:

  • Navigateurs stockent des cookies émis par une application web.Browsers store cookies issued by a web app.
  • Les cookies stockés incluent les cookies de session pour les utilisateurs authentifiés.Stored cookies include session cookies for authenticated users.
  • Les navigateurs envoient que tous les cookies associés à un domaine à l’application web chaque demande, quel que soit la façon dont la demande d’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 à exploiter les cookies.However, CSRF attacks aren't limited to exploiting cookies. Par exemple, l’authentification de base et Digest sont également vulnérables.For example, Basic and Digest authentication are also vulnerable. Une fois 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. Il est sans rapport avec les sessions côté serveur ou Middleware de Session ASP.NET Core.It's unrelated to server-side sessions or ASP.NET Core Session Middleware.

Les utilisateurs peuvent se prémunir contre les vulnérabilités CSRF en prenant les précautions :Users can guard against CSRF vulnerabilities by taking precautions:

  • Signature de l’applications web une fois que leur utilisation.Sign off of web apps when finished using them.
  • Cookies du navigateur effacer périodiquement.Clear browser cookies periodically.

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

Principes de base de l’authentificationAuthentication fundamentals

L’authentification basée sur le cookie est un formulaire populaires d’authentification.Cookie-based authentication is a popular form of authentication. Systèmes d’authentification par jeton gagnent en popularité, en particulier pour les Applications à Page unique (SPA).Token-based authentication systems are growing in popularity, especially for Single Page Applications (SPAs).

Lorsqu’un utilisateur s’authentifie à l’aide de leur nom d’utilisateur et le mot de passe, ils sont émis un jeton contenant un ticket d’authentification qui peut ê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é en tant que permet un cookie qui accompagne chaque demande du client.The token is stored as a cookie that accompanies every request the client makes. Génération et la validation de ce cookie sont effectuée par le Middleware Cookie d’authentification.Generating and validating this cookie is performed by the Cookie Authentication Middleware. Le intergiciel (middleware) sérialise un principal d’utilisateur dans un cookie chiffré.The middleware serializes a user principal into an encrypted cookie. Sur les demandes suivantes, le middleware valide le cookie recrée le principal et attribue au principal de la utilisateur propriété du HttpContext.On subsequent requests, the middleware validates the cookie, recreates the principal, and assigns the principal to the User property of HttpContext.

Authentification par jetonToken-based authentication

Lorsqu’un utilisateur est authentifié, ils sont émis un jeton (pas un jeton anti-contrefaçon).When a user is authenticated, they're issued a token (not an antiforgery token). Le jeton contient les informations de l’utilisateur sous la forme de revendications ou un jeton de référence qui pointe l’application à l’état utilisateur mis à jour 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émentaires 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 demande ultérieure, le jeton est passé dans la demande pour la 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ées; il a encodé.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, stocker 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 soyez pas inquiet à une 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.

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

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

Bien que example1.contoso.net et example2.contoso.net sont des hôtes différents, il existe une relation de confiance implicite entre les hôtes sous le *.contoso.net domaine.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 de confiance implicite permet des hôtes potentiellement non fiables affecter des cookies entre eux (les stratégies de même origine qui régissent les demandes AJAX ne s’appliquent obligatoirement 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).

Pour empêcher les attaques qui exploitent les cookies de confiance entre les applications hébergées sur le même domaine, ne pas partager des 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 implicite de cookie à exploiter.When each app is hosted on its own domain, there is no implicit cookie trust relationship to exploit.

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

Avertissement

ASP.NET Core implémente à l’aide d’anti-contrefaçon 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. Consultez configuration de la protection des données pour plus d’informations.See Configuring data protection for more information.

Dans ASP.NET Core 2.0 ou version ultérieure, le FormTagHelper injecte des jetons anti-contrefaçon dans les é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 GET.Similarly, IHtmlHelper.BeginForm generates antiforgery tokens by default if the form's method isn't GET.

La génération automatique des jetons anti-contrefaçon pour les éléments de formulaire HTML se produit lorsque le <form> balise contient le method="post" attribut et une des opérations suivantes sont 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 d’action n’est pas fourni (<form method="post">).The action attribute isn't supplied (<form method="post">).

Vous pouvez désactiver la génération automatique des jetons anti-contrefaçon pour les éléments de formulaire HTML :Automatic generation of antiforgery tokens for HTML form elements can be disabled:

  • Désactiver explicitement des jetons anti-contrefaçon avec le asp-antiforgery attribut :Explicitly disable antiforgery tokens with the asp-antiforgery attribute:

    <form method="post" asp-antiforgery="false">
        ...
    </form>
    
  • L’élément du formulaire est choisi par de Tag Helpers à l’aide du programme d’assistance de balise ! annulations symbole:The form element is opted-out of Tag Helpers by using the Tag Helper ! opt-out symbol:

    <!form method="post">
        ...
    </!form>
    
  • Supprimer le FormTagHelper à partir de la vue.Remove the FormTagHelper from the view. Le FormTagHelper peut être supprimé à partir 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

Pages Razor sont protégés automatiquement contre XSRF/CSRF.Razor Pages are automatically protected from XSRF/CSRF. Pour plus d’informations, consultez XSRF/CSRF et Pages Razor.For more information, see XSRF/CSRF and Razor Pages.

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

  1. Le serveur envoie un jeton associé avec 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 envoie le jeton au serveur pour la 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 à 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 un séquençage correct d’une série de demandes (par exemple, en garantissant la séquence de demande de : la 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). Tous les formulaires dans les modèles ASP.NET Core MVC et les Pages Razor 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"))
{
    ...
}

Ajouter explicitement un jeton anti-contrefaçon pour un <form> élément sans recourir à des Tag Helpers avec le programme d’assistance HTML @Html.AntiForgeryToken :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é similaire à ce qui suit :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 inclut trois filtres pour travailler avec des jetons anti-contrefaçon :ASP.NET Core includes three filters for working with antiforgery tokens:

Options anti-contrefaçonAntiforgery options

Personnaliser 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 l’anti-contrefaçon Cookie propriétés à l’aide des propriétés de la CookieBuilder classe.†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 Le nom du champ de formulaire masqué utilisé par le système anti-contrefaçon pour restituer 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 Le 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 la X-Frame-Options en-tête.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 future version.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 Le nom du cookie.The name of the cookie. Si ne pas définie, le système génère un nom unique commençant par le DefaultCookiePrefix ( ». AspNetCore.Antiforgery. »).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 future version.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 Le 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 future version.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 Le nom du champ de formulaire masqué utilisé par le système anti-contrefaçon pour restituer 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 Le 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 HTTPS est requis par le système anti-contrefaçon.Specifies whether HTTPS is required by the antiforgery system. Si true, les requêtes 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 future version.This property is obsolete and will be removed in a future version. L’alternative recommandée consiste à définir les Cookie.SecurePolicy.The recommended alternative is to set Cookie.SecurePolicy.
SuppressXFrameOptionsHeaderSuppressXFrameOptionsHeader Spécifie s’il faut supprimer la génération de la X-Frame-Options en-tête.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 les 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 le Configure méthode de la Startup classe.IAntiforgery can be requested in the Configure method of the Startup class. L’exemple suivant utilise l’intergiciel (middleware) à partir de la page d’accueil 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 de nommage Angular par défaut est 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 dans le monde entier.ValidateAntiForgeryToken is an action filter that can be applied to an individual action, a controller, or globally. Les demandes effectuées à des actions qui ont ce filtre est appliqué sont bloquées, sauf si la demande inclut 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 });
}

Le ValidateAntiForgeryToken attribut requiert un jeton pour les demandes aux méthodes d’action il décore, y compris les requêtes HTTP GET.The ValidateAntiForgeryToken attribute requires a token for requests to the action methods it decorates, including HTTP GET requests. Si le ValidateAntiForgeryToken attribut est appliqué sur les contrôleurs de l’application, il peut être remplacé par le IgnoreAntiforgeryToken attribut.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 en charge l’ajout automatique des jetons anti-contrefaçon aux demandes GET.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ésAutomatically validate antiforgery tokens for unsafe HTTP methods only

Les applications ASP.NET Core ne pas générer des jetons anti-contrefaçon pour les méthodes HTTP sécurisés (GET, HEAD, 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 largement le ValidateAntiForgeryToken attribut, puis en remplaçant avec IgnoreAntiforgeryToken attributs, la AutoValidateAntiforgeryToken attribut 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 manière identique à la ValidateAntiForgeryToken d’attribut, à ceci près qu’il ne nécessite des jetons pour les demandes effectuées à l’aide de 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 recommandons l’utilisation de AutoValidateAntiforgeryToken largement pour les scénarios non-API.We recommend use of AutoValidateAntiforgeryToken broadly for non-API scenarios. Cela garantit que les actions POST 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é aux méthodes d’action individuelles.The alternative is to ignore antiforgery tokens by default, unless ValidateAntiForgeryToken is applied to individual action methods. Il n’est plus probable que dans ce scénario pour une méthode d’action POST rester pas protégé par erreur, en laissant l’application vulnérable aux attaques par falsification de requête Intersites.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.

API n’ont pas 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. Certains exemples sont présentés ci-dessous :Some examples are shown below:

Exemple de niveau classe :Class-level example:

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

Exemple global :Global example:

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

Remplacement global ou attributs anti-contrefaçon contrôleurOverride global or controller antiforgery attributes

Le IgnoreAntiforgeryToken filtre est utilisé pour éliminer le besoin 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 ValidateAntiForgeryToken et AutoValidateAntiforgeryToken filtres 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
    }
}

Une fois l’authentification des jetons d’actualisationRefresh tokens after authentication

Les jetons doivent être actualisées une fois que l’utilisateur est authentifié en redirigeant l’utilisateur à une vue ou une page Pages Razor.Tokens should be refreshed after the user is authenticated by redirecting the user to a view or Razor Pages page.

JavaScript, AJAX et les applications SPAJavaScript, AJAX, and SPAs

Dans les applications HTML traditionnelles, les jetons anti-contrefaçon sont passés au serveur à l’aide des champs de formulaire masqué.In traditional HTML-based apps, antiforgery tokens are passed to the server using hidden form fields. Dans les applications modernes basées sur JavaScript et les applications SPA, nombre de demandes envoyées par programmation.In modern JavaScript-based apps and SPAs, many requests are made programmatically. Ces demandes AJAX peuvent utiliser d’autres techniques (telles que les en-têtes de requête ou des 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, une vulnérabilité CSRF peut être atténuée, car les valeurs à partir du stockage local ne sont pas automatiquement envoyés 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 envoie le jeton, comme un 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. Injecter le Microsoft.AspNetCore.Antiforgery.IAntiforgery service 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 évite de devoir traiter directement avec la définition des cookies à partir 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 de champ masqué pour l’en-tête AJAX POST.The preceding example uses JavaScript to read the hidden field value for the AJAX POST header.

JavaScript peut également jetons d’accès 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, configurer le service anti-contrefaçon pour rechercher le X-CSRF-TOKEN en-tête :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 requête 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 à l’adresse CSRF.AngularJS uses a convention to address CSRF. Si le serveur envoie un cookie portant le nom XSRF-TOKEN, le AngularJS $http service ajoute la valeur du 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 de définir 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 les API ASP.NET Core travailler avec cette convention dans le démarrage de votre application :For ASP.NET Core API to work with this convention in your application startup:

  • Configurer 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.
  • Configurer 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 anti-contrefaçonExtend antiforgery

Le IAntiForgeryAdditionalDataProvider type permet aux développeurs d’étendre le comportement du système anti-CSRF par les données supplémentaires de l’aller-retour 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. Le GetAdditionalData méthode 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 implémenteur peut retourner un horodatage, une valeur à usage unique ou toute autre valeur, puis appelez ValidateAdditionalData pour valider ces données lorsque le jeton est validé.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. Nom d’utilisateur du client est déjà incorporée dans les jetons générés, il est donc inutile 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 aucune IAntiForgeryAdditionalDataProvider est configuré, les données supplémentaires n’est pas validées.If a token includes supplemental data but no IAntiForgeryAdditionalDataProvider is configured, the supplemental data isn't validated.

Ressources supplémentairesAdditional resources