Evitare attacchi Cross-Site Request Forgery (XSRF/CSRF) in ASP.NET CorePrevent Cross-Site Request Forgery (XSRF/CSRF) attacks in ASP.NET Core

Di Rick Anderson, Fiyaz Hasane Steve SmithBy Rick Anderson, Fiyaz Hasan, and Steve Smith

La richiesta tra siti falsificata (nota anche come XSRF o CSRF) è un attacco contro app ospitate sul Web, in cui un'app Web dannosa può influenzare l'interazione tra un browser client e un'app Web che considera attendibile il browser.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. Questi attacchi sono possibili perché i Web browser inviano automaticamente alcuni tipi di token di autenticazione con ogni richiesta a un sito Web.These attacks are possible because web browsers send some types of authentication tokens automatically with every request to a website. Questa forma di exploit è nota anche come un attacco con un solo clic o una sessione di guida perché l'attacco sfrutta la sessione precedentemente autenticata dell'utente.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.

Esempio di attacco CSRF:An example of a CSRF attack:

  1. Un utente accede www.good-banking-site.com usando l'autenticazione basata su form.A user signs into www.good-banking-site.com using forms authentication. Il server autentica l'utente e genera una risposta che include un cookie di autenticazione.The server authenticates the user and issues a response that includes an authentication cookie. Il sito è vulnerabile agli attacchi poiché considera attendibile qualsiasi richiesta ricevuta con un cookie di autenticazione valido.The site is vulnerable to attack because it trusts any request that it receives with a valid authentication cookie.

  2. L'utente visita un sito dannoso, www.bad-crook-site.com.The user visits a malicious site, www.bad-crook-site.com.

    Il sito dannoso, www.bad-crook-site.com, contiene un form HTML simile al seguente: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>
    

    Si noti che il action del modulo viene pubblicato sul sito vulnerabile, non sul sito dannoso.Notice that the form's action posts to the vulnerable site, not to the malicious site. Si tratta della parte "cross-site" di CSRF.This is the "cross-site" part of CSRF.

  3. L'utente seleziona il pulsante Submit (Invia).The user selects the submit button. Il browser esegue la richiesta e include automaticamente il cookie di autenticazione per il dominio richiesto, 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 richiesta viene eseguita nel server di www.good-banking-site.com con il contesto di autenticazione dell'utente e può eseguire qualsiasi azione che un utente autenticato è autorizzato a eseguire.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.

Oltre allo scenario in cui l'utente seleziona il pulsante per l'invio del modulo, il sito dannoso potrebbe:In addition to the scenario where the user selects the button to submit the form, the malicious site could:

  • Eseguire uno script che invia automaticamente il modulo.Run a script that automatically submits the form.
  • Inviare il modulo inviato come richiesta AJAX.Send the form submission as an AJAX request.
  • Nascondere il form usando CSS.Hide the form using CSS.

Questi scenari alternativi non richiedono alcuna azione o input da parte dell'utente, tranne che inizialmente visitare il sito dannoso.These alternative scenarios don't require any action or input from the user other than initially visiting the malicious site.

L'uso di HTTPS non impedisce un attacco CSRF.Using HTTPS doesn't prevent a CSRF attack. Il sito dannoso può inviare una richiesta di https://www.good-banking-site.com/ con la stessa facilità con cui è possibile inviare una richiesta non protetta.The malicious site can send an https://www.good-banking-site.com/ request just as easily as it can send an insecure request.

Alcuni attacchi hanno come destinazione endpoint che rispondono alle richieste GET, nel qual caso è possibile usare un tag di immagine per eseguire l'azione.Some attacks target endpoints that respond to GET requests, in which case an image tag can be used to perform the action. Questo tipo di attacco è comune nei siti dei forum che consentono le immagini ma bloccano JavaScript.This form of attack is common on forum sites that permit images but block JavaScript. Le app che modificano lo stato di richieste GET, in cui variabili o risorse vengono modificate, sono vulnerabili ad attacchi dannosi.Apps that change state on GET requests, where variables or resources are altered, are vulnerable to malicious attacks. Le richieste GET che cambiano lo stato non sono sicure. Una procedura consigliata consiste nel non modificare mai lo stato di una richiesta GET.GET requests that change state are insecure. A best practice is to never change state on a GET request.

Gli attacchi CSRF sono possibili per le app Web che usano i cookie per l'autenticazione perché:CSRF attacks are possible against web apps that use cookies for authentication because:

  • I browser archiviano i cookie emessi da un'app Web.Browsers store cookies issued by a web app.
  • I cookie archiviati includono i cookie di sessione per gli utenti autenticati.Stored cookies include session cookies for authenticated users.
  • I browser inviano tutti i cookie associati a un dominio all'app Web ogni richiesta, indipendentemente dalla modalità di generazione della richiesta all'app all'interno del browser.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.

Tuttavia, gli attacchi CSRF non sono limitati allo sfruttamento dei cookie.However, CSRF attacks aren't limited to exploiting cookies. Ad esempio, anche l'autenticazione di base e del digest è vulnerabile.For example, Basic and Digest authentication are also vulnerable. Dopo che un utente ha eseguito l'accesso con l'autenticazione di base o del digest, il browser invia automaticamente le credenziali fino al termine della sessione†.After a user signs in with Basic or Digest authentication, the browser automatically sends the credentials until the session† ends.

†in questo contesto, Session fa riferimento alla sessione lato client durante la quale l'utente viene autenticato.†In this context, session refers to the client-side session during which the user is authenticated. Non è correlato alle sessioni sul lato server o al middleware della sessione ASP.NET Core.It's unrelated to server-side sessions or ASP.NET Core Session Middleware.

Gli utenti possono proteggersi da vulnerabilità CSRF adottando le precauzioni seguenti:Users can guard against CSRF vulnerabilities by taking precautions:

  • Disconnettersi dalle app Web al termine dell'uso.Sign off of web apps when finished using them.
  • Cancellare periodicamente i cookie del browser.Clear browser cookies periodically.

Tuttavia, le vulnerabilità CSRF sono fondamentalmente un problema dell'app web, non dell'utente finale.However, CSRF vulnerabilities are fundamentally a problem with the web app, not the end user.

Nozioni fondamentali sull'autenticazioneAuthentication fundamentals

L'autenticazione basata su cookie è una forma comune di autenticazione.Cookie-based authentication is a popular form of authentication. I sistemi di autenticazione basata su token hanno una maggiore popolarità, soprattutto per le applicazioni a pagina singola (Spa).Token-based authentication systems are growing in popularity, especially for Single Page Applications (SPAs).

Quando un utente esegue l'autenticazione usando il nome utente e la password, viene emesso un token contenente un ticket di autenticazione che può essere usato per l'autenticazione e l'autorizzazione.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. Il token viene archiviato come cookie che accompagna ogni richiesta eseguita dal client.The token is stored as a cookie that accompanies every request the client makes. La generazione e la convalida di questo cookie viene eseguita dal middleware di autenticazione dei cookie.Generating and validating this cookie is performed by the Cookie Authentication Middleware. Il middleware serializza un'entità utente in un cookie crittografato.The middleware serializes a user principal into an encrypted cookie. Nelle richieste successive il middleware convalida il cookie, ricrea l'entità e assegna l'entità alla proprietà User di HttpContext.On subsequent requests, the middleware validates the cookie, recreates the principal, and assigns the principal to the User property of HttpContext.

Autenticazione basata su tokenToken-based authentication

Quando un utente viene autenticato, viene emesso un token (non un token antifalsificazione).When a user is authenticated, they're issued a token (not an antiforgery token). Il token contiene informazioni sull'utente sotto forma di attestazioni o un token di riferimento che punta l'app allo stato utente mantenuto nell'app.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. Quando un utente tenta di accedere a una risorsa che richiede l'autenticazione, il token viene inviato all'app con un'intestazione di autorizzazione aggiuntiva nel formato token di connessione.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. Questa operazione rende l'app senza stato.This makes the app stateless. In ogni richiesta successiva il token viene passato nella richiesta di convalida lato server.In each subsequent request, the token is passed in the request for server-side validation. Questo token non è crittografato; è codificato.This token isn't encrypted; it's encoded. Sul server, il token viene decodificato per accedere alle informazioni.On the server, the token is decoded to access its information. Per inviare il token alle richieste successive, archiviare il token nella risorsa di archiviazione locale del browser.To send the token on subsequent requests, store the token in the browser's local storage. Non preoccuparsi della vulnerabilità CSRF se il token è archiviato nella risorsa di archiviazione locale del browser.Don't be concerned about CSRF vulnerability if the token is stored in the browser's local storage. CSRF rappresenta un problema quando il token viene archiviato in un cookie.CSRF is a concern when the token is stored in a cookie. Per ulteriori informazioni, vedere l'esempio di codice di GitHub Issue Spa aggiunge due cookie.For more information, see the GitHub issue SPA code sample adds two cookies.

Più app ospitate in un dominioMultiple apps hosted at one domain

Gli ambienti di hosting condiviso sono vulnerabili al Hijack della sessione, all'account di accesso CSRF e ad altri attacchi.Shared hosting environments are vulnerable to session hijacking, login CSRF, and other attacks.

Sebbene example1.contoso.net e example2.contoso.net siano host diversi, esiste una relazione di trust implicita tra gli host nel dominio *.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. Questa relazione di trust implicita consente a host potenzialmente non attendibili di influenzare gli altri cookie (i criteri di origine identici che regolano le richieste AJAX non si applicano necessariamente ai cookie 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).

Gli attacchi che sfruttano i cookie attendibili tra le app ospitate nello stesso dominio possono essere impediti dalla condivisione dei domini.Attacks that exploit trusted cookies between apps hosted on the same domain can be prevented by not sharing domains. Quando ogni app è ospitata nel proprio dominio, non esiste alcuna relazione di trust con i cookie implicita da sfruttare.When each app is hosted on its own domain, there is no implicit cookie trust relationship to exploit.

ASP.NET Core configurazione antifalsificazioneASP.NET Core antiforgery configuration

Avviso

ASP.NET Core implementa la antifalsificazione usando la protezione dei dati ASP.NET Core.ASP.NET Core implements antiforgery using ASP.NET Core Data Protection. Lo stack di protezione dei dati deve essere configurato in modo da funzionare in un server farm.The data protection stack must be configured to work in a server farm. Per ulteriori informazioni, vedere configurazione della protezione dei dati .See Configuring data protection for more information.

Il middleware antifalsificazione viene aggiunto al contenitore di inserimento delle dipendenze quando una delle API seguenti viene chiamata in Startup.ConfigureServices:Antiforgery middleware is added to the Dependency injection container when one of the following APIs is called in Startup.ConfigureServices:

Il middleware antifalsificazione viene aggiunto al contenitore di inserimento delle dipendenze quando viene chiamato AddMvc in Startup.ConfigureServicesAntiforgery middleware is added to the Dependency injection container when AddMvc is called in Startup.ConfigureServices

In ASP.NET Core 2,0 o versioni successive, FormTagHelper inserisce i token antifalsificazione negli elementi del form HTML.In ASP.NET Core 2.0 or later, the FormTagHelper injects antiforgery tokens into HTML form elements. Il markup seguente in un file Razor genera automaticamente i token antifalsificazione:The following markup in a Razor file automatically generates antiforgery tokens:

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

Analogamente, IHtmlHelper. BeginForm genera token antifalsificazione per impostazione predefinita se il metodo del modulo non è Get.Similarly, IHtmlHelper.BeginForm generates antiforgery tokens by default if the form's method isn't GET.

La generazione automatica dei token antifalsificazione per gli elementi del form HTML si verifica quando il tag <form> contiene l'attributo method="post" e si verifica una delle condizioni seguenti: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'attributo Action è vuoto (action="").The action attribute is empty (action="").
  • L'attributo Action non è specificato (<form method="post">).The action attribute isn't supplied (<form method="post">).

La generazione automatica dei token antifalsificazione per gli elementi del modulo HTML può essere disabilitata:Automatic generation of antiforgery tokens for HTML form elements can be disabled:

  • Disabilitare in modo esplicito i token antifalsificazione con l'attributo asp-antiforgery:Explicitly disable antiforgery tokens with the asp-antiforgery attribute:

    <form method="post" asp-antiforgery="false">
        ...
    </form>
    
  • L'elemento form è escluso dagli Helper tag usando il simbolo Helper tag ! opt-out:The form element is opted-out of Tag Helpers by using the Tag Helper ! opt-out symbol:

    <!form method="post">
        ...
    </!form>
    
  • Rimuovere il FormTagHelper dalla visualizzazione.Remove the FormTagHelper from the view. Il FormTagHelper può essere rimosso da una visualizzazione aggiungendo la direttiva seguente alla visualizzazione 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
    

Nota

Razor Pages vengono protetti automaticamente da XSRF/CSRF.Razor Pages are automatically protected from XSRF/CSRF. Per ulteriori informazioni, vedere XSRF/CSRF e Razor Pages.For more information, see XSRF/CSRF and Razor Pages.

L'approccio più comune alla difesa dagli attacchi CSRF consiste nell'usare il modello di token di sincronizzazione (STP).The most common approach to defending against CSRF attacks is to use the Synchronizer Token Pattern (STP). STP viene usato quando l'utente richiede una pagina con dati del modulo:STP is used when the user requests a page with form data:

  1. Il server invia al client un token associato all'identità dell'utente corrente.The server sends a token associated with the current user's identity to the client.
  2. Il client invia il token al server per la verifica.The client sends back the token to the server for verification.
  3. Se il server riceve un token che non corrisponde all'identità dell'utente autenticato, la richiesta viene rifiutata.If the server receives a token that doesn't match the authenticated user's identity, the request is rejected.

Il token è univoco e imprevedibile.The token is unique and unpredictable. Il token può essere usato anche per garantire la sequenziazione corretta di una serie di richieste, ad esempio per garantire la sequenza di richiesta: pagina 1 – pagina 2 – pagina 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). Tutti i moduli nei modelli ASP.NET Core MVC e Razor Pages generano token antifalsificazione.All of the forms in ASP.NET Core MVC and Razor Pages templates generate antiforgery tokens. La coppia seguente di esempi di viste genera i token antifalsificazione:The following pair of view examples generate antiforgery tokens:

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

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

Aggiungere in modo esplicito un token antifalsificazione a un elemento <form> senza usare gli helper tag con l'helper 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>

In ognuno dei casi precedenti, ASP.NET Core aggiunge un campo del form nascosto simile al seguente: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 include tre filtri per l'utilizzo di token antifalsificazione:ASP.NET Core includes three filters for working with antiforgery tokens:

Opzioni antifalsificazioneAntiforgery options

Personalizzare le Opzioni antifalsificazione in 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;
});

†impostare le proprietà della Cookie antifalsificazione usando le proprietà della classe CookieBuilder .†Set the antiforgery Cookie properties using the properties of the CookieBuilder class.

OpzioneOption DescrizioneDescription
CookieCookie Determina le impostazioni utilizzate per creare i cookie antifalsificazione.Determines the settings used to create the antiforgery cookies.
FormFieldNameFormFieldName Nome del campo del form nascosto utilizzato dal sistema antifalsificazione per il rendering dei token antifalsificazione nelle viste.The name of the hidden form field used by the antiforgery system to render antiforgery tokens in views.
HeaderNameHeaderName Nome dell'intestazione utilizzata dal sistema antifalsificazione.The name of the header used by the antiforgery system. Se null, il sistema considera solo i dati del modulo.If null, the system considers only form data.
SuppressXFrameOptionsHeaderSuppressXFrameOptionsHeader Specifica se escludere la generazione dell'intestazione X-Frame-Options.Specifies whether to suppress generation of the X-Frame-Options header. Per impostazione predefinita, l'intestazione viene generata con un valore "SAMEORIGIN".By default, the header is generated with a value of "SAMEORIGIN". L'impostazione predefinita è 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;
});
OpzioneOption DescrizioneDescription
CookieCookie Determina le impostazioni utilizzate per creare i cookie antifalsificazione.Determines the settings used to create the antiforgery cookies.
CookieDomainCookieDomain Dominio del cookie.The domain of the cookie. L'impostazione predefinita è null.Defaults to null. Questa proprietà è obsoleta e verrà rimossa in una versione futura.This property is obsolete and will be removed in a future version. L'alternativa consigliata è cookie. Domain.The recommended alternative is Cookie.Domain.
CookieNameCookieName Nome del cookie.The name of the cookie. Se non è impostato, il sistema genera un nome univoco che inizia con DefaultCookiePrefix (". AspNetCore. antifalsificazione. ").If not set, the system generates a unique name beginning with the DefaultCookiePrefix (".AspNetCore.Antiforgery."). Questa proprietà è obsoleta e verrà rimossa in una versione futura.This property is obsolete and will be removed in a future version. L'alternativa consigliata è Cookie.Name.The recommended alternative is Cookie.Name.
CookiePathCookiePath Percorso impostato nel cookie.The path set on the cookie. Questa proprietà è obsoleta e verrà rimossa in una versione futura.This property is obsolete and will be removed in a future version. L'alternativa consigliata è cookie. Path.The recommended alternative is Cookie.Path.
FormFieldNameFormFieldName Nome del campo del form nascosto utilizzato dal sistema antifalsificazione per il rendering dei token antifalsificazione nelle viste.The name of the hidden form field used by the antiforgery system to render antiforgery tokens in views.
HeaderNameHeaderName Nome dell'intestazione utilizzata dal sistema antifalsificazione.The name of the header used by the antiforgery system. Se null, il sistema considera solo i dati del modulo.If null, the system considers only form data.
RequireSslRequireSsl Specifica se HTTPS è richiesto dal sistema antifalsificazione.Specifies whether HTTPS is required by the antiforgery system. Se true, le richieste non HTTPS hanno esito negativo.If true, non-HTTPS requests fail. L'impostazione predefinita è false.Defaults to false. Questa proprietà è obsoleta e verrà rimossa in una versione futura.This property is obsolete and will be removed in a future version. L'alternativa consigliata consiste nell'impostare cookie. SecurePolicy.The recommended alternative is to set Cookie.SecurePolicy.
SuppressXFrameOptionsHeaderSuppressXFrameOptionsHeader Specifica se escludere la generazione dell'intestazione X-Frame-Options.Specifies whether to suppress generation of the X-Frame-Options header. Per impostazione predefinita, l'intestazione viene generata con un valore "SAMEORIGIN".By default, the header is generated with a value of "SAMEORIGIN". L'impostazione predefinita è false.Defaults to false.

Per ulteriori informazioni, vedere CookieAuthenticationOptions.For more information, see CookieAuthenticationOptions.

Configurare le funzionalità antifalsificazione con IAntiforgeryConfigure antiforgery features with IAntiforgery

IAntiforgery fornisce l'API per configurare le funzionalità antifalsificazione.IAntiforgery provides the API to configure antiforgery features. IAntiforgery possibile richiedere nel metodo Configure della classe Startup.IAntiforgery can be requested in the Configure method of the Startup class. Nell'esempio seguente viene usato il middleware della home page dell'app per generare un token antifalsificazione e inviarlo nella risposta come cookie (usando la convenzione di denominazione angolare predefinita descritta più avanti in questo argomento):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);
    });
}

Richiedi convalida antifalsificazioneRequire antiforgery validation

ValidateAntiForgeryToken è un filtro azioni che può essere applicato a una singola azione, a un controller o a livello globale.ValidateAntiForgeryToken is an action filter that can be applied to an individual action, a controller, or globally. Le richieste effettuate alle azioni con questo filtro vengono bloccate a meno che la richiesta non includa un token antifalsificazione valido.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'attributo ValidateAntiForgeryToken richiede un token per le richieste ai metodi di azione contrassegnati, incluse le richieste HTTP GET.The ValidateAntiForgeryToken attribute requires a token for requests to the action methods it marks, including HTTP GET requests. Se l'attributo ValidateAntiForgeryToken viene applicato tra i controller dell'app, è possibile eseguirne l'override con l'attributo IgnoreAntiforgeryToken.If the ValidateAntiForgeryToken attribute is applied across the app's controllers, it can be overridden with the IgnoreAntiforgeryToken attribute.

Nota

ASP.NET Core non supporta l'aggiunta di token antifalsificazione per ottenere automaticamente le richieste.ASP.NET Core doesn't support adding antiforgery tokens to GET requests automatically.

Convalidare automaticamente i token antifalsificazione per metodi HTTP unsafeAutomatically validate antiforgery tokens for unsafe HTTP methods only

ASP.NET Core app non generano token antifalsificazione per metodi HTTP sicuri (GET, HEAD, OPTIONS e TRACE).ASP.NET Core apps don't generate antiforgery tokens for safe HTTP methods (GET, HEAD, OPTIONS, and TRACE). Anziché applicare in larga misura l'attributo ValidateAntiForgeryToken e quindi eseguire l'override con IgnoreAntiforgeryToken attributi, è possibile usare l'attributo AutoValidateAntiforgeryToken .Instead of broadly applying the ValidateAntiForgeryToken attribute and then overriding it with IgnoreAntiforgeryToken attributes, the AutoValidateAntiforgeryToken attribute can be used. Questo attributo funziona in modo identico all'attributo ValidateAntiForgeryToken, ad eccezione del fatto che non richiede token per le richieste effettuate usando i metodi HTTP seguenti: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

Per gli scenari non API si consiglia l'uso di AutoValidateAntiforgeryToken ampiamente.We recommend use of AutoValidateAntiforgeryToken broadly for non-API scenarios. Ciò garantisce che le azioni POST siano protette per impostazione predefinita.This ensures POST actions are protected by default. In alternativa, è possibile ignorare i token antifalsificazione per impostazione predefinita, a meno che non ValidateAntiForgeryToken venga applicato a singoli metodi di azione.The alternative is to ignore antiforgery tokens by default, unless ValidateAntiForgeryToken is applied to individual action methods. È più probabile che in questo scenario un metodo di azione POST venga lasciato non protetto per errore, lasciando l'app vulnerabile agli attacchi 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. Tutti i post devono inviare il token antifalsificazione.All POSTs should send the antiforgery token.

Le API non hanno un meccanismo automatico per l'invio della parte non cookie del token.APIs don't have an automatic mechanism for sending the non-cookie part of the token. È probabile che l'implementazione dipenda dall'implementazione del codice client.The implementation probably depends on the client code implementation. Di seguito sono riportati alcuni esempi:Some examples are shown below:

Esempio a livello di classe:Class-level example:

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

Esempio globale:Global example:

Servizi. AddMvc (opzioni = Opzioni >. Filters. Add (New AutoValidateAntiforgeryTokenAttribute ()));services.AddMvc(options => options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute()));

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

Sostituisci attributi antifalsificazione globali o controllerOverride global or controller antiforgery attributes

Il filtro IgnoreAntiforgeryToken viene usato per eliminare la necessità di un token antifalsificazione per un'azione o un controller specifico.The IgnoreAntiforgeryToken filter is used to eliminate the need for an antiforgery token for a given action (or controller). Quando applicato, questo filtro sostituisce ValidateAntiForgeryToken e AutoValidateAntiforgeryToken i filtri specificati a un livello superiore (globalmente o in un controller).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
    }
}

Aggiornare i token dopo l'autenticazioneRefresh tokens after authentication

I token devono essere aggiornati dopo che l'utente è stato autenticato reindirizzando l'utente a una vista o a una pagina Razor Pages.Tokens should be refreshed after the user is authenticated by redirecting the user to a view or Razor Pages page.

JavaScript, AJAX e SPA (Single Page Application)JavaScript, AJAX, and SPAs

Nelle app tradizionali basate su HTML, i token antifalsificazione vengono passati al server usando i campi dei moduli nascosti.In traditional HTML-based apps, antiforgery tokens are passed to the server using hidden form fields. Nelle app moderne basate su JavaScript e in Spa, molte richieste vengono eseguite a livello di programmazione.In modern JavaScript-based apps and SPAs, many requests are made programmatically. Queste richieste AJAX possono usare altre tecniche (ad esempio, intestazioni di richiesta o cookie) per inviare il token.These AJAX requests may use other techniques (such as request headers or cookies) to send the token.

Se i cookie vengono usati per archiviare i token di autenticazione e per autenticare le richieste API sul server, CSRF è un potenziale problema.If cookies are used to store authentication tokens and to authenticate API requests on the server, CSRF is a potential problem. Se viene usata l'archiviazione locale per archiviare il token, la vulnerabilità CSRF potrebbe essere attenuata perché i valori della risorsa di archiviazione locale non vengono inviati automaticamente al server con ogni richiesta.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. Quindi, l'uso dell'archiviazione locale per archiviare il token antifalsificazione nel client e l'invio del token come intestazione della richiesta è un approccio consigliato.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

Utilizzando JavaScript con le visualizzazioni, è possibile creare il token utilizzando un servizio all'interno della vista.Using JavaScript with views, the token can be created using a service from within the view. Inserire il servizio Microsoft. AspNetCore. antifalsification. IAntiforgery nella vista e chiamare 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>

Questo approccio elimina la necessità di gestire direttamente l'impostazione dei cookie dal server o di leggerli dal client.This approach eliminates the need to deal directly with setting cookies from the server or reading them from the client.

Nell'esempio precedente viene usato JavaScript per leggere il valore del campo nascosto per l'intestazione AJAX POST.The preceding example uses JavaScript to read the hidden field value for the AJAX POST header.

JavaScript può anche accedere ai token nei cookie e usare il contenuto del cookie per creare un'intestazione con il valore del token.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 });

Supponendo che lo script richieda di inviare il token in un'intestazione denominata X-CSRF-TOKEN, configurare il servizio antifalsificazione in modo da cercare l'intestazione del 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");

Nell'esempio seguente viene usato JavaScript per creare una richiesta AJAX con l'intestazione appropriata: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 usa una convenzione per indirizzare CSRF.AngularJS uses a convention to address CSRF. Se il server invia un cookie con il nome XSRF-TOKEN, il servizio di $http AngularJS aggiunge il valore del cookie a un'intestazione quando invia una richiesta al server.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. Questo processo è automatico.This process is automatic. L'intestazione non deve essere impostata in modo esplicito nel client.The header doesn't need to be set in the client explicitly. Il nome dell'intestazione è X-XSRF-TOKEN.The header name is X-XSRF-TOKEN. Il server deve rilevare questa intestazione e convalidarne il contenuto.The server should detect this header and validate its contents.

Per ASP.NET Core API da usare con questa convenzione nell'avvio dell'applicazione:For ASP.NET Core API to work with this convention in your application startup:

  • Configurare l'app per fornire un token in un cookie denominato XSRF-TOKEN.Configure your app to provide a token in a cookie called XSRF-TOKEN.
  • Configurare il servizio antifalsificazione per cercare un'intestazione denominata 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");
}

Visualizzare o scaricare il codice di esempio (procedura per il download)View or download sample code (how to download)

Estendi antifalsificazioneExtend antiforgery

Il tipo IAntiForgeryAdditionalDataProvider consente agli sviluppatori di estendere il comportamento del sistema anti-CSRF eseguendo il round trip di dati aggiuntivi in ogni token.The IAntiForgeryAdditionalDataProvider type allows developers to extend the behavior of the anti-CSRF system by round-tripping additional data in each token. Il metodo GetAdditionalData viene chiamato ogni volta che viene generato un token di campo e il valore restituito viene incorporato all'interno del token generato.The GetAdditionalData method is called each time a field token is generated, and the return value is embedded within the generated token. Un responsabile dell'implementazione può restituire un timestamp, un parametro nonce o qualsiasi altro valore, quindi chiamare ValidateAdditionalData per convalidare questi dati quando il token viene convalidato.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. Il nome utente del client è già incorporato nei token generati, pertanto non è necessario includere tali informazioni.The client's username is already embedded in the generated tokens, so there's no need to include this information. Se un token include dati supplementari ma non è configurata alcuna IAntiForgeryAdditionalDataProvider, i dati supplementari non vengono convalidati.If a token includes supplemental data but no IAntiForgeryAdditionalDataProvider is configured, the supplemental data isn't validated.

Risorse aggiuntiveAdditional resources