Förhindra XSRF-/CSRF-attacker (Cross-Site Request Forgery) i ASP.NET Core

Av Fiyaz Hasan och Rick Anderson

Förfalskning av begäranden mellan webbplatser är ett angrepp mot webbaserade appar där en skadlig webbapp kan påverka interaktionen mellan en klientwebbläsare och en webbapp som litar på webbläsaren. Dessa attacker är möjliga eftersom webbläsare skickar vissa typer av autentiseringstoken automatiskt med varje begäran till en webbplats. Den här typen av exploatering kallas även för en attack med ett klick eller session som körs eftersom attacken utnyttjar användarens tidigare autentiserade session. Förfalskning av begäranden mellan webbplatser kallas även XSRF eller CSRF.

Ett exempel på en CSRF-attack:

  1. En användare loggar in på www.good-banking-site.example.com med formulärautentisering. Servern autentiserar användaren och utfärdar ett svar som innehåller en autentisering cookie. Webbplatsen är sårbar för angrepp eftersom den litar på alla förfrågningar som den tar emot med en giltig autentisering cookie.

  2. Användaren besöker en skadlig webbplats www.bad-crook-site.example.com.

    Den skadliga webbplatsen, www.bad-crook-site.example.com, innehåller ett HTML-formulär som liknar följande exempel:

    <h1>Congratulations! You're a Winner!</h1>
    <form action="https://www.good-banking-site.example.com/api/account" method="post">
        <input type="hidden" name="Transaction" value="withdraw" />
        <input type="hidden" name="Amount" value="1000000" />
        <input type="submit" value="Click to collect your prize!" />
    </form>
    

    Observera att formulärets action skickas till den sårbara webbplatsen, inte till den skadliga webbplatsen. Det här är "cross-site"-delen av CSRF.

  3. Användaren väljer knappen Skicka. Webbläsaren gör begäran och innehåller automatiskt autentiseringen cookie för den begärda domänen www.good-banking-site.example.com.

  4. Begäran körs på www.good-banking-site.example.com-servern med användarens autentiseringskontext och kan utföra alla åtgärder som en autentiserad användare tillåts utföra.

Förutom scenariot där användaren väljer knappen för att skicka formuläret kan den skadliga webbplatsen:

  • Kör ett skript som automatiskt skickar formuläret.
  • Skicka formuläret som en AJAX-begäran.
  • Dölj formuläret med hjälp av CSS.

Dessa alternativa scenarier kräver ingen åtgärd eller indata från användaren förutom att först besöka den skadliga webbplatsen.

Att använda HTTPS förhindrar inte en CSRF-attack. Den skadliga webbplatsen kan skicka https://www.good-banking-site.example.com/ en begäran lika enkelt som den kan skicka en osäker begäran.

Vissa attacker, anger mot slutpunkter som svarar på GET-begäranden, i så fall kan en img-tagg användas för att utföra åtgärden. Den här typen av angrepp är vanlig på forumwebbplatser som tillåter bilder men blockerar JavaScript. Appar som ändrar tillstånd för GET-begäranden, där variabler eller resurser ändras, är sårbara för skadliga attacker. GET-begäranden som ändrar tillstånd är osäkra. En bästa praxis är att aldrig ändra tillstånd för en GET-begäran.

CSRF-attacker är möjliga mot webbappar som använder cookies för autentisering eftersom:

  • Webbläsare lagrar cookies som utfärdats av en webbapp.
  • Lagrade cookies inkluderar sessionscookies för autentiserade användare.
  • Webbläsare skickar alla cookies som är associerade med en domän till webbappen varje begäran oavsett hur begäran till appen genererades i webbläsaren.

CSRF-attacker är dock inte begränsade till att utnyttja cookies. Till exempel är grundläggande och sammanfattad autentisering också sårbara. När en användare har loggat in med Basic- eller Digest-autentisering skickar webbläsaren automatiskt autentiseringsuppgifterna tills sessionen är slut.

I det här sammanhanget refererar session till den session på klientsidan som användaren autentiseras under. Det är inte relaterat till sessioner på serversidan eller ASP.NET Core sessionsmellanprogram.

Användare kan skydda mot CSRF-sårbarheter genom att vidta försiktighetsåtgärder:

  • Logga ut från webbappar när du är klar med att använda dem.
  • Rensa webbläsarcookies med jämna mellanrum.

CsRF-sårbarheter är dock i grunden ett problem med webbappen, inte slutanvändaren.

Grunderna för autentisering

Cookie-baserad autentisering är en populär form av autentisering. Tokenbaserade autentiseringssystem växer i popularitet, särskilt för ensidesprogram (SPA).

När en användare autentiserar med sitt användarnamn och lösenord utfärdas en token som innehåller en autentiseringsbiljett. Token kan användas för autentisering och auktorisering. Token lagras som en cookie som skickas med varje begäran som klienten gör. Generering och validering av detta cookie utförs med mellanprogrammet för cookie autentisering. mellanprogram serialiserar ett användarhuvudnamn till en krypterad cookie. Vid efterföljande begäranden validerar mellanprogrammet cookie, återskapar principalen och tilldelar principalen till egenskapen HttpContext.User.

Tokenbaserad autentisering

När en användare autentiseras utfärdas en token (inte en antiforgery-token). Tokenet innehåller användarinformation i form av anspråk eller en referenstoken som pekar appen mot användartillståndet som underhålls i appen. När en användare försöker komma åt en resurs som kräver autentisering skickas token till appen med ett extra auktoriseringshuvud i form av en Bearer token. Den här metoden gör appen tillståndslös. I varje efterföljande begäran skickas token i begäran om verifiering på serversidan. Den här token är inte krypterad; det är kodat. På servern avkodas token för att komma åt informationen. Om du vill skicka token på efterföljande begäranden lagrar du token i webbläsarens lokala lagring. Att placera en token i webbläsarens lokala lagring och hämta den och använda den som en ägartoken ger skydd mot CSRF-attacker. Men om appen skulle vara sårbar för skriptinmatning via XSS eller en komprometterad extern JavaScript-fil kan en cyberattacker hämta valfritt värde från lokal lagring och skicka det till sig själva. ASP.NET Core kodar alla utdata på serversidan från variabler som standard, vilket minskar risken för XSS. Om du åsidosätter det här beteendet med hjälp av Html.Raw- eller anpassad kod med ej betrodda indata kan du öka risken för XSS.

Oroa dig inte för CSRF-sårbarhet om token lagras i webbläsarens lokala lagring. CSRF är ett problem när token lagras i en cookie. Mer information finns i GitHub-problemet SPA-kodexempel lägger till två cookies.

Flera appar som finns i en domän

Delade värdmiljöer är sårbara för sessionskapning, CSRF vid inloggning och andra attacker.

Även om example1.contoso.net och example2.contoso.net är olika värdar finns det en implicit förtroenderelation mellan värdar under den *.contoso.net domänen. Den här implicita förtroenderelationen gör att potentiellt ej betrodda värdar kan påverka varandras cookies (principerna för samma ursprung som styr AJAX-begäranden gäller inte nödvändigtvis för HTTP-cookies).

Attacker som utnyttjar betrodda cookies mellan appar som finns på samma domän kan förhindras genom att inte dela domäner. När varje app finns på sin egen domän finns det ingen implicit cookie förtroenderelation att utnyttja.

Hämta metadatahuvuden

Moderna webbläsare kopplar hämta metadatabegärandehuvuden – viktigast av allt Sec-Fetch-Site– till varje begäran. Sec-Fetch-Site beskriver förhållandet mellan det ursprung som initierade begäran och det ursprung som begärs: same-origin identifierar en begäran som webbplatsen har gjort till sig själv, medan same-site och cross-site identifierar begäranden som initierats av ett annat ursprung. Headern Origin innehåller ursprunget för begärans initiering och fungerar som en reservlösning för webbläsare som är äldre än Fetch Metadata.

Sec-Fetch-Site och Origin är förbjudna begärandehuvuden: webbläsaren anger dem och JavaScript som körs på en sida kan inte åsidosätta eller förfalska dem. Det gör dem till en tillförlitlig signal för att skilja en webbplats egna förfrågningar från begäranden mellan webbplatser utan en serverutfärdad token. Det automatiska CSRF-skyddet som är inbyggt i ASP.NET Core använder den här signalen för att avvisa formulärposter mellan webbplatser som inte uttryckligen är betrodda.

Automatiskt CSRF-skydd i ASP.NET Core

ASP.NET Core innehåller middleware för automatiskt CSRF-skydd som är aktiverat som standard i appar som skapats med WebApplication.CreateBuilder. Till skillnad från det tokenbaserade antiforgery-systemet utfärdar eller validerar inte det här mellanprogrammet token. I stället inspekterar den Sec-Fetch-Site och OriginFetch-metadatahuvuden och registrerar ett valideringsutlåtande för förfrågan. Komponenter som bearbetar inskickade formulärdata upprätthåller det beslutet och avvisar formulärpostningar från andra ursprung som inte uttryckligen har godkänts som betrodda.

För de flesta appar krävs inga kodändringar: webbläsarbegäranden med samma ursprung, säkra HTTP-metoder och icke-webbläsarklienter (curlserver-till-server, mobilappar) passerar alla opåverkade. Mellanprogrammet påverkar främst appar som accepterar formulärinlägg mellan ursprung från en webbläsare, till exempel en webbplats som publicerar ett formulär till ett API med ett annat ursprung. Dessa scenarier måste antingen konfigurera CORS för att ange den betrodda originen eller undanta slutpunkten.

Det här mellanprogrammet är additivt till det tokenbaserade antiforgery-systemet. De två skydden samexisterar och kan båda vara aktiva på samma slutpunkt. En jämförelse av när var och en gäller finns i Interaktion med tokenbaserat förfalskningsskydd.

Så här fungerar det

För varje begäran utvärderar mellanprogrammet en kort regelkedja för att nå en dom – tillåten eller nekad. Kontrollerna körs i ordning och den första matchningen vinner:

  1. Säkra HTTP-metoder tillåts alltid.GET, HEAD, OPTIONSoch TRACE begäranden skickas igenom. Detta följer RFC 9110 §9.2.1 och överensstämmer med den långvariga regeln att slutpunkter inte ska ändra tillstånd på GET.
  2. Sec-Fetch-Site: same-origin eller Sec-Fetch-Site: none tillåts. Moderna webbläsare skickar Sec-Fetch-Site på varje begäran. same-origin omfattar normal navigering och hämtning i appen och none omfattar begäranden som initieras direkt av användaren (skriva en URL med ett bokmärke). Det här är den vanligaste kodvägen – den mesta legitima webbläsartrafiken går här.
  3. Ett betrott ursprung från CORS tillåts. Om begäran innehåller en Origin-header och slutpunktens fastställda CORS-princip litar på det ursprunget, tillåts begäran. Mellanprogrammet löser principen på samma sätt som CORS-mellanprogrammet gör: principen per slutpunkt från [EnableCors("name")] först och sedan standardprincipen som registrerats med AddDefaultPolicy. Se Tillåt klienter med korsande ursprung för viktiga gränser för den här regeln.
  4. Alla andra Sec-Fetch-Site värden nekas. När Sec-Fetch-Site är cross-site eller same-site och ursprunget inte är betrott enligt CORS nekas begäran.
  5. Ingen Sec-Fetch-Site, men Origin finns: mellanprogrammet jämför Origin med scheme://host[:port] som skapats utifrån begäran. Om de stämmer överens tillåts begäran; annars nekas den. Det här är återställningssökvägen för webbläsare som är äldre än specifikationen Hämta metadata (utgiven ~2020).
  6. Nej Sec-Fetch-Site och nej Origin: begäran tillåts. Webbläsare skickar alltid minst en av dessa på en skrivbegäran, så en begäran som saknar båda är nästan säkert en icke-webbläsarklient som curl, Postman, en mobilapp eller en server-till-server-anropare. CSRF är en attackvektor som endast fungerar i webbläsare, så dessa förfrågningar släpps igenom.

Mellanprogramvaran registrerar denna bedömning på begäran i stället för att själv avsluta begäran. Information om hur och när en nekad dom förvandlas till ett HTTP-svar 400 Bad Request finns i Uppskjuten validering.

Uppskjuten validering

Mellanprogrammet avvisar inte en begäran på egen hand. I stället registrerar den sin bedömning av begärans IAntiforgeryValidationFeature– samma funktion som det tokenbaserade antiforgery-systemet använder – där en nekad dom registreras som ogiltig. Begäran fortsätter nedåt i pipelinen. En ogiltig bedömning blir endast en HTTP 400 Bad Request när en komponent som bearbetar formulärdata observerar den. Den här senareläggningen överensstämmer med hur det tokenbaserade systemet redan fungerar: bedömningen görs tidigt men tillämpas först när ett formulär används.

Följande komponenter läser IAntiforgeryValidationFeature och avvisar en begäran med 400 - Bad Request när den registrerade domen är ogiltig:

  • MVC-åtgärder med förfalskningsskydd.
  • Minimala API-slutpunkter som binder en formulärparameter.
  • Blazor SSR-slutpunkter.
  • All kod som läser begäransformuläret direkt, vilket fungerar som en säkerhetsåtgärd.

Varje konsument bekräftar först att ett antiforgery- eller CSRF-mellanprogram faktiskt kördes innan det litar på domen, så en pipeline utan mellanprogram ger inte falska avslag.

En följd av den här modellen är att en slutpunkt som aldrig läser formulärdata körs även när domen är ogiltig. Till exempel avvisas inte en JSON API-slutpunkt som binder dess brödtext från JSON, eller en hanterare som ignorerar begärandetexten, automatiskt på en begäran mellan ursprung. Beslutet lagras fortfarande på IAntiforgeryValidationFeature för kod som vill undersöka det, men inget upprätthåller det. CSRF är en formulär- och cookieattackvektor, så ändpunkter som inte tar emot ett formulär som skickats från webbläsaren behöver i allmänhet inte den här avvisningen. Slutpunkter som bearbetar formulär –Razor Sidor, MVC-vyer, Blazor SSR och Minimal API-formulärbindning – får skyddet automatiskt.

Standardbeteende

Mellanprogrammet registreras automatiskt av WebApplication.CreateBuilder och körs efter autentisering och auktorisering. Den validerar varje begäran med hjälp av den registrerade ICsrfProtection implementeringen, vilket som standard tillämpar de regler som beskrivs i Så här fungerar den. Standardimplementeringen kan ersättas. se Anpassa: implementera ICsrfProtection. Information om hur du inaktiverar mellanprogrammet helt finns i Inaktivera globalt.

Resultatet är att en minimal app med en slutpunkt för formulärhantering som följande redan är skyddad:

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.MapPost("/widgets", ([FromForm] Widget w) =>
    Results.Created($"/widgets/{w.Id}", w));

app.Run();

En webbläsare som gör en begäran från samma ursprung POST /widgets når ändpunkten normalt. En webbläsare på https://attacker.example.com som skickar in samma formulär avvisas med 400 - Bad Request när ändpunkten binder formulärdata, innan hanterarens kod körs. En curl begäran utan Sec-Fetch-Site eller Origin tillåts.

Eftersom avvisning överlåts till konsumenter av formulärdata avvisas inte en ändpunkt som inte läser formulärdata, till exempel ett JSON-API som binder brödtexten från JSON, automatiskt, inte ens vid en begäran över ursprungsgränser. Domen registreras fortfarande på begäran om kod som vill inspektera den.

Mellanprogrammet integreras med den befintliga antiförfalskningsmodellen:

  • Minimala API:er: Att anropa .DisableAntiforgery() på en slutpunkt gör att slutpunkten undantas från både den tokenbaserade mellanprogramvaran och mellanprogramvaran för CSRF-skydd. Samma metadata (IAntiforgeryMetadata { RequiresValidation = false }) kontrolleras av båda.
  • MVC-styrenheter och actioner:[IgnoreAntiforgeryToken] undantar också slutpunkten från båda skydden.

Tillåta klienter med korsande ursprung

Det vanligaste scenariot som kräver åtgärd är en webbläsarbaserad klient som skickar ett formulär mellan ursprung – till exempel en webbplats på https://app.contoso.com som skickar ett formulär till ett API på https://api.contoso.com. Sådana formulärinlägg nekas som standard eftersom Sec-Fetch-Site är same-site eller cross-site snarare än same-origin, och formulärkonsumenten upprätthåller detta beslut med en 400 - Bad Request.

CSRF-mellanprogrammet introducerar inte en egen förtroendelista. Den återanvänder samma CORS-princip som CORS-mellanprogrammet löser för slutpunkten: om den principen tillåter begärans Originregistrerar CSRF-mellanprogrammet en tillåten dom för begäran.

Policyn väljs per slutpunkt i följande ordning:

  1. [EnableCors("api")] (MVC) eller .RequireCors("api") (minimalt API) → den namngivna principen "api".
  2. Det finns inga CORS-metadata på slutpunkten → standardpolicyn som registrerats med AddDefaultPolicy gäller.
  3. Ingen matchande princip (namngiven princip inte registrerad, ingen standardprincip eller services.AddCors() aldrig anropad) → inget CORS-härlett förtroende. Mellanprogramvaran faller tillbaka på reglerna för Sec-Fetch-Site och Origin-vs-Host.

Ett minimalt exempel med en standardprincip och en minimal API-slutpunkt:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddCors(options =>
{
    options.AddDefaultPolicy(policy =>
        policy.WithOrigins("https://app.contoso.com")
              .AllowAnyHeader()
              .AllowAnyMethod());
});

var app = builder.Build();

app.UseCors();

app.MapPost("/widgets", ([FromForm] Widget w) =>
    Results.Created($"/widgets/{w.Id}", w));

app.Run();

För en namngiven princip på en enskild slutpunkt:

app.MapPost("/widgets", ([FromForm] Widget w) => Results.Created($"/widgets/{w.Id}", w))
   .RequireCors("api");

Varning

AllowAnyOrigin ignoreras avsiktligt som en CSRF-förtroendesignal. AllowAnyOrigin betyder "vilken webbläsare som helst kan läsa den här resursen", vilket är en annan fråga än "vilket ursprung som helst får ändra tillstånd å användarens vägnar". Att behandla AllowAnyOrigin som betrott skulle göra denna middleware till en no-op för skrivningar mellan olika ursprung. Appar som behöver en CORS-princip för offentlig läsåtkomst i kombination med CSRF-skyddad skrivåtkomst bör uttryckligen lista betrodda ursprung för skrivåtkomst med WithOrigins eller undanta skrivslutpunkter om de inte förlitar sig på cookie-baserad autentisering.

[DisableCors] på en slutpunkt är inte en CSRF opt-out. Den hoppar över det CORS-härledda förtroendesteget och begäran måste fortfarande uppfylla Sec-Fetch-Site reglerna och Origin-vs-Host. Om du vill undanta CSRF-skydd, se Undanta en slutpunkt.

Mer information om hur du konfigurerar CORS själv – , , , och resten av principverktygets API – finns AddCors. AddDefaultPolicyAddPolicyWithOrigins

Exkludera en slutpunkt

Om en slutpunkt inte kan nås via webbläsaren eller skyddas av en icke-mekanismcookie , till exempel en ägartoken eller API-nyckel, väljer du bort den individuellt i stället för att inaktivera mellanprogrammet globalt.

Minimala API:er – anropa DisableAntiforgery på slutpunkten eller gruppen:

app.MapPost("/api/webhook", (WebhookPayload p) => Results.Accepted())
   .DisableAntiforgery();

MVC-styrenheter – gäller [IgnoreAntiforgeryToken] för åtgärden eller kontrollanten:

[ApiController]
[Route("api/[controller]")]
[IgnoreAntiforgeryToken]
public class WebhookController : ControllerBase
{
    [HttpPost]
    public IActionResult Post([FromBody] WebhookPayload payload) => Accepted();
}

Båda metoderna lägger till IAntiforgeryMetadata { RequiresValidation = false } i ändpunkten, vilket CSRF-mellanprogrammet respekterar genom att hoppa över valideringen.

Varning

Att inaktivera CSRF-skydd på en slutpunkt bör endast göras när slutpunkten inte är sårbar för CSRF-attacker, till exempel slutpunkter som inte kan anropas från en webbläsare eller som skyddas med icke-autentiseringcookie , till exempel ägartoken eller API-nycklar. Inaktivera inte CSRF-skydd på webbläsartillgängliga slutpunkter som förlitar sig på cookies för autentisering.

Inaktivera globalt

Mellanprogrammet kan inaktiveras i hela appen med hjälp av konfigurationsnyckeln DisableCsrfProtection . Det här är en nödutgång – välj helst undantag för varje slutpunkt.

I appsettings.json:

{
  "DisableCsrfProtection": true
}

Eller som en miljövariabel:

ASPNETCORE_DisableCsrfProtection=true

När den här nyckeln är inställd truepå hoppar WebApplication över registreringen av mellanprogrammet i pipelinen. Tjänsten ICsrfProtection förblir registrerad, så allt som löser det direkt fortsätter att fungera.

Varning

Det automatiska CSRF-mellanprogrammet uppfyller också kravet på skydd mot förfalskning för slutpunkter som kräver validering, även när en app inte anropar app.UseAntiforgery(). Om en app förlitar sig på antiforgery men inte anropar app.UseAntiforgery(), inaktiverar CSRF-mellanprogrammet globalt eller körs på en värd som inte är byggd med WebApplication, där mellanprogrammet inte matas in, lämnar de slutpunkterna utan mellanprogram mot förfalskning. En begäran till en sådan slutpunkt utlöser sedan ett undantag. Anropa app.UseAntiforgery() i den konfigurationen.

Webbläsarstöd

Sec-Fetch-Site stöds av alla aktuella versioner av Chromium-baserade webbläsare, Firefox och Safari. En auktoritativ kompatibilitetstabell finns i MDN-referensen för Sec-Fetch-Site.

Äldre webbläsare som är äldre än Fetch Metadata skickar inte Sec-Fetch-Site. För dessa klienter går mellanprogrammet tillbaka till att jämföra Origin-headern med begärans schema och värd. Webbläsare har skickat Origin i skrivförfrågningar av typen cross-origin i många år, så den här reservlösningen täcker i stort sett all trafik från äldre webbläsare.

Icke-webbläsarklienter –curl Postman, mobilappar, server-till-server-anropare – skickar vanligtvis varken Sec-Fetch-Site eller Origin. Dessa begäranden tillåts eftersom CSRF är en attackvektor endast i webbläsaren som är beroende av att webbläsaren automatiskt kopplar omgivande autentiseringsuppgifter, till exempel cookies. En icke-webbläsarklient som vill attackera API:et behöver inte CSRF. Det kan helt enkelt anropa API:et direkt med de autentiseringsuppgifter som det har.

Anpassa: implementera ICsrfProtection

Beslutslogik finns bakom ett gränssnitt med en metod:

namespace Microsoft.AspNetCore.Antiforgery;

public interface ICsrfProtection
{
    ValueTask<CsrfProtectionResult> ValidateAsync(HttpContext context);
}

Om du vill ersätta standardimplementeringen registrerar du en singleton i DI. Eftersom ramverket använder TryAddSingletonåsidosätter ett explicit AddSingleton anrop standardvärdet:

builder.Services.AddSingleton<ICsrfProtection, AllowlistCsrfProtection>();

En anpassad implementering är användbar när förtroendemodellen inte passar CORS, till exempel när en fast lista över partnerursprung föredras eller när strängare regler behövs:

using Microsoft.AspNetCore.Antiforgery;
using Microsoft.AspNetCore.Http;

public sealed class AllowlistCsrfProtection : ICsrfProtection
{
    private static readonly HashSet<string> SafeMethods =
        new(StringComparer.OrdinalIgnoreCase) { "GET", "HEAD", "OPTIONS", "TRACE" };

    private static readonly HashSet<string> TrustedOrigins =
        new(StringComparer.OrdinalIgnoreCase)
        {
            "https://app.contoso.com",
            "https://admin.contoso.com",
        };

    public ValueTask<CsrfProtectionResult> ValidateAsync(HttpContext context)
    {
        if (SafeMethods.Contains(context.Request.Method))
        {
            return ValueTask.FromResult(CsrfProtectionResult.Allowed());
        }

        var origin = context.Request.Headers.Origin.ToString();
        var allowed = !string.IsNullOrEmpty(origin) && TrustedOrigins.Contains(origin);

        return ValueTask.FromResult(
            allowed ? CsrfProtectionResult.Allowed() : CsrfProtectionResult.Denied());
    }
}

Mellanprogrammet respekteras fortfarande oavsett vilken implementering som är registrerad – avanmälningen hanteras av själva mellanprogrammet innan det anropas.DisableAntiforgery() / [IgnoreAntiforgeryToken].ValidateAsync

Interagera med tokenbaserat skydd mot förfalskning

De två CSRF-skydden riktar sig mot olika lager och är utformade för att samexistera. De delar också samma begärandefunktion: båda registrerar sitt resultat i IAntiforgeryValidationFeature, och formulärskonsumenter tillämpar det utslag som finns.

Aspect Tokenbaserad AntiforgeryMiddleware Automatiskt middleware för CSRF-skydd
Lanserade ASP.NET Core 2.0+ .NET 11
Activation Anmälan via app.UseAntiforgery() (eller implicit genom AddMvc / MapRazorPages / AddRazorComponents) Matas in automatiskt av WebApplication.CreateBuilder
Validerar Synkroniserad token (formulärfält + cookie par) Sec-Fetch-Site / Origin Headers
Requires ASP.NET Core Översikt över dataskydd för tokenkryptering Inga token, inget tillstånd
Webbläsaromfång Alla webbläsare som skickar cookies Alla moderna webbläsare; Origin reservlösning för äldre
Avaktivering per slutpunkt .DisableAntiforgery() / [IgnoreAntiforgeryToken] Samma – båda respekterar samma metadata

Det tokenbaserade mellanprogrammet skyddar specifikt mot det klassiska CSRF-attackmönstret där en skadlig webbplats utlöser ett formulär POST till en sårbar webbplats med hjälp av användarens omgivande cookies. Det automatiska CSRF-mellanprogrammet hanterar samma hot på HTTP-lagret med hjälp av metadata från webbläsaren. Båda kan vara aktiva på samma slutpunkt och många appar drar nytta av skydd på djupet:

  • Razor Sidor, MVC- och Blazor SSR-appar som redan använder tokensystemet får en rubrikbaserad kontroll som körs före tokenvalidering, utan att tokenflödet ändras.
  • Minimala API-appar som binder formulär får en användbar standard utan att behöva anropa app.UseAntiforgery() eller tråda IAntiforgery via slutpunkter.
  • API:er som anropas från SPA:er från andra ursprung kan använda denna middleware i kombination med en CORS-allowlist och helt avstå från tokensystemet om API:et aldrig serverar HTML-formulär.

Det automatiska CSRF-mellanprogrammet ersätter det tokenbaserade systemet i många scenarier, eftersom båda skyddar samma slutpunkter för formulärhantering. Behåll det tokenbaserade systemet när:

Mer information om det tokenbaserade systemet, inklusive formulärintegrering, AJAX-flöden, konfiguration via AntiforgeryOptionsoch IAntiforgery API:er finns i Antiforgery i ASP.NET Core.

Tokenverifiering har företräde

När en app anropar app.UseAntiforgery()körs det tokenbaserade mellanprogrammet efter det automatiska CSRF-mellanprogrammet. Token-mellanprogrammet rensar alla bedömningar som CSRF-mellanprogrammet har registrerat och ersätter den med resultatet av tokenvalideringen. Tokenresultatet är auktoritativt:

  • En begäran om att CSRF-mellanprogrammet som markerats som ogiltigt blir giltigt om det har en giltig token.
  • En begäran om att CSRF-mellanprogrammet tillåts markeras som ogiltig om dess token saknas eller är ogiltig.

Den här ordningen innebär att appar som använder tokensystemet ser samma beteende från slutpunkt till slutpunkt som de hade innan det automatiska mellanprogrammet fanns, medan appar som inte använder token återgår till CSRF-mellanprogrammets bedömning.

Blazor statisk återgivning på serversidan

Blazor statiska slutpunkter för rendering på serversidan (SSR) ingår i samma fördröjda modell. Razor Components-slutpunkten litar på den bedömning som registrerats på IAntiforgeryValidationFeature av den överordnade mellanprogramvaran och returnerar endast 400 - Bad Request för ett formulärinlägg när den bedömningen är ogiltig. Slutpunkten validerar inte längre själva begäran.

Beteendet beror på vilket mellanprogram som kördes:

  • Appar som anropar app.UseAntiforgery() är oförändrade. Det tokenbaserade mellanprogrammet verifierar varje begäran och antiforgery-token genereras för renderade formulär som tidigare.
  • Appar som inte anropar app.UseAntiforgery() skyddas av det automatiska CSRF-mellanprogrammet i stället. I den konfigurationen hoppar slutpunkten över generering av antiforgery-token eftersom det inte finns några tokenmellanprogram för att verifiera en token vid en senare begäran.

Det här är en ändring i beteendet för statisk SSR, där app.UseAntiforgery() tidigare togs bort: de skyddas nu av CSRF-mellanprogrammet i stället för att lämnas oskyddade, och de slutar generera antiförfalskningstoken. Information om migrering finns i Migrera från ASP.NET Core i .NET 10 till ASP.NET Core i .NET 11. För det formella meddelandet om den icke-bakåtkompatibla ändringen, se Blazor rendering på serversidan överlåter antiförfalskningsvalidering till mellanprogram.

Troubleshooting

Symptom: Begäranden med samma ursprung från en webbläsare lyckas, men inlägg med korsande ursprungsformulär returneras 400 - Bad Request utan brödtext.

Orsaka: CSRF-mellanprogrammet registrerade en ogiltig dom för begäran om korsande ursprung och en formulärbearbetningskomponent – till exempel en MVC-åtgärd, en minimal API-formulärbindning eller ett Blazor SSR-formulärinlägg – framtvingade den domen med en 400 - Bad Request. Detta är det förväntade standardbeteendet för slutpunkter som bearbetar formulär.

Lösning: Välj något av följande beroende på scenariot:

  • Om det anropande ursprunget är känt och betrott tillåter du det via CORS.
  • Om slutpunkten inte går att nå från en webbläsare eller använder annan autentisering än cookie, väljer du bort den med .DisableAntiforgery() eller [IgnoreAntiforgeryToken].
  • Om hela appen behöver avstå (till exempel under ett migreringsfönster), inaktivera globalt.

Diagnostisera: Mellanprogrammet loggar alla ogiltiga omdömen på Debug nivå under kategorin Microsoft.AspNetCore.Antiforgery.CsrfProtectionMiddleware med händelsenamnet CsrfValidationFailed. Aktivera Debug loggning för den kategorin i appsettings.Development.json:

{
  "Logging": {
    "LogLevel": {
      "Microsoft.AspNetCore.Antiforgery.CsrfProtectionMiddleware": "Debug"
    }
  }
}

Ett registrerat utslag visas sedan i loggen som:

dbug: Microsoft.AspNetCore.Antiforgery.CsrfProtectionMiddleware[1]
      Cross-origin CSRF protection marked request POST /widgets from origin 'https://attacker.example.com' as invalid.

Återskapa lokalt: Använd curl med en uttrycklig Origin-header för att simulera en webbläsarbegäran mellan olika ursprung mot en formulärändpunkt:

curl -i -X POST https://localhost:{PORT}/widgets \
     -H "Origin: https://attacker.example.com" \
     -H "Content-Type: application/x-www-form-urlencoded" \
     -d "name=test"

Ersätt {PORT} med appens lokala HTTPS-port. 400 - Bad Request Observeras eftersom slutpunkten binder formuläret, vilket framtvingar den registrerade domen. En icke-formulärslutpunkt returnerar sitt normala svar eftersom inget läser domen. Utan Origin-huvudet tillåts samma begäran eftersom curl inte heller skickar Sec-Fetch-Site, och en begäran utan någotdera huvudet behandlas som en icke-webbläsarklient.

Det tokenbaserade antiforgery-systemet som beskrivs i resten av den här artikeln föregår mellanprogrammet och förblir tillgängligt. För de flesta appar räcker det automatiska skyddet på egen hand. Information om när du ska behålla det tokenbaserade systemet och hur du migrerar finns i Migrera från ASP.NET Core i .NET 10 till ASP.NET Core i .NET 11.

Antiförfalskning i ASP.NET Core

Varning

ASP.NET Core använder ASP.NET Core Data Protectionför att implementera skydd mot förfalskning. Dataskyddsstacken måste konfigureras för att fungera i en servergrupp. Mer information finns i Konfigurera dataskydd.

Antiforgery-mellanprogram läggs till i containern Dependency injection när något av följande API:er anropas i Program.cs:

Mer information finns i Antiforgery med minimala API:er.

FormTagHelper infogar antiforgery-token i HTML-formulärelement. Följande kod i en Razor-fil genererar automatiskt antiforgery-token:

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

På samma sätt genererar IHtmlHelper.BeginForm antiforgerytoken som standard om formulärets metod inte är GET.

Den automatiska genereringen av antiforgery-token för HTML-formulärelement sker när taggen <form> innehåller attributet method="post" och något av följande är sant:

  • Åtgärdsattributet är tomt (action="").
  • Åtgärdsattributet anges inte (<form method="post">).

Automatisk generering av antiforgery-token för HTML-formulärelement kan inaktiveras:

  • Avaktivera antifalsifieringstoken uttryckligen med attributet asp-antiforgery:

    <form method="post" asp-antiforgery="false">
        <!-- ... -->
    </form>
    
  • Formulärelementet väljs bort från Tag Helpers genom att använda Tag Helper ! opt-out-symbolen:

    <!form method="post">
        <!-- ... -->
    </!form>
    
  • Ta bort FormTagHelper från vyn. Du kan ta bort FormTagHelper från en vy genom att lägga till följande direktiv i vyn Razor:

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

Obs

Razor Pages skyddas automatiskt från XSRF/CSRF. Mer information finns i XSRF/CSRF och Razor Pages.

Den vanligaste metoden för att skydda mot CSRF-attacker är att använda synkroniserartokens mönster (STP). STP används när användaren begär en sida med formulärdata:

  1. Servern skickar en token som är associerad med den aktuella användarens identitet till klienten.
  2. Klienten skickar tillbaka token till servern för verifiering.
  3. Om servern tar emot en token som inte matchar den autentiserade användarens identitet avvisas begäran.

Token är unik och oförutsägbar. Token kan också användas för att säkerställa korrekt sekvensering av en serie begäranden (till exempel genom att säkerställa begärandesekvensen på sidan 1 > sida 2 > sida 3). Alla formulär i ASP.NET Core MVC- och Razor Pages-mallar genererar antiforgery-token. Följande par av vyexempel genererar anti-förfalskningstecken:

<form asp-action="Index" asp-controller="Home" method="post">
    <!-- ... -->
</form>

@using (Html.BeginForm("Index", "Home"))
{
    <!-- ... -->
}

Lägg till en antiforgery-token uttryckligen i ett <form>-element utan att använda Tag Helpers med HTML-hjälparen @Html.AntiForgeryToken:

<form asp-action="Index" asp-controller="Home" method="post">
    @Html.AntiForgeryToken()

    <!-- ... -->
</form>

I vart och ett av de föregående fallen lägger ASP.NET Core till ett dolt formulärfält som liknar följande exempel:

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

ASP.NET Core innehåller tre filter för arbete med antiförfalsknings-token:

Antiförfalskning med AddControllers

Att anropa AddControllers gör inte att antiförfalskningsmarkörer aktiveras. AddControllersWithViews måste anropas för att ha inbyggt stöd för antiförfalskningstoken.

Flera webbläsarflikar och mönstret för synkroniseringstoken

Flera flikar som loggas in som olika användare, eller en som är inloggad som anonym, stöds inte.

Konfigurera förfalskningsskydd med AntiforgeryOptions

Anpassa AntiforgeryOptions i appens Program fil:

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

Ange egenskaper för förfalskningsskydd cookie med hjälp av egenskaperna för klassen CookieBuilder, som du ser i följande tabell.

Alternativ Beskrivning
Cookie Avgör vilka inställningar som används för att skapa antiforgery-cookies.
FormFieldName Namnet på det gömda formulärfältet som används av antiforgery-systemet för att generera antiforgery-tokens i vyer.
HeaderName Namnet på rubriken som används av antiforgerysystemet. Om nulltar systemet endast hänsyn till formulärdata.
SuppressXFrameOptionsHeader Anger om du vill utelämna genereringen av X-Frame-Options-huvudet. Som standard genereras rubriken med värdet "SAMEORIGIN". Ställs in som standard till false.

Vissa webbläsare tillåter inte osäkra slutpunkter att ange cookies med en "säker" flagga eller skriva över cookies vars "säkra" flagga har angetts (mer information finns i Inaktuell ändring av "säkra" cookies från icke-säkra ursprung). Eftersom blandningen av säkra och osäkra slutpunkter är ett vanligt scenario i appar, minskar ASP.NET Core restriktionen på den säkra policyn för vissa cookies, som till exempel antiforgery cookie, genom att ställa in cookies SecurePolicy till CookieSecurePolicy.None. Även om en obehörig användare stjäl en antiforgery cookie, måste de också stjäla den antiforgery-token som vanligtvis skickas via ett formulärfält (oftare) eller en separat begäran-rubrik (mer sällan) plus autentiseringen cookie. Cookies relaterade till autentisering eller auktorisering använder en starkare princip än CookieSecurePolicy.None.

Du kan också skydda antiforgery cookie i icke-Development miljöer med hjälp av en säker anslutning med SSL, endast över HTTPS, genom att använda följande AntiforgeryOptions.Cookie egenskapsinställning i appens Program-fil:

if (!builder.Environment.IsDevelopment())
{
    builder.Services.AddAntiforgery(o =>
    {
        o.Cookie.SecurePolicy = CookieSecurePolicy.Always;
    });
}

Mer information finns i CookieAuthenticationOptions.

Generera tokens för skydd mot förfalskning med IAntiforgery

IAntiforgery tillhandahåller API:et för att konfigurera funktioner för skydd mot förfalskning. IAntiforgery kan begäras i Program.cs med hjälp av WebApplication.Services. I följande exempel används mellanprogram från appens startsida för att generera en skyddstoken mot förfalskning och skicka den i svaret som en cookie:

app.UseRouting();

app.UseAuthorization();

var antiforgery = app.Services.GetRequiredService<IAntiforgery>();

app.Use((context, next) =>
{
    var requestPath = context.Request.Path.Value;

    if (string.Equals(requestPath, "/", StringComparison.OrdinalIgnoreCase)
        || string.Equals(requestPath, "/index.html", StringComparison.OrdinalIgnoreCase))
    {
        var tokenSet = antiforgery.GetAndStoreTokens(context);
        context.Response.Cookies.Append("XSRF-TOKEN", tokenSet.RequestToken!,
            new CookieOptions { HttpOnly = false });
    }

    return next(context);
});

I föregående exempel anges en cookie med namnet XSRF-TOKEN. Klienten kan läsa den här cookie och ange dess värde som en rubrik som är kopplad till AJAX-begäranden. Till exempel innehåller Angular inbyggt XSRF-skydd som läser en cookie med namnet XSRF-TOKEN som standard.

Kräv validering för att förhindra förfalskning

ValidateAntiForgeryToken åtgärdsfiltret kan tillämpas på en enskild åtgärd, en kontroller eller globalt. Begäranden som görs till åtgärder som har det här filtret tillämpade blockeras om inte begäran innehåller en giltig antiforgery-token:

[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Index()
{
    // ...

    return RedirectToAction();
}

Attributet ValidateAntiForgeryToken kräver en token för begäranden till de åtgärdsmetoder som markeras, inklusive HTTP GET-begäranden. Om attributet ValidateAntiForgeryToken tillämpas på appens kontrollanter kan det åsidosättas med attributet IgnoreAntiforgeryToken.

Verifiera antiforgeringstoken automatiskt endast för osäkra HTTP-metoder

Istället för att använda attributet ValidateAntiForgeryToken på ett omfattande sätt och sedan åsidosätta det med IgnoreAntiforgeryToken-attributet, kan attributet AutoValidateAntiforgeryToken användas. Det här attributet fungerar identiskt med attributet ValidateAntiForgeryToken, förutom att det inte kräver token för begäranden som görs med hjälp av följande HTTP-metoder:

  • GET
  • HUVUD
  • ALTERNATIV
  • SPÅRA

Vi rekommenderar att du använder AutoValidateAntiforgeryToken brett för scenarier som inte är API-scenarier. Det här attributet säkerställer att POST-åtgärder skyddas som standard. Alternativet är att ignorera antiforgery-token som standard, såvida inte ValidateAntiForgeryToken tillämpas på enskilda åtgärdsmetoder. I det här scenariot är det mer troligt att en POST-åtgärdsmetod lämnas oskyddad av misstag, vilket gör appen sårbar för CSRF-attacker. Alla POST:er bör skicka antiforgery-token.

API:er har ingen automatisk mekanism för att skicka den icke-cookie delen av token. Implementeringen beror förmodligen på klientkodimplementeringen. Några exempel visas nedan:

Exempel på klassnivå:

[AutoValidateAntiforgeryToken]
public class HomeController : Controller

Globalt exempel:

builder.Services.AddControllersWithViews(options =>
{
    options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute());
});

Åsidosätt globala eller kontroller-antiförfalskningsattribut

Filtret IgnoreAntiforgeryToken används för att eliminera behovet av en antiforgerytoken för en viss åtgärd (eller kontroller). När det här filtret används åsidosätter det ValidateAntiForgeryToken- och AutoValidateAntiforgeryToken-filter som anges på en högre nivå (globalt eller på en kontrollenhet).

[IgnoreAntiforgeryToken]
public IActionResult IndexOverride()
{
    // ...

    return RedirectToAction();
}

Uppdatera token efter autentisering

Token bör uppdateras efter att användaren har autentiserats genom att omdirigera användaren till en vy eller Razor Pages-sidan.

JavaScript, AJAX och SPA

I traditionella HTML-baserade appar skickas antiforgerytoken till servern med hjälp av dolda formulärfält. I moderna JavaScript-baserade appar och SPA:er görs många begäranden programmatiskt. Dessa AJAX-begäranden kan använda andra tekniker, till exempel begärandehuvuden eller cookies, för att skicka token.

Om cookies används för att lagra autentiseringstoken och autentisera API-begäranden på servern är CSRF ett potentiellt problem. Om lokal lagring används för att lagra token kan säkerhetsrisken för CSRF minskas eftersom värden från lokal lagring inte skickas automatiskt till servern med varje begäran. Användning av lokal lagring för att spara antiförfalskningstoken på klienten och skicka tokenen som en begäranderubrik är en rekommenderad metod.

Blazor

Mer information finns i ASP.NET Core Blazor-autentisering och auktorisering.

JavaScript

När man använder JavaScript med vyer kan en token skapas med hjälp av en tjänst inifrån vyn. Mata in IAntiforgery-tjänsten i vyn och anropa GetAndStoreTokens:

@inject Microsoft.AspNetCore.Antiforgery.IAntiforgery Antiforgery

@{
    ViewData["Title"] = "JavaScript";

    var requestToken = Antiforgery.GetAndStoreTokens(Context).RequestToken;
}

<input id="RequestVerificationToken" type="hidden" value="@requestToken" />

<button id="button" class="btn btn-primary">Submit with Token</button>
<div id="result" class="mt-2"></div>

@section Scripts {
<script>
    document.addEventListener("DOMContentLoaded", () => {
        const resultElement = document.getElementById("result");

        document.getElementById("button").addEventListener("click", async () => {

            const response = await fetch("@Url.Action("FetchEndpoint")", {
                method: "POST",
                headers: {
                    RequestVerificationToken:
                        document.getElementById("RequestVerificationToken").value
                }
            });

            if (response.ok) {
                resultElement.innerText = await response.text();
            } else {
                resultElement.innerText = `Request Failed: ${response.status}`
            }
        });
    });
</script>
}

I föregående exempel används JavaScript för att läsa det dolda fältvärdet för AJAX POST-huvudet.

Den här metoden eliminerar behovet av att hantera att ange cookies direkt från servern eller läsa dem från klienten. Men när det inte går att injicera IAntiforgery-tjänsten, använd JavaScript för att komma åt token i cookies.

  • Åtkomsttoken i en ytterligare begäran till servern, vanligtvis same-origin.
  • Använd innehållet i cookieför att skapa en rubrik med tokens värde.

Om skriptet skickar token i ett begärandehuvud med namnet X-XSRF-TOKENkonfigurerar du tjänsten för förfalskningsbekämpning för att leta efter X-XSRF-TOKEN-huvudet:

builder.Services.AddAntiforgery(options => options.HeaderName = "X-XSRF-TOKEN");

I följande exempel läggs en skyddad slutpunkt till som skriver en begärandetoken till en för JavaScript läsbar cookie:

app.UseAuthorization();
app.MapGet("antiforgery/token", (IAntiforgery forgeryService, HttpContext context) =>
{
    var tokens = forgeryService.GetAndStoreTokens(context);
    context.Response.Cookies.Append("XSRF-TOKEN", tokens.RequestToken!,
            new CookieOptions { HttpOnly = false });

    return Results.Ok();
}).RequireAuthorization();

I följande exempel används JavaScript för att göra en AJAX-begäran för att hämta token och göra en annan begäran med rätt rubrik:

var response = await fetch("/antiforgery/token", {
    method: "GET",
    headers: { "Authorization": authorizationToken }
});

if (response.ok) {
    // https://developer.mozilla.org/docs/web/api/document/cookie
    const xsrfToken = document.cookie
        .split("; ")
        .find(row => row.startsWith("XSRF-TOKEN="))
        .split("=")[1];

    response = await fetch("/JavaScript/FetchEndpoint", {
        method: "POST",
        headers: { "X-XSRF-TOKEN": xsrfToken, "Authorization": authorizationToken }
    });

    if (response.ok) {
        resultElement.innerText = await response.text();
    } else {
        resultElement.innerText = `Request Failed: ${response.status}`
    }
} else {    
    resultElement.innerText = `Request Failed: ${response.status}`
}

Obs

När anti-förfalsknings-token anges i både begärandehuvudet och i formulärets nyttolast verifieras endast tokenen i begärandehuvudet.

Antiforgery med minimala APIer

Anropa AddAntiforgery och UseAntiforgery(IApplicationBuilder) för att registrera tjänster för förfalskningsskydd i DI. Antiforgery-tokenar används för att motverka Cross-Site Request Forgery-attacker.

var builder = WebApplication.CreateBuilder();

builder.Services.AddAntiforgery();

var app = builder.Build();

app.UseAntiforgery();

app.MapGet("/", () => "Hello World!");

app.Run();

Antiförfalskningsmellanprogrammet:

Antiforgery-token verifieras endast om:

  • Slutpunkten innehåller metadata som implementerar IAntiforgeryMetadata där RequiresValidation=true.
  • HTTP-metoden som är associerad med slutpunkten är en relevant HTTP-metod av typen POST, PUT eller PATCH.
  • Begäran är associerad med en giltig slutpunkt.

Mellanprogrammet för skydd mot förfalskning avbryter inte begärandepipelinen. Slutpunktskoden körs alltid, även om tokenverifieringen misslyckas. För att observera resultatet av tokenverifieringen, lös IAntiforgeryValidationFeature från HttpContext.Features och inspektera dess IsValid-egenskap eller Error-egenskapen för information om fel. Det här tillvägagångssättet är användbart när slutpunkter kräver anpassad hantering vid misslyckad antiförfalskningsvalidering.

Obs! När det är aktiverat manuellt måste mellanprogrammet för skydd mot förfalskning köras efter mellanprogrammet för autentisering och auktorisering för att förhindra att formulärdata läsas när användaren är oautentiserad.

Som standard kräver minimala API:er som accepterar formulärdata validering av CSRF-token och stoppas innan applikationskoden körs om CSRF-valideringen inte lyckas.

Överväg följande GenerateForm metod:

public static string GenerateForm(string action, 
    AntiforgeryTokenSet token, bool UseToken=true)
{
    string tokenInput = "";
    if (UseToken)
    {
        tokenInput = $@"<input name=""{token.FormFieldName}""
                         type=""hidden"" value=""{token.RequestToken}"" />";
    }

    return $@"
    <html><body>
        <form action=""{action}"" method=""POST"" enctype=""multipart/form-data"">
            {tokenInput}
            <input type=""text"" name=""name"" />
            <input type=""date"" name=""dueDate"" />
            <input type=""checkbox"" name=""isCompleted"" />
            <input type=""submit"" />
        </form>
    </body></html>
";
}

Föregående kod har tre argument, åtgärden, antiforgery-token och en bool som anger om token ska användas.

Tänk på följande exempel:

using Microsoft.AspNetCore.Antiforgery;
using Microsoft.AspNetCore.Mvc;

var builder = WebApplication.CreateBuilder();

builder.Services.AddAntiforgery();

var app = builder.Build();

app.UseAntiforgery();

// Pass token
app.MapGet("/", (HttpContext context, IAntiforgery antiforgery) =>
{
    var token = antiforgery.GetAndStoreTokens(context);
    return Results.Content(MyHtml.GenerateForm("/todo", token), "text/html");
});

// Don't pass a token, fails
app.MapGet("/SkipToken", (HttpContext context, IAntiforgery antiforgery) =>
{
    var token = antiforgery.GetAndStoreTokens(context);
    return Results.Content(MyHtml.GenerateForm("/todo",token, false ), "text/html");
});

// Post to /todo2. DisableAntiforgery on that endpoint so no token needed.
app.MapGet("/DisableAntiforgery", (HttpContext context, IAntiforgery antiforgery) =>
{
    var token = antiforgery.GetAndStoreTokens(context);
    return Results.Content(MyHtml.GenerateForm("/todo2", token, false), "text/html");
});

app.MapPost("/todo", ([FromForm] Todo todo) => Results.Ok(todo));

app.MapPost("/todo2", ([FromForm] Todo todo) => Results.Ok(todo))
                                                .DisableAntiforgery();

app.Run();

class Todo
{
    public required string Name { get; set; }
    public bool IsCompleted { get; set; }
    public DateTime DueDate { get; set; }
}

public static class MyHtml
{
    public static string GenerateForm(string action, 
        AntiforgeryTokenSet token, bool UseToken=true)
    {
        string tokenInput = "";
        if (UseToken)
        {
            tokenInput = $@"<input name=""{token.FormFieldName}""
                             type=""hidden"" value=""{token.RequestToken}"" />";
        }

        return $@"
        <html><body>
            <form action=""{action}"" method=""POST"" enctype=""multipart/form-data"">
                {tokenInput}
                <input type=""text"" name=""name"" />
                <input type=""date"" name=""dueDate"" />
                <input type=""checkbox"" name=""isCompleted"" />
                <input type=""submit"" />
            </form>
        </body></html>
    ";
    }
}

I föregående kod publicerar du till:

  • /todo kräver en giltig förfalskningsskyddstoken.
  • /todo2 kräver inte en giltig antiförfalskningstoken eftersom DisableAntiforgery anropas.
app.MapPost("/todo", ([FromForm] Todo todo) => Results.Ok(todo));

app.MapPost("/todo2", ([FromForm] Todo todo) => Results.Ok(todo))
                                                .DisableAntiforgery();

Varning

Anrop .DisableAntiforgery() inaktiverar CSRF-skydd (cross-site request forgery) för slutpunkten. Detta bör endast användas när en slutpunkt inte är sårbar för CSRF-attacker, till exempel:

  • Slutpunkter som inte kan anropas från en webbläsare (till exempel interna API:er)
  • Slutpunkter som skyddas med icke-baserad autentisering (till exempel ägartoken eller API-nycklarcookie)
  • Interna slutpunkter eller infrastrukturslutpunkter som inte förlitar sig på användarcookies

Inaktivera inte antiförfalskningsverifiering för webbläsartillgängliga slutpunkter som förlitar sig på cookies för autentisering eller som bearbetar formulärdata som skickas in av användaren, eftersom detta gör ditt program tillgängligt för CSRF-attacker.

Ett inlägg till:

  • /todo från formuläret som genereras av slutpunkten / lyckas eftersom förfalskningsskyddstoken är giltig.
  • /todo från formuläret som genereras av /SkipToken misslyckas eftersom anti-förfalskningsmekanismen inte ingår.
  • /todo2 från formuläret som genereras av /DisableAntiforgery-ändpunkten lyckas eftersom förfalskningsskydd inte krävs.
app.MapPost("/todo", ([FromForm] Todo todo) => Results.Ok(todo));

app.MapPost("/todo2", ([FromForm] Todo todo) => Results.Ok(todo))
                                                .DisableAntiforgery();

När ett formulär skickas utan en giltig säkerhetskod:

  • I miljön Development genereras ett undantag.
  • I miljön Production loggas ett meddelande.

HTTP-metodbegränsningar och HttpMethodOverrideMiddleware interaktion

För det middleware-baserade förfalskningsskyddsflödet validerar AntiforgeryMiddleware och UseAntiforgery() förfalskningsskyddstoken endast för HTTP-POST-, PUT- och PATCH-begäranden. Andra HTTP-metoder, till exempel DELETE, verifieras inte automatiskt.

Om du vill validera antiförfalskningstoken för andra HTTP-metoder löser du IAntiforgery från DI och anropar ValidateRequestAsync eller IsRequestValidAsync uttryckligen:

app.MapDelete("/item/{id}", async (int id, IAntiforgery antiforgery, HttpContext context) =>
{
    await antiforgery.ValidateRequestAsync(context);
    // Process the DELETE request
});

Varning

När HttpMethodOverrideMiddleware har konfigurerats med FormFieldName (formulärfältsläge) och placerats före AntiforgeryMiddlewarekan en POST-begäran åsidosättas till DELETE (eller någon annan icke-validerad metod). Eftersom AntiforgeryMiddleware endast validerar POST, PUT och PATCH, kringgår den åsidosatta begäran validering av förfalskningsskydd.

Så här skyddar du dessa slutpunkter:

  • Placera helst HttpMethodOverrideMiddleware efter antiforgery-validering när din pipeline tillåter det.
  • Undvik åsidosättningar av formulärfält för slutpunkter som använder antiförfalskningsvalidering.
  • Om åsidosättningen av formulärfält måste köras först, validera antiforgery-tokenen uttryckligen med IAntiforgery.ValidateRequestAsync.

Konfigurationsinformation finns i ASP.NET Core mellanprogram.

Windows-autentisering och förfalskningsskyddande cookies

När du använder Windows-autentisering måste programslutpunkter skyddas mot CSRF-attacker på samma sätt som för cookies. Webbläsaren skickar implicit autentiseringskontexten till servern och slutpunkterna måste skyddas mot CSRF-attacker.

Utöka förfalskningsskydd

Med IAntiforgeryAdditionalDataProvider-typen kan utvecklare utöka beteendet för anti-CSRF-systemet genom att skicka ytterligare data fram och tillbaka med varje token. Metoden GetAdditionalData anropas varje gång en fälttoken genereras och returvärdet bäddas in i den genererade token. En implementer kan returnera en tidsstämpel, en nonce eller något annat värde och sedan anropa ValidateAdditionalData för att verifiera dessa data när token verifieras. Klientens användarnamn är redan inbäddat i de genererade token, så du behöver inte inkludera den här informationen. Om en token innehåller kompletterande data men ingen IAntiForgeryAdditionalDataProvider har konfigurerats verifieras inte tilläggsdata.

Ytterligare resurser

Förfalskning av begäranden mellan webbplatser (även kallat XSRF eller CSRF) är en attack mot webbaserade appar där en skadlig webbapp kan påverka interaktionen mellan en klientwebbläsare och en webbapp som litar på webbläsaren. Dessa attacker är möjliga eftersom webbläsare skickar vissa typer av autentiseringstoken automatiskt med varje begäran till en webbplats. Den här typen av exploatering kallas även för en attack med ett klick eller session som körs eftersom attacken utnyttjar användarens tidigare autentiserade session.

Ett exempel på en CSRF-attack:

  1. En användare loggar in på www.good-banking-site.example.com med formulärautentisering. Servern autentiserar användaren och utfärdar ett svar som innehåller en autentisering cookie. Webbplatsen är sårbar för angrepp eftersom den litar på alla förfrågningar som den tar emot med en giltig autentisering cookie.

  2. Användaren besöker en skadlig webbplats www.bad-crook-site.example.com.

    Den skadliga webbplatsen, www.bad-crook-site.example.com, innehåller ett HTML-formulär som liknar följande exempel:

    <h1>Congratulations! You're a Winner!</h1>
    <form action="https://www.good-banking-site.example.com/api/account" method="post">
        <input type="hidden" name="Transaction" value="withdraw" />
        <input type="hidden" name="Amount" value="1000000" />
        <input type="submit" value="Click to collect your prize!" />
    </form>
    

    Observera att formulärets action skickas till den sårbara webbplatsen, inte till den skadliga webbplatsen. Det här är "cross-site"-delen av CSRF.

  3. Användaren väljer knappen Skicka. Webbläsaren gör begäran och innehåller automatiskt autentiseringen cookie för den begärda domänen www.good-banking-site.example.com.

  4. Begäran körs på www.good-banking-site.example.com-servern med användarens autentiseringskontext och kan utföra alla åtgärder som en autentiserad användare tillåts utföra.

Förutom scenariot där användaren väljer knappen för att skicka formuläret kan den skadliga webbplatsen:

  • Kör ett skript som automatiskt skickar formuläret.
  • Skicka formuläret som en AJAX-begäran.
  • Dölj formuläret med hjälp av CSS.

Dessa alternativa scenarier kräver ingen åtgärd eller indata från användaren förutom att först besöka den skadliga webbplatsen.

Att använda HTTPS förhindrar inte en CSRF-attack. Den skadliga webbplatsen kan skicka https://www.good-banking-site.example.com/ en begäran lika enkelt som den kan skicka en osäker begäran.

Vissa attacker, anger mot slutpunkter som svarar på GET-begäranden, i så fall kan en img-tagg användas för att utföra åtgärden. Den här typen av angrepp är vanlig på forumwebbplatser som tillåter bilder men blockerar JavaScript. Appar som ändrar tillstånd för GET-begäranden, där variabler eller resurser ändras, är sårbara för skadliga attacker. GET-begäranden som ändrar tillstånd är osäkra. En bästa praxis är att aldrig ändra tillstånd för en GET-begäran.

CSRF-attacker är möjliga mot webbappar som använder cookies för autentisering eftersom:

  • Webbläsare lagrar cookies som utfärdats av en webbapp.
  • Lagrade cookies inkluderar sessionscookies för autentiserade användare.
  • Webbläsare skickar alla cookies som är associerade med en domän till webbappen varje begäran oavsett hur begäran till appen genererades i webbläsaren.

CSRF-attacker är dock inte begränsade till att utnyttja cookies. Till exempel är grundläggande och sammanfattad autentisering också sårbara. När en användare har loggat in med Basic- eller Digest-autentisering skickar webbläsaren automatiskt autentiseringsuppgifterna tills sessionen är slut.

I det här sammanhanget refererar session till den session på klientsidan som användaren autentiseras under. Det är inte relaterat till sessioner på serversidan eller ASP.NET Core sessionsmellanprogram.

Användare kan skydda mot CSRF-sårbarheter genom att vidta försiktighetsåtgärder:

  • Logga ut från webbappar när du är klar med att använda dem.
  • Rensa webbläsarcookies med jämna mellanrum.

CsRF-sårbarheter är dock i grunden ett problem med webbappen, inte slutanvändaren.

Grunderna för autentisering

Cookie-baserad autentisering är en populär form av autentisering. Tokenbaserade autentiseringssystem växer i popularitet, särskilt för ensidesprogram (SPA).

När en användare autentiserar med sitt användarnamn och lösenord utfärdas en token som innehåller en autentiseringsbiljett som kan användas för autentisering och auktorisering. Token lagras som en cookie som skickas med varje begäran som klienten gör. Generering och validering av detta cookie utförs av mellanprogrammet för cookie autentisering. mellanprogram serialiserar ett användarhuvudnamn till en krypterad cookie. Vid efterföljande begäranden validerar mellanprogrammet cookie, återskapar principalen och tilldelar principalen till egenskapen HttpContext.User.

Tokenbaserad autentisering

När en användare autentiseras utfärdas en token (inte en antiforgery-token). Tokenet innehåller användarinformation i form av anspråk eller en referenstoken som pekar appen mot användartillståndet som underhålls i appen. När en användare försöker komma åt en resurs som kräver autentisering skickas token till appen med ett extra auktoriseringshuvud i form av en Bearer token. Den här metoden gör appen tillståndslös. I varje efterföljande begäran skickas token i begäran om verifiering på serversidan. Den här token är inte krypterad; det är kodat. På servern avkodas token för att komma åt informationen. Om du vill skicka token på efterföljande begäranden lagrar du token i webbläsarens lokala lagring. Att placera en token i webbläsarens lokala lagring och hämta den och använda den som en ägartoken ger skydd mot CSRF-attacker. Men om appen skulle vara sårbar för skriptinmatning via XSS eller en komprometterad extern javascript-fil kan en cyberattacker hämta valfritt värde från lokal lagring och skicka det till sig själva. ASP.NET Core kodar alla utdata på serversidan från variabler som standard, vilket minskar risken för XSS. Om du åsidosätter det här beteendet med hjälp av Html.Raw- eller anpassad kod med ej betrodda indata kan du öka risken för XSS.

Oroa dig inte för CSRF-sårbarhet om token lagras i webbläsarens lokala lagring. CSRF är ett problem när token lagras i en cookie. Mer information finns i GitHub-problemet SPA-kodexempel lägger till två cookies.

Flera appar som finns i en domän

Delade värdmiljöer är sårbara för sessionskapning, inloggnings-CSRF och andra attacker.

Även om example1.contoso.net och example2.contoso.net är olika värdar finns det en implicit förtroenderelation mellan värdar under den *.contoso.net domänen. Den här implicita förtroenderelationen gör att potentiellt ej betrodda värdar kan påverka varandras cookies (principerna för samma ursprung som styr AJAX-begäranden gäller inte nödvändigtvis för HTTP-cookies).

Attacker som utnyttjar betrodda cookies mellan appar som finns på samma domän kan förhindras genom att inte dela domäner. När varje app finns på sin egen domän finns det ingen implicit cookie förtroenderelation att utnyttja.

Antiförfalskning i ASP.NET Core

Varning

ASP.NET Core använder ASP.NET Core Data Protectionför att implementera skydd mot förfalskning. Dataskyddsstacken måste konfigureras för att fungera i en servergrupp. Mer information finns i Konfigurera dataskydd.

Antiforgery-mellanprogram läggs till i containern Dependency injection när något av följande API:er anropas i Program.cs:

FormTagHelper infogar antiforgery-token i HTML-formulärelement. Följande kod i en Razor-fil genererar automatiskt antiforgery-token:

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

På samma sätt genererar IHtmlHelper.BeginForm antiforgerytoken som standard om formulärets metod inte är GET.

Den automatiska genereringen av antiforgery-token för HTML-formulärelement sker när taggen <form> innehåller attributet method="post" och något av följande är sant:

  • Åtgärdsattributet är tomt (action="").
  • Åtgärdsattributet anges inte (<form method="post">).

Automatisk generering av antiforgery-token för HTML-formulärelement kan inaktiveras:

  • Avaktivera antifalsifieringstoken uttryckligen med attributet asp-antiforgery:

    <form method="post" asp-antiforgery="false">
        <!-- ... -->
    </form>
    
  • Formulärelementet väljs bort från Tag Helpers genom att använda Tag Helper ! opt-out-symbolen:

    <!form method="post">
        <!-- ... -->
    </!form>
    
  • Ta bort FormTagHelper från vyn. Du kan ta bort FormTagHelper från en vy genom att lägga till följande direktiv i vyn Razor:

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

Obs

Razor Pages skyddas automatiskt från XSRF/CSRF. Mer information finns i XSRF/CSRF och Razor Pages.

Den vanligaste metoden för att försvara sig mot CSRF-attacker är att använda Synkroniserartokens mönster (STP). STP används när användaren begär en sida med formulärdata:

  1. Servern skickar en token som är associerad med den aktuella användarens identitet till klienten.
  2. Klienten skickar tillbaka token till servern för verifiering.
  3. Om servern tar emot en token som inte matchar den autentiserade användarens identitet avvisas begäran.

Token är unik och oförutsägbar. Token kan också användas för att säkerställa korrekt sekvensering av en serie begäranden (till exempel genom att säkerställa begärandesekvensen på sidan 1 > sida 2 > sida 3). Alla formulär i ASP.NET Core MVC- och Razor Pages-mallar genererar antiforgery-token. Följande par av vyexempel genererar anti-förfalskningstecken:

<form asp-action="Index" asp-controller="Home" method="post">
    <!-- ... -->
</form>

@using (Html.BeginForm("Index", "Home"))
{
    <!-- ... -->
}

Lägg till en antiforgery-token uttryckligen i ett <form>-element utan att använda Tag Helpers med HTML-hjälparen @Html.AntiForgeryToken:

<form asp-action="Index" asp-controller="Home" method="post">
    @Html.AntiForgeryToken()

    <!-- ... -->
</form>

I vart och ett av de föregående fallen lägger ASP.NET Core till ett dolt formulärfält som liknar följande exempel:

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

ASP.NET Core innehåller tre filter för arbete med antiförfalsknings-token:

Antiförfalskning med AddControllers

Att anropa AddControllers gör inte att antiförfalskningsmarkörer aktiveras. AddControllersWithViews måste anropas för att ha inbyggt stöd för antiförfalskningstoken.

Flera webbläsarflikar och mönstret för synkroniseringstoken

Med Synkroniserare token-mönstret innehåller endast den senast inlästa sidan en giltig antiförfalskningstoken. Det kan vara problematiskt att använda flera flikar. Om en användare till exempel öppnar flera flikar:

  • Endast den senast inlästa fliken innehåller en giltig skyddstoken.
  • Begäranden från tidigare inlästa flikar misslyckas med ett fel: Antiforgery token validation failed. The antiforgery cookie token and request token do not match

Överväg alternativa CSRF-skyddsmönster om detta utgör ett problem.

Konfigurera förfalskningsskydd med AntiforgeryOptions

Anpassa AntiforgeryOptions i appens Program fil:

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

Ange egenskaper för förfalskningsskydd cookie med hjälp av egenskaperna för klassen CookieBuilder, som du ser i följande tabell.

Alternativ Beskrivning
Cookie Avgör vilka inställningar som används för att skapa antiforgery-cookies.
FormFieldName Namnet på det gömda formulärfältet som används av antiforgery-systemet för att generera antiforgery-tokens i vyer.
HeaderName Namnet på rubriken som används av antiforgerysystemet. Om nulltar systemet endast hänsyn till formulärdata.
SuppressXFrameOptionsHeader Anger om du vill utelämna genereringen av X-Frame-Options-huvudet. Som standard genereras rubriken med värdet "SAMEORIGIN". Ställs in som standard till false.

Vissa webbläsare tillåter inte osäkra slutpunkter att ange cookies med en "säker" flagga eller skriva över cookies vars "säkra" flagga har angetts (mer information finns i Inaktuell ändring av "säkra" cookies från icke-säkra ursprung). Eftersom blandningen av säkra och osäkra slutpunkter är ett vanligt scenario i appar, minskar ASP.NET Core restriktionen på den säkra policyn för vissa cookies, som till exempel antiforgery cookie, genom att ställa in cookies SecurePolicy till CookieSecurePolicy.None. Även om en obehörig användare stjäl en antiforgery cookie, måste de också stjäla den antiforgery-token som vanligtvis skickas via ett formulärfält (oftare) eller en separat begäran-rubrik (mer sällan) plus autentiseringen cookie. Cookies relaterade till autentisering eller auktorisering använder en starkare princip än CookieSecurePolicy.None.

Du kan också skydda antiforgery cookie i icke-Development miljöer med hjälp av en säker anslutning med SSL, endast över HTTPS, genom att använda följande AntiforgeryOptions.Cookie egenskapsinställning i appens Program-fil:

if (!builder.Environment.IsDevelopment())
{
    builder.Services.AddAntiforgery(o =>
    {
        o.Cookie.SecurePolicy = CookieSecurePolicy.Always;
    });
}

Mer information finns i CookieAuthenticationOptions.

Generera tokens för skydd mot förfalskning med IAntiforgery

IAntiforgery tillhandahåller API:et för att konfigurera funktioner för skydd mot förfalskning. IAntiforgery kan begäras i Program.cs med hjälp av WebApplication.Services. I följande exempel används mellanprogram från appens startsida för att generera en skyddstoken mot förfalskning och skicka den i svaret som en cookie:

app.UseRouting();

app.UseAuthorization();

var antiforgery = app.Services.GetRequiredService<IAntiforgery>();

app.Use((context, next) =>
{
    var requestPath = context.Request.Path.Value;

    if (string.Equals(requestPath, "/", StringComparison.OrdinalIgnoreCase)
        || string.Equals(requestPath, "/index.html", StringComparison.OrdinalIgnoreCase))
    {
        var tokenSet = antiforgery.GetAndStoreTokens(context);
        context.Response.Cookies.Append("XSRF-TOKEN", tokenSet.RequestToken!,
            new CookieOptions { HttpOnly = false });
    }

    return next(context);
});

I föregående exempel anges en cookie med namnet XSRF-TOKEN. Klienten kan läsa den här cookie och ange dess värde som en rubrik som är kopplad till AJAX-begäranden. Till exempel innehåller Angular inbyggt XSRF-skydd som läser en cookie med namnet XSRF-TOKEN som standard.

Kräv validering för att förhindra förfalskning

ValidateAntiForgeryToken åtgärdsfiltret kan tillämpas på en enskild åtgärd, en kontroller eller globalt. Begäranden som görs till åtgärder som har det här filtret tillämpade blockeras om inte begäran innehåller en giltig antiforgery-token:

[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Index()
{
    // ...

    return RedirectToAction();
}

Attributet ValidateAntiForgeryToken kräver en token för begäranden till de åtgärdsmetoder som markeras, inklusive HTTP GET-begäranden. Om attributet ValidateAntiForgeryToken tillämpas på appens kontrollanter kan det åsidosättas med attributet IgnoreAntiforgeryToken.

Verifiera antiforgeringstoken automatiskt endast för osäkra HTTP-metoder

Istället för att använda attributet ValidateAntiForgeryToken på ett omfattande sätt och sedan åsidosätta det med IgnoreAntiforgeryToken-attributet, kan attributet AutoValidateAntiforgeryToken användas. Det här attributet fungerar identiskt med attributet ValidateAntiForgeryToken, förutom att det inte kräver token för begäranden som görs med hjälp av följande HTTP-metoder:

  • GET
  • HUVUD
  • ALTERNATIV
  • SPÅRA

Vi rekommenderar att du använder AutoValidateAntiforgeryToken brett för scenarier som inte är API-scenarier. Det här attributet säkerställer att POST-åtgärder skyddas som standard. Alternativet är att ignorera antiforgery-token som standard, såvida inte ValidateAntiForgeryToken tillämpas på enskilda åtgärdsmetoder. I det här scenariot är det mer troligt att en POST-åtgärdsmetod lämnas oskyddad av misstag, vilket gör appen sårbar för CSRF-attacker. Alla POST:er bör skicka antiforgery-token.

API:er har ingen automatisk mekanism för att skicka den icke-cookie delen av token. Implementeringen beror förmodligen på klientkodimplementeringen. Några exempel visas nedan:

Exempel på klassnivå:

[AutoValidateAntiforgeryToken]
public class HomeController : Controller

Globalt exempel:

builder.Services.AddControllersWithViews(options =>
{
    options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute());
});

Åsidosätt globala eller kontroller-antiförfalskningsattribut

Filtret IgnoreAntiforgeryToken används för att eliminera behovet av en antiforgerytoken för en viss åtgärd (eller kontroller). När det här filtret används åsidosätter det ValidateAntiForgeryToken- och AutoValidateAntiforgeryToken-filter som anges på en högre nivå (globalt eller på en kontrollenhet).

[IgnoreAntiforgeryToken]
public IActionResult IndexOverride()
{
    // ...

    return RedirectToAction();
}

Uppdatera token efter autentisering

Token bör uppdateras efter att användaren har autentiserats genom att omdirigera användaren till en vy eller Razor Pages-sidan.

JavaScript, AJAX och SPA

I traditionella HTML-baserade appar skickas antiforgerytoken till servern med hjälp av dolda formulärfält. I moderna JavaScript-baserade appar och SPA:er görs många begäranden programmatiskt. Dessa AJAX-begäranden kan använda andra tekniker (till exempel begärandehuvuden eller cookies) för att skicka token.

Om cookies används för att lagra autentiseringstoken och autentisera API-begäranden på servern är CSRF ett potentiellt problem. Om lokal lagring används för att lagra token kan säkerhetsrisken för CSRF minskas eftersom värden från lokal lagring inte skickas automatiskt till servern med varje begäran. Användning av lokal lagring för att spara antiförfalskningstoken på klienten och skicka tokenen som en begäranderubrik är en rekommenderad metod.

JavaScript

När man använder JavaScript med vyer kan en token skapas med hjälp av en tjänst inifrån vyn. Mata in IAntiforgery-tjänsten i vyn och anropa GetAndStoreTokens:

@inject Microsoft.AspNetCore.Antiforgery.IAntiforgery Antiforgery

@{
    ViewData["Title"] = "JavaScript";

    var requestToken = Antiforgery.GetAndStoreTokens(Context).RequestToken;
}

<input id="RequestVerificationToken" type="hidden" value="@requestToken" />

<button id="button" class="btn btn-primary">Submit with Token</button>
<div id="result" class="mt-2"></div>

@section Scripts {
<script>
    document.addEventListener("DOMContentLoaded", () => {
        const resultElement = document.getElementById("result");

        document.getElementById("button").addEventListener("click", async () => {

            const response = await fetch("@Url.Action("FetchEndpoint")", {
                method: "POST",
                headers: {
                    RequestVerificationToken:
                        document.getElementById("RequestVerificationToken").value
                }
            });

            if (response.ok) {
                resultElement.innerText = await response.text();
            } else {
                resultElement.innerText = `Request Failed: ${response.status}`
            }
        });
    });
</script>
}

I föregående exempel används JavaScript för att läsa det dolda fältvärdet för AJAX POST-huvudet.

Den här metoden eliminerar behovet av att hantera att ange cookies direkt från servern eller läsa dem från klienten. Men när det inte går att injicera IAntiforgery-tjänsten, använd JavaScript för att komma åt token i cookies.

  • Åtkomsttoken i en ytterligare begäran till servern, vanligtvis same-origin.
  • Använd innehållet i cookieför att skapa en rubrik med tokens värde.

Om skriptet skickar token i ett begärandehuvud med namnet X-XSRF-TOKENkonfigurerar du tjänsten för förfalskningsbekämpning för att leta efter X-XSRF-TOKEN-huvudet:

builder.Services.AddAntiforgery(options => options.HeaderName = "X-XSRF-TOKEN");

I följande exempel läggs en skyddad slutpunkt till som skriver en begärandetoken till en för JavaScript läsbar cookie:

app.UseAuthorization();
app.MapGet("antiforgery/token", (IAntiforgery forgeryService, HttpContext context) =>
{
    var tokens = forgeryService.GetAndStoreTokens(context);
    context.Response.Cookies.Append("XSRF-TOKEN", tokens.RequestToken!,
            new CookieOptions { HttpOnly = false });

    return Results.Ok();
}).RequireAuthorization();

I följande exempel används JavaScript för att göra en AJAX-begäran för att hämta token och göra en annan begäran med rätt rubrik:

var response = await fetch("/antiforgery/token", {
    method: "GET",
    headers: { "Authorization": authorizationToken }
});

if (response.ok) {
    // https://developer.mozilla.org/docs/web/api/document/cookie
    const xsrfToken = document.cookie
        .split("; ")
        .find(row => row.startsWith("XSRF-TOKEN="))
        .split("=")[1];

    response = await fetch("/JavaScript/FetchEndpoint", {
        method: "POST",
        headers: { "X-XSRF-TOKEN": xsrfToken, "Authorization": authorizationToken }
    });

    if (response.ok) {
        resultElement.innerText = await response.text();
    } else {
        resultElement.innerText = `Request Failed: ${response.status}`
    }
} else {    
    resultElement.innerText = `Request Failed: ${response.status}`
}

Obs

När anti-förfalsknings-token anges i både begärandehuvudet och i formulärets nyttolast verifieras endast tokenen i begärandehuvudet.

Antiforgery med minimala APIer

Minimal APIs stöder inte användningen av de inkluderade filtren (ValidateAntiForgeryToken, AutoValidateAntiforgeryToken, IgnoreAntiforgeryToken), men IAntiforgery tillhandahåller de API:er som krävs för att verifiera en begäran.

I följande exempel skapas ett filter som verifierar antiforgery-token:

internal static class AntiForgeryExtensions
{
    public static TBuilder ValidateAntiforgery<TBuilder>(this TBuilder builder) where TBuilder : IEndpointConventionBuilder
    {
        return builder.AddEndpointFilter(routeHandlerFilter: async (context, next) =>
        {
            try
            {
                var antiForgeryService = context.HttpContext.RequestServices.GetRequiredService<IAntiforgery>();
                await antiForgeryService.ValidateRequestAsync(context.HttpContext);
            }
            catch (AntiforgeryValidationException)
            {
                return Results.BadRequest("Antiforgery token validation failed.");
            }

            return await next(context);

        });
    }
}

Filtret kan sedan tillämpas på en slutpunkt:

app.MapPost("api/upload", (IFormFile name) => Results.Accepted())
    .RequireAuthorization()
    .ValidateAntiforgery();

Windows-autentisering och förfalskningsskyddande cookies

När du använder Windows-autentisering måste programslutpunkter skyddas mot CSRF-attacker på samma sätt som för cookies. Webbläsaren skickar implicit autentiseringskontexten till servern och slutpunkterna måste skyddas mot CSRF-attacker.

Utöka förfalskningsskydd

Med IAntiforgeryAdditionalDataProvider-typen kan utvecklare utöka beteendet för anti-CSRF-systemet genom att skicka ytterligare data fram och tillbaka med varje token. Metoden GetAdditionalData anropas varje gång en fälttoken genereras och returvärdet bäddas in i den genererade token. En implementer kan returnera en tidsstämpel, en nonce eller något annat värde och sedan anropa ValidateAdditionalData för att verifiera dessa data när token verifieras. Klientens användarnamn är redan inbäddat i de genererade token, så du behöver inte inkludera den här informationen. Om en token innehåller kompletterande data men ingen IAntiForgeryAdditionalDataProvider har konfigurerats verifieras inte tilläggsdata.

Ytterligare resurser

Förfalskning av begäranden mellan webbplatser (även kallat XSRF eller CSRF) är en attack mot webbaserade appar där en skadlig webbapp kan påverka interaktionen mellan en klientwebbläsare och en webbapp som litar på webbläsaren. Dessa attacker är möjliga eftersom webbläsare skickar vissa typer av autentiseringstoken automatiskt med varje begäran till en webbplats. Den här typen av exploatering kallas även för en attack med ett klick eller session som körs eftersom attacken utnyttjar användarens tidigare autentiserade session.

Ett exempel på en CSRF-attack:

  1. En användare loggar in på www.good-banking-site.example.com med formulärautentisering. Servern autentiserar användaren och utfärdar ett svar som innehåller en autentisering cookie. Webbplatsen är sårbar för angrepp eftersom den litar på alla förfrågningar som den tar emot med en giltig autentisering cookie.

  2. Användaren besöker en skadlig webbplats www.bad-crook-site.example.com.

    Den skadliga webbplatsen, www.bad-crook-site.example.com, innehåller ett HTML-formulär som liknar följande exempel:

    <h1>Congratulations! You're a Winner!</h1>
    <form action="https://www.good-banking-site.example.com/api/account" method="post">
        <input type="hidden" name="Transaction" value="withdraw" />
        <input type="hidden" name="Amount" value="1000000" />
        <input type="submit" value="Click to collect your prize!" />
    </form>
    

    Observera att formulärets action skickas till den sårbara webbplatsen, inte till den skadliga webbplatsen. Det här är "cross-site"-delen av CSRF.

  3. Användaren väljer knappen Skicka. Webbläsaren gör begäran och innehåller automatiskt autentiseringen cookie för den begärda domänen www.good-banking-site.example.com.

  4. Begäran körs på www.good-banking-site.example.com-servern med användarens autentiseringskontext och kan utföra alla åtgärder som en autentiserad användare tillåts utföra.

Förutom scenariot där användaren väljer knappen för att skicka formuläret kan den skadliga webbplatsen:

  • Kör ett skript som automatiskt skickar formuläret.
  • Skicka formuläret som en AJAX-begäran.
  • Dölj formuläret med hjälp av CSS.

Dessa alternativa scenarier kräver ingen åtgärd eller indata från användaren förutom att först besöka den skadliga webbplatsen.

Att använda HTTPS förhindrar inte en CSRF-attack. Den skadliga webbplatsen kan skicka https://www.good-banking-site.example.com/ en begäran lika enkelt som den kan skicka en osäker begäran.

Vissa attacker, anger mot slutpunkter som svarar på GET-begäranden, i så fall kan en img-tagg användas för att utföra åtgärden. Den här typen av angrepp är vanlig på forumwebbplatser som tillåter bilder men blockerar JavaScript. Appar som ändrar tillstånd för GET-begäranden, där variabler eller resurser ändras, är sårbara för skadliga attacker. GET-begäranden som ändrar tillstånd är osäkra. En bästa praxis är att aldrig ändra tillstånd för en GET-begäran.

CSRF-attacker är möjliga mot webbappar som använder cookies för autentisering eftersom:

  • Webbläsare lagrar cookies som utfärdats av en webbapp.
  • Lagrade cookies inkluderar sessionscookies för autentiserade användare.
  • Webbläsare skickar alla cookies som är associerade med en domän till webbappen varje begäran oavsett hur begäran till appen genererades i webbläsaren.

CSRF-attacker är dock inte begränsade till att utnyttja cookies. Till exempel är grundläggande och sammanfattad autentisering också sårbara. När en användare har loggat in med Basic- eller Digest-autentisering skickar webbläsaren automatiskt autentiseringsuppgifterna tills sessionen är slut.

I det här sammanhanget refererar session till den session på klientsidan som användaren autentiseras under. Det är inte relaterat till sessioner på serversidan eller ASP.NET Core sessionsmellanprogram.

Användare kan skydda mot CSRF-sårbarheter genom att vidta försiktighetsåtgärder:

  • Logga ut från webbappar när du är klar med att använda dem.
  • Rensa webbläsarcookies med jämna mellanrum.

CsRF-sårbarheter är dock i grunden ett problem med webbappen, inte slutanvändaren.

Grunderna för autentisering

Cookie-baserad autentisering är en populär form av autentisering. Tokenbaserade autentiseringssystem växer i popularitet, särskilt för ensidesprogram (SPA).

När en användare autentiserar med sitt användarnamn och lösenord utfärdas en token som innehåller en autentiseringsbiljett som kan användas för autentisering och auktorisering. Token lagras som en cookie som skickas med varje begäran som klienten gör. Generering och validering av detta cookie utförs av mellanprogrammet för cookie autentisering. mellanprogram serialiserar ett användarhuvudnamn till en krypterad cookie. Vid efterföljande begäranden validerar mellanprogrammet cookie, återskapar principalen och tilldelar principalen till egenskapen HttpContext.User.

Tokenbaserad autentisering

När en användare autentiseras utfärdas en token (inte en antiforgery-token). Tokenet innehåller användarinformation i form av anspråk eller en referenstoken som pekar appen mot användartillståndet som underhålls i appen. När en användare försöker komma åt en resurs som kräver autentisering skickas token till appen med ett extra auktoriseringshuvud i form av en Bearer token. Den här metoden gör appen tillståndslös. I varje efterföljande begäran skickas token i begäran om verifiering på serversidan. Den här token är inte krypterad; det är kodat. På servern avkodas token för att komma åt informationen. Om du vill skicka token på efterföljande begäranden lagrar du token i webbläsarens lokala lagring. Oroa dig inte för CSRF-sårbarhet om token lagras i webbläsarens lokala lagring. CSRF är ett problem när token lagras i en cookie. Mer information finns i GitHub-problemet SPA-kodexempel lägger till två cookies.

Flera appar som finns i en domän

Delade värdmiljöer är sårbara för sessionskapning, inloggnings-CSRF och andra attacker.

Även om example1.contoso.net och example2.contoso.net är olika värdar finns det en implicit förtroenderelation mellan värdar under den *.contoso.net domänen. Den här implicita förtroenderelationen gör att potentiellt ej betrodda värdar kan påverka varandras cookies (principerna för samma ursprung som styr AJAX-begäranden gäller inte nödvändigtvis för HTTP-cookies).

Attacker som utnyttjar betrodda cookies mellan appar som finns på samma domän kan förhindras genom att inte dela domäner. När varje app finns på sin egen domän finns det ingen implicit cookie förtroenderelation att utnyttja.

Antiförfalskning i ASP.NET Core

Varning

ASP.NET Core använder ASP.NET Core Data Protectionför att implementera skydd mot förfalskning. Dataskyddsstacken måste konfigureras för att fungera i en servergrupp. Mer information finns i Konfigurera dataskydd.

Antiforgery-mellanprogram läggs till i containern Dependency injection när något av följande API:er anropas i Program.cs:

FormTagHelper infogar antiforgery-token i HTML-formulärelement. Följande kod i en Razor-fil genererar automatiskt antiforgery-token:

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

På samma sätt genererar IHtmlHelper.BeginForm antiforgerytoken som standard om formulärets metod inte är GET.

Den automatiska genereringen av antiforgery-token för HTML-formulärelement sker när taggen <form> innehåller attributet method="post" och något av följande är sant:

  • Åtgärdsattributet är tomt (action="").
  • Åtgärdsattributet anges inte (<form method="post">).

Automatisk generering av antiforgery-token för HTML-formulärelement kan inaktiveras:

  • Avaktivera antifalsifieringstoken uttryckligen med attributet asp-antiforgery:

    <form method="post" asp-antiforgery="false">
        <!-- ... -->
    </form>
    
  • Formulärelementet väljs bort från Tag Helpers genom att använda Tag Helper ! opt-out-symbolen:

    <!form method="post">
        <!-- ... -->
    </!form>
    
  • Ta bort FormTagHelper från vyn. Du kan ta bort FormTagHelper från en vy genom att lägga till följande direktiv i vyn Razor:

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

Obs

Razor Pages skyddas automatiskt från XSRF/CSRF. Mer information finns i XSRF/CSRF och Razor Pages.

Den vanligaste metoden för att försvara sig mot CSRF-attacker är att använda Synkroniserartokens mönster (STP). STP används när användaren begär en sida med formulärdata:

  1. Servern skickar en token som är associerad med den aktuella användarens identitet till klienten.
  2. Klienten skickar tillbaka token till servern för verifiering.
  3. Om servern tar emot en token som inte matchar den autentiserade användarens identitet avvisas begäran.

Token är unik och oförutsägbar. Token kan också användas för att säkerställa korrekt sekvensering av en serie begäranden (till exempel genom att säkerställa begärandesekvensen på sidan 1 > sida 2 > sida 3). Alla formulär i ASP.NET Core MVC- och Razor Pages-mallar genererar antiforgery-token. Följande par av vyexempel genererar anti-förfalskningstecken:

<form asp-action="Index" asp-controller="Home" method="post">
    <!-- ... -->
</form>

@using (Html.BeginForm("Index", "Home"))
{
    <!-- ... -->
}

Lägg till en antiforgery-token uttryckligen i ett <form>-element utan att använda Tag Helpers med HTML-hjälparen @Html.AntiForgeryToken:

<form asp-action="Index" asp-controller="Home" method="post">
    @Html.AntiForgeryToken()

    <!-- ... -->
</form>

I vart och ett av de föregående fallen lägger ASP.NET Core till ett dolt formulärfält som liknar följande exempel:

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

ASP.NET Core innehåller tre filter för arbete med antiförfalsknings-token:

Antiförfalskning med AddControllers

Att anropa AddControllers gör inte att antiförfalskningsmarkörer aktiveras. AddControllersWithViews måste anropas för att ha inbyggt stöd för antiförfalskningstoken.

Flera webbläsarflikar och mönstret för synkroniseringstoken

Med Synkroniserare token-mönstret innehåller endast den senast inlästa sidan en giltig antiförfalskningstoken. Det kan vara problematiskt att använda flera flikar. Om en användare till exempel öppnar flera flikar:

  • Endast den senast inlästa fliken innehåller en giltig skyddstoken.
  • Begäranden från tidigare inlästa flikar misslyckas med ett fel: Antiforgery token validation failed. The antiforgery cookie token and request token do not match

Överväg alternativa CSRF-skyddsmönster om detta utgör ett problem.

Konfigurera förfalskningsskydd med AntiforgeryOptions

Anpassa AntiforgeryOptions i appens Program fil:

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

Ange egenskaper för förfalskningsskydd cookie med hjälp av egenskaperna för klassen CookieBuilder, som du ser i följande tabell.

Alternativ Beskrivning
Cookie Avgör vilka inställningar som används för att skapa antiforgery-cookies.
FormFieldName Namnet på det gömda formulärfältet som används av antiforgery-systemet för att generera antiforgery-tokens i vyer.
HeaderName Namnet på rubriken som används av antiforgerysystemet. Om nulltar systemet endast hänsyn till formulärdata.
SuppressXFrameOptionsHeader Anger om du vill utelämna genereringen av X-Frame-Options-huvudet. Som standard genereras rubriken med värdet "SAMEORIGIN". Ställs in som standard till false.

Vissa webbläsare tillåter inte osäkra slutpunkter att ange cookies med en "säker" flagga eller skriva över cookies vars "säkra" flagga har angetts (mer information finns i Inaktuell ändring av "säkra" cookies från icke-säkra ursprung). Eftersom blandningen av säkra och osäkra slutpunkter är ett vanligt scenario i appar, minskar ASP.NET Core restriktionen på den säkra policyn för vissa cookies, som till exempel antiforgery cookie, genom att ställa in cookies SecurePolicy till CookieSecurePolicy.None. Även om en obehörig användare stjäl en antiforgery cookie, måste de också stjäla den antiforgery-token som vanligtvis skickas via ett formulärfält (oftare) eller en separat begäran-rubrik (mer sällan) plus autentiseringen cookie. Cookies relaterade till autentisering eller auktorisering använder en starkare princip än CookieSecurePolicy.None.

Du kan också skydda antiforgery cookie i icke-Development miljöer med hjälp av en säker anslutning med SSL, endast över HTTPS, genom att använda följande AntiforgeryOptions.Cookie egenskapsinställning i appens Program-fil:

if (!builder.Environment.IsDevelopment())
{
    builder.Services.AddAntiforgery(o =>
    {
        o.Cookie.SecurePolicy = CookieSecurePolicy.Always;
    });
}

Mer information finns i CookieAuthenticationOptions.

Generera tokens för skydd mot förfalskning med IAntiforgery

IAntiforgery tillhandahåller API:et för att konfigurera funktioner för skydd mot förfalskning. IAntiforgery kan begäras i Program.cs med hjälp av WebApplication.Services. I följande exempel används mellanprogram från appens startsida för att generera en skyddstoken mot förfalskning och skicka den i svaret som en cookie:

app.UseRouting();

app.UseAuthorization();

var antiforgery = app.Services.GetRequiredService<IAntiforgery>();

app.Use((context, next) =>
{
    var requestPath = context.Request.Path.Value;

    if (string.Equals(requestPath, "/", StringComparison.OrdinalIgnoreCase)
        || string.Equals(requestPath, "/index.html", StringComparison.OrdinalIgnoreCase))
    {
        var tokenSet = antiforgery.GetAndStoreTokens(context);
        context.Response.Cookies.Append("XSRF-TOKEN", tokenSet.RequestToken!,
            new CookieOptions { HttpOnly = false });
    }

    return next(context);
});

I föregående exempel anges en cookie med namnet XSRF-TOKEN. Klienten kan läsa den här cookie och ange dess värde som en rubrik som är kopplad till AJAX-begäranden. Till exempel innehåller Angular inbyggt XSRF-skydd som läser en cookie med namnet XSRF-TOKEN som standard.

Kräv validering för att förhindra förfalskning

ValidateAntiForgeryToken åtgärdsfiltret kan tillämpas på en enskild åtgärd, en kontroller eller globalt. Begäranden som görs till åtgärder som har det här filtret tillämpade blockeras om inte begäran innehåller en giltig antiforgery-token:

[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Index()
{
    // ...

    return RedirectToAction();
}

Attributet ValidateAntiForgeryToken kräver en token för begäranden till de åtgärdsmetoder som markeras, inklusive HTTP GET-begäranden. Om attributet ValidateAntiForgeryToken tillämpas på appens kontrollanter kan det åsidosättas med attributet IgnoreAntiforgeryToken.

Verifiera antiforgeringstoken automatiskt endast för osäkra HTTP-metoder

Istället för att använda attributet ValidateAntiForgeryToken på ett omfattande sätt och sedan åsidosätta det med IgnoreAntiforgeryToken-attributet, kan attributet AutoValidateAntiforgeryToken användas. Det här attributet fungerar identiskt med attributet ValidateAntiForgeryToken, förutom att det inte kräver token för begäranden som görs med hjälp av följande HTTP-metoder:

  • GET
  • HUVUD
  • ALTERNATIV
  • SPÅRA

Vi rekommenderar att du använder AutoValidateAntiforgeryToken brett för scenarier som inte är API-scenarier. Det här attributet säkerställer att POST-åtgärder skyddas som standard. Alternativet är att ignorera antiforgery-token som standard, såvida inte ValidateAntiForgeryToken tillämpas på enskilda åtgärdsmetoder. I det här scenariot är det mer troligt att en POST-åtgärdsmetod lämnas oskyddad av misstag, vilket gör appen sårbar för CSRF-attacker. Alla POST:er bör skicka antiforgery-token.

API:er har ingen automatisk mekanism för att skicka den icke-cookie delen av token. Implementeringen beror förmodligen på klientkodimplementeringen. Några exempel visas nedan:

Exempel på klassnivå:

[AutoValidateAntiforgeryToken]
public class HomeController : Controller

Globalt exempel:

builder.Services.AddControllersWithViews(options =>
{
    options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute());
});

Åsidosätt globala eller kontroller-antiförfalskningsattribut

Filtret IgnoreAntiforgeryToken används för att eliminera behovet av en antiforgerytoken för en viss åtgärd (eller kontroller). När det här filtret används åsidosätter det ValidateAntiForgeryToken- och AutoValidateAntiforgeryToken-filter som anges på en högre nivå (globalt eller på en kontrollenhet).

[IgnoreAntiforgeryToken]
public IActionResult IndexOverride()
{
    // ...

    return RedirectToAction();
}

Uppdatera token efter autentisering

Token bör uppdateras efter att användaren har autentiserats genom att omdirigera användaren till en vy eller Razor Pages-sidan.

JavaScript, AJAX och SPA

I traditionella HTML-baserade appar skickas antiforgerytoken till servern med hjälp av dolda formulärfält. I moderna JavaScript-baserade appar och SPA:er görs många begäranden programmatiskt. Dessa AJAX-begäranden kan använda andra tekniker (till exempel begärandehuvuden eller cookies) för att skicka token.

Om cookies används för att lagra autentiseringstoken och autentisera API-begäranden på servern är CSRF ett potentiellt problem. Om lokal lagring används för att lagra token kan säkerhetsrisken för CSRF minskas eftersom värden från lokal lagring inte skickas automatiskt till servern med varje begäran. Användning av lokal lagring för att spara antiförfalskningstoken på klienten och skicka tokenen som en begäranderubrik är en rekommenderad metod.

JavaScript

När man använder JavaScript med vyer kan en token skapas med hjälp av en tjänst inifrån vyn. Mata in IAntiforgery-tjänsten i vyn och anropa GetAndStoreTokens:

@inject Microsoft.AspNetCore.Antiforgery.IAntiforgery Antiforgery

@{
    ViewData["Title"] = "JavaScript";

    var requestToken = Antiforgery.GetAndStoreTokens(Context).RequestToken;
}

<input id="RequestVerificationToken" type="hidden" value="@requestToken" />

<button id="button" class="btn btn-primary">Submit with Token</button>
<div id="result" class="mt-2"></div>

@section Scripts {
<script>
    document.addEventListener("DOMContentLoaded", () => {
        const resultElement = document.getElementById("result");

        document.getElementById("button").addEventListener("click", async () => {

            const response = await fetch("@Url.Action("FetchEndpoint")", {
                method: "POST",
                headers: {
                    RequestVerificationToken:
                        document.getElementById("RequestVerificationToken").value
                }
            });

            if (response.ok) {
                resultElement.innerText = await response.text();
            } else {
                resultElement.innerText = `Request Failed: ${response.status}`
            }
        });
    });
</script>
}

I föregående exempel används JavaScript för att läsa det dolda fältvärdet för AJAX POST-huvudet.

Den här metoden eliminerar behovet av att hantera att ange cookies direkt från servern eller läsa dem från klienten. Men när det inte går att injicera IAntiforgery-tjänsten kan JavaScript också komma åt en token i cookies, som hämtas från en ytterligare begäran till servern (vanligtvis same-origin), och använda innehållet i cookieför att skapa ett huvud med tokenvärdet.

Om skriptet skickar token i ett begärandehuvud med namnet X-XSRF-TOKENkonfigurerar du tjänsten för förfalskningsbekämpning för att leta efter X-XSRF-TOKEN-huvudet:

builder.Services.AddAntiforgery(options => options.HeaderName = "X-XSRF-TOKEN");

I följande exempel lägger du till en skyddad slutpunkt som kommer att skriva begärandetoken till en JavaScript-läsbar cookie:

app.UseAuthorization();
app.MapGet("antiforgery/token", (IAntiforgery forgeryService, HttpContext context) =>
{
    var tokens = forgeryService.GetAndStoreTokens(context);
    context.Response.Cookies.Append("XSRF-TOKEN", tokens.RequestToken!,
            new CookieOptions { HttpOnly = false });

    return Results.Ok();
}).RequireAuthorization();

I följande exempel används JavaScript för att göra en AJAX-begäran för att hämta token och göra en annan begäran med rätt rubrik:

var response = await fetch("/antiforgery/token", {
    method: "GET",
    headers: { "Authorization": authorizationToken }
});

if (response.ok) {
    // https://developer.mozilla.org/docs/web/api/document/cookie
    const xsrfToken = document.cookie
        .split("; ")
        .find(row => row.startsWith("XSRF-TOKEN="))
        .split("=")[1];

    response = await fetch("/JavaScript/FetchEndpoint", {
        method: "POST",
        headers: { "X-XSRF-TOKEN": xsrfToken, "Authorization": authorizationToken }
    });

    if (response.ok) {
        resultElement.innerText = await response.text();
    } else {
        resultElement.innerText = `Request Failed: ${response.status}`
    }
} else {    
    resultElement.innerText = `Request Failed: ${response.status}`
}

Windows-autentisering och förfalskningsskyddande cookies

När du använder Windows-autentisering måste programslutpunkter skyddas mot CSRF-attacker på samma sätt som för cookies. Webbläsaren skickar implicit autentiseringskontexten till servern och därför måste slutpunkter skyddas mot CSRF-attacker.

Utöka förfalskningsskydd

Med IAntiforgeryAdditionalDataProvider-typen kan utvecklare utöka beteendet för anti-CSRF-systemet genom att skicka ytterligare data fram och tillbaka med varje token. Metoden GetAdditionalData anropas varje gång en fälttoken genereras och returvärdet bäddas in i den genererade token. En implementer kan returnera en tidsstämpel, en nonce eller något annat värde och sedan anropa ValidateAdditionalData för att verifiera dessa data när token verifieras. Klientens användarnamn är redan inbäddat i de genererade token, så du behöver inte inkludera den här informationen. Om en token innehåller kompletterande data men ingen IAntiForgeryAdditionalDataProvider har konfigurerats verifieras inte tilläggsdata.

Ytterligare resurser

Förfalskning av begäranden mellan webbplatser (även kallat XSRF eller CSRF) är en attack mot webbaserade appar där en skadlig webbapp kan påverka interaktionen mellan en klientwebbläsare och en webbapp som litar på webbläsaren. Dessa attacker är möjliga eftersom webbläsare skickar vissa typer av autentiseringstoken automatiskt med varje begäran till en webbplats. Den här typen av exploatering kallas även för en attack med ett klick eller session som körs eftersom attacken utnyttjar användarens tidigare autentiserade session.

Ett exempel på en CSRF-attack:

  1. En användare loggar in på www.good-banking-site.example.com med formulärautentisering. Servern autentiserar användaren och utfärdar ett svar som innehåller en autentisering cookie. Webbplatsen är sårbar för angrepp eftersom den litar på alla förfrågningar som den tar emot med en giltig autentisering cookie.

  2. Användaren besöker en skadlig webbplats www.bad-crook-site.example.com.

    Den skadliga webbplatsen, www.bad-crook-site.example.com, innehåller ett HTML-formulär som liknar följande exempel:

    <h1>Congratulations! You're a Winner!</h1>
    <form action="https://www.good-banking-site.example.com/api/account" method="post">
        <input type="hidden" name="Transaction" value="withdraw" />
        <input type="hidden" name="Amount" value="1000000" />
        <input type="submit" value="Click to collect your prize!" />
    </form>
    

    Observera att formulärets action skickas till den sårbara webbplatsen, inte till den skadliga webbplatsen. Det här är "cross-site"-delen av CSRF.

  3. Användaren väljer knappen Skicka. Webbläsaren gör begäran och innehåller automatiskt autentiseringen cookie för den begärda domänen www.good-banking-site.example.com.

  4. Begäran körs på www.good-banking-site.example.com-servern med användarens autentiseringskontext och kan utföra alla åtgärder som en autentiserad användare tillåts utföra.

Förutom scenariot där användaren väljer knappen för att skicka formuläret kan den skadliga webbplatsen:

  • Kör ett skript som automatiskt skickar formuläret.
  • Skicka formuläret som en AJAX-begäran.
  • Dölj formuläret med hjälp av CSS.

Dessa alternativa scenarier kräver ingen åtgärd eller indata från användaren förutom att först besöka den skadliga webbplatsen.

Att använda HTTPS förhindrar inte en CSRF-attack. Den skadliga webbplatsen kan skicka https://www.good-banking-site.example.com/ en begäran lika enkelt som den kan skicka en osäker begäran.

Vissa attacker, anger mot slutpunkter som svarar på GET-begäranden, i så fall kan en img-tagg användas för att utföra åtgärden. Den här typen av angrepp är vanlig på forumwebbplatser som tillåter bilder men blockerar JavaScript. Appar som ändrar tillstånd för GET-begäranden, där variabler eller resurser ändras, är sårbara för skadliga attacker. GET-begäranden som ändrar tillstånd är osäkra. En bästa praxis är att aldrig ändra tillstånd för en GET-begäran.

CSRF-attacker är möjliga mot webbappar som använder cookies för autentisering eftersom:

  • Webbläsare lagrar cookies som utfärdats av en webbapp.
  • Lagrade cookies inkluderar sessionscookies för autentiserade användare.
  • Webbläsare skickar alla cookies som är associerade med en domän till webbappen varje begäran oavsett hur begäran till appen genererades i webbläsaren.

CSRF-attacker är dock inte begränsade till att utnyttja cookies. Till exempel är grundläggande och sammanfattad autentisering också sårbara. När en användare har loggat in med Basic- eller Digest-autentisering skickar webbläsaren automatiskt autentiseringsuppgifterna tills sessionen är slut.

I det här sammanhanget refererar session till den session på klientsidan som användaren autentiseras under. Det är inte relaterat till sessioner på serversidan eller ASP.NET Core sessionsmellanprogram.

Användare kan skydda mot CSRF-sårbarheter genom att vidta försiktighetsåtgärder:

  • Logga ut från webbappar när du är klar med att använda dem.
  • Rensa webbläsarcookies med jämna mellanrum.

CsRF-sårbarheter är dock i grunden ett problem med webbappen, inte slutanvändaren.

Grunderna för autentisering

Cookie-baserad autentisering är en populär form av autentisering. Tokenbaserade autentiseringssystem växer i popularitet, särskilt för ensidesprogram (SPA).

När en användare autentiserar med sitt användarnamn och lösenord utfärdas en token som innehåller en autentiseringsbiljett som kan användas för autentisering och auktorisering. Token lagras som en cookie som skickas med varje begäran som klienten gör. Generering och validering av detta cookie utförs av mellanprogrammet för cookie autentisering. mellanprogram serialiserar ett användarhuvudnamn till en krypterad cookie. Vid efterföljande begäranden validerar mellanprogrammet cookie, återskapar principalen och tilldelar principalen till egenskapen HttpContext.User.

Tokenbaserad autentisering

När en användare autentiseras utfärdas en token (inte en antiforgery-token). Tokenet innehåller användarinformation i form av anspråk eller en referenstoken som pekar appen mot användartillståndet som underhålls i appen. När en användare försöker komma åt en resurs som kräver autentisering skickas token till appen med ett extra auktoriseringshuvud i form av en Bearer token. Den här metoden gör appen tillståndslös. I varje efterföljande begäran skickas token i begäran om verifiering på serversidan. Den här token är inte krypterad; det är kodat. På servern avkodas token för att komma åt informationen. Om du vill skicka token på efterföljande begäranden lagrar du token i webbläsarens lokala lagring. Oroa dig inte för CSRF-sårbarhet om token lagras i webbläsarens lokala lagring. CSRF är ett problem när token lagras i en cookie. Mer information finns i GitHub-problemet SPA-kodexempel lägger till två cookies.

Flera appar som finns i en domän

Delade värdmiljöer är sårbara för sessionskapning, inloggnings-CSRF och andra attacker.

Även om example1.contoso.net och example2.contoso.net är olika värdar finns det en implicit förtroenderelation mellan värdar under den *.contoso.net domänen. Den här implicita förtroenderelationen gör att potentiellt ej betrodda värdar kan påverka varandras cookies (principerna för samma ursprung som styr AJAX-begäranden gäller inte nödvändigtvis för HTTP-cookies).

Attacker som utnyttjar betrodda cookies mellan appar som finns på samma domän kan förhindras genom att inte dela domäner. När varje app finns på sin egen domän finns det ingen implicit cookie förtroenderelation att utnyttja.

ASP.NET Core anti-förfalskningskonfiguration

Varning

ASP.NET Core använder ASP.NET Core Data Protectionför att implementera skydd mot förfalskning. Dataskyddsstacken måste konfigureras för att fungera i en servergrupp. Mer information finns i Konfigurera dataskydd.

Antiforgery-mellanprogram läggs till i containern Dependency injection när något av följande API:er anropas i Startup.ConfigureServices:

I ASP.NET Core 2.0 eller senare injicerar FormTagHelper antiforgery-tokenen i HTML-formulärelement. Följande kod i en Razor-fil genererar automatiskt antiforgery-token:

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

På samma sätt genererar IHtmlHelper.BeginForm antiforgerytoken som standard om formulärets metod inte är GET.

Den automatiska genereringen av antiforgery-token för HTML-formulärelement sker när taggen <form> innehåller attributet method="post" och något av följande är sant:

  • Åtgärdsattributet är tomt (action="").
  • Åtgärdsattributet anges inte (<form method="post">).

Automatisk generering av antiforgery-token för HTML-formulärelement kan inaktiveras:

  • Avaktivera antifalsifieringstoken uttryckligen med attributet asp-antiforgery:

    <form method="post" asp-antiforgery="false">
        ...
    </form>
    
  • Formulärelementet väljs bort från Tag Helpers genom att använda Tag Helper ! opt-out-symbolen:

    <!form method="post">
        ...
    </!form>
    
  • Ta bort FormTagHelper från vyn. Du kan ta bort FormTagHelper från en vy genom att lägga till följande direktiv i vyn Razor:

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

Obs

Razor Pages skyddas automatiskt från XSRF/CSRF. Mer information finns i XSRF/CSRF och Razor Pages.

Den vanligaste metoden för att försvara sig mot CSRF-attacker är att använda Synkroniserartokens mönster (STP). STP används när användaren begär en sida med formulärdata:

  1. Servern skickar en token som är associerad med den aktuella användarens identitet till klienten.
  2. Klienten skickar tillbaka token till servern för verifiering.
  3. Om servern tar emot en token som inte matchar den autentiserade användarens identitet avvisas begäran.

Token är unik och oförutsägbar. Token kan också användas för att säkerställa korrekt sekvensering av en serie begäranden (till exempel genom att säkerställa begärandesekvensen på sidan 1 > sida 2 > sida 3). Alla formulär i ASP.NET Core MVC- och Razor Pages-mallar genererar antiforgery-token. Följande par av vyexempel genererar anti-förfalskningstecken:

<form asp-controller="Todo" asp-action="Create" method="post">
    ...
</form>

@using (Html.BeginForm("Create", "Todo"))
{
    ...
}

Lägg till en antiforgery-token uttryckligen i ett <form>-element utan att använda Tag Helpers med HTML-hjälparen @Html.AntiForgeryToken:

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

I vart och ett av de föregående fallen lägger ASP.NET Core till ett dolt formulärfält som liknar följande exempel:

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

ASP.NET Core innehåller tre filter för arbete med antiförfalsknings-token:

Alternativ för antiförfalskning

Anpassa AntiforgeryOptions i Startup.ConfigureServices:

services.AddAntiforgery(options => 
{
    options.FormFieldName = "AntiforgeryFieldname";
    options.HeaderName = "X-CSRF-TOKEN-HEADERNAME";
    options.SuppressXFrameOptionsHeader = false;
});

Ange egenskaper för förfalskningsskydd cookie med hjälp av egenskaperna för klassen CookieBuilder, som du ser i följande tabell.

Alternativ Beskrivning
Cookie Avgör vilka inställningar som används för att skapa antiforgery-cookies.
FormFieldName Namnet på det gömda formulärfältet som används av antiforgery-systemet för att generera antiforgery-tokens i vyer.
HeaderName Namnet på rubriken som används av antiforgerysystemet. Om nulltar systemet endast hänsyn till formulärdata.
SuppressXFrameOptionsHeader Anger om du vill utelämna genereringen av X-Frame-Options-huvudet. Som standard genereras rubriken med värdet "SAMEORIGIN". Ställs in som standard till false.

Vissa webbläsare tillåter inte osäkra slutpunkter att ange cookies med en "säker" flagga eller skriva över cookies vars "säkra" flagga har angetts (mer information finns i Inaktuell ändring av "säkra" cookies från icke-säkra ursprung). Eftersom blandningen av säkra och osäkra slutpunkter är ett vanligt scenario i appar, minskar ASP.NET Core restriktionen på den säkra policyn för vissa cookies, som till exempel antiforgery cookie, genom att ställa in cookies SecurePolicy till CookieSecurePolicy.None. Även om en obehörig användare stjäl en antiforgery cookie, måste de också stjäla den antiforgery-token som vanligtvis skickas via ett formulärfält (oftare) eller en separat begäran-rubrik (mer sällan) plus autentiseringen cookie. Cookies relaterade till autentisering eller auktorisering använder en starkare princip än CookieSecurePolicy.None.

Du kan också skydda antiförfalskning cookie i andra än Development miljöer med Secure Sockets Layer (SSL), enbart över HTTPS, genom att använda följande AntiforgeryOptions.Cookie-egenskapsinställning i appens Startup-klass:

public class Startup
{
    public Startup(IConfiguration configuration, IHostEnvironment environment)
    {
        Configuration = configuration;
        Environment = environment;
    }

    public IConfiguration Configuration { get; }
    public IHostEnvironment Environment { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        // Other services are registered here

        if (!Environment.IsDevelopment())
        {
            services.AddAntiforgery(o =>
            {
                o.Cookie.SecurePolicy = CookieSecurePolicy.Always;
            });
        }
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        // Request processing pipeline
    }
}

Mer information finns i CookieAuthenticationOptions.

Konfigurera förfalskningsskydd med IAntiforgery

IAntiforgery tillhandahåller API:et för att konfigurera funktioner för skydd mot förfalskning. IAntiforgery kan begäras i Configure-metoden för klassen Startup.

I följande exempel:

  • Mellanvara från appens startsida används för att generera en antiforgery-token och skicka den i svaret som en cookie.
  • Begärandetoken skickas som en JavaScript-läsbar cookie med standardkonventionen för Angular-namngivning som beskrivs i avsnittet AngularJS.
public void Configure(IApplicationBuilder app, IAntiforgery antiforgery)
{
    app.Use(next => context =>
    {
        string path = context.Request.Path.Value;

        if (string.Equals(path, "/", StringComparison.OrdinalIgnoreCase) ||
            string.Equals(path, "/index.html", StringComparison.OrdinalIgnoreCase))
        {
            var tokens = antiforgery.GetAndStoreTokens(context);
            context.Response.Cookies.Append("XSRF-TOKEN", tokens.RequestToken, 
                new CookieOptions() { HttpOnly = false });
        }

        return next(context);
    });
}

Kräv validering för att förhindra förfalskning

ValidateAntiForgeryToken är ett åtgärdsfilter som kan tillämpas på en enskild åtgärd, en kontrollant eller globalt. Begäranden som görs till åtgärder som har detta filter tillämpat blockeras, såvida begäran inte innehåller en giltig antiförfalskningstoken.

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

Attributet ValidateAntiForgeryToken kräver en token för begäranden till de åtgärdsmetoder som markeras, inklusive HTTP GET-begäranden. Om attributet ValidateAntiForgeryToken tillämpas på appens kontrollanter kan det åsidosättas med attributet IgnoreAntiforgeryToken.

Obs

ASP.NET Core stöder inte automatisk tillägg av antiforgery-token i GET-begäranden.

Verifiera antiforgeringstoken automatiskt endast för osäkra HTTP-metoder

ASP.NET Core-appar genererar inte antiforgerytoken för säkra HTTP-metoder (GET, HEAD, OPTIONS och TRACE). Istället för att använda attributet ValidateAntiForgeryToken på ett omfattande sätt och sedan åsidosätta det med IgnoreAntiforgeryToken-attributet, kan attributet AutoValidateAntiforgeryToken användas. Det här attributet fungerar identiskt med attributet ValidateAntiForgeryToken, förutom att det inte kräver token för begäranden som görs med hjälp av följande HTTP-metoder:

  • GET
  • HUVUD
  • ALTERNATIV
  • SPÅRA

Vi rekommenderar att du använder AutoValidateAntiforgeryToken brett för scenarier som inte är API-scenarier. Det här attributet säkerställer att POST-åtgärder skyddas som standard. Alternativet är att ignorera antiforgery-token som standard, såvida inte ValidateAntiForgeryToken tillämpas på enskilda åtgärdsmetoder. I det här scenariot är det mer troligt att en POST-åtgärdsmetod lämnas oskyddad av misstag, vilket gör appen sårbar för CSRF-attacker. Alla POST:er bör skicka antiforgery-token.

API:er har ingen automatisk mekanism för att skicka den icke-cookie delen av token. Implementeringen beror förmodligen på klientkodimplementeringen. Några exempel visas nedan:

Exempel på klassnivå:

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

Globalt exempel:

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

Åsidosätt globala eller kontroller-antiförfalskningsattribut

Filtret IgnoreAntiforgeryToken används för att eliminera behovet av en antiforgerytoken för en viss åtgärd (eller kontroller). När det här filtret används åsidosätter det ValidateAntiForgeryToken- och AutoValidateAntiforgeryToken-filter som anges på en högre nivå (globalt eller på en kontrollenhet).

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

Uppdatera token efter autentisering

Token bör uppdateras efter att användaren har autentiserats genom att omdirigera användaren till en vy eller Razor Pages-sidan.

JavaScript, AJAX och SPA

I traditionella HTML-baserade appar skickas antiforgerytoken till servern med hjälp av dolda formulärfält. I moderna JavaScript-baserade appar och SPA:er görs många begäranden programmatiskt. Dessa AJAX-begäranden kan använda andra tekniker (till exempel begärandehuvuden eller cookies) för att skicka token.

Om cookies används för att lagra autentiseringstoken och autentisera API-begäranden på servern är CSRF ett potentiellt problem. Om lokal lagring används för att lagra token kan säkerhetsrisken för CSRF minskas eftersom värden från lokal lagring inte skickas automatiskt till servern med varje begäran. Användning av lokal lagring för att spara antiförfalskningstoken på klienten och skicka tokenen som en begäranderubrik är en rekommenderad metod.

JavaScript

När man använder JavaScript med vyer kan en token skapas med hjälp av en tjänst inifrån vyn. Mata in IAntiforgery-tjänsten i vyn och anropa 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>

Den här metoden eliminerar behovet av att hantera att ange cookies direkt från servern eller läsa dem från klienten.

I föregående exempel används JavaScript för att läsa det dolda fältvärdet för AJAX POST-huvudet.

JavaScript kan också komma åt token i cookies och använda innehållet i cookieför att skapa en rubrik med tokens värde.

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

Om du antar att skriptbegärandena om att skicka token i ett huvud med namnet X-CSRF-TOKEN, konfigurerar du tjänsten för förfalskningsbekämpning för att leta efter X-CSRF-TOKEN-huvudet:

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

I följande exempel används JavaScript för att göra en AJAX-begäran med rätt rubrik:

function getCookie(cname) {
    var name = cname + "=";
    var decodedCookie = decodeURIComponent(document.cookie);
    var ca = decodedCookie.split(';');
    for (var i = 0; i < ca.length; i++) {
        var c = ca[i];
        while (c.charAt(0) === ' ') {
            c = c.substring(1);
        }
        if (c.indexOf(name) === 0) {
            return c.substring(name.length, c.length);
        }
    }
    return "";
}

var csrfToken = getCookie("CSRF-TOKEN");

var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function () {
    if (xhttp.readyState === XMLHttpRequest.DONE) {
        if (xhttp.status === 204) {
            alert('Todo item is created successfully.');
        } else {
            alert('There was an error processing the AJAX request.');
        }
    }
};
xhttp.open('POST', '/api/items', true);
xhttp.setRequestHeader("Content-type", "application/json");
xhttp.setRequestHeader("X-CSRF-TOKEN", csrfToken);
xhttp.send(JSON.stringify({ "name": "Learn C#" }));

AngularJS

AngularJS använder en konvention för att hantera CSRF. Om servern skickar en cookie med namnet XSRF-TOKENlägger tjänsten AngularJS $http till värdet cookie i ett huvud när en begäran skickas till servern. Den här processen är automatisk. Klienten behöver inte explicit ange rubriken. Rubriknamnet är X-XSRF-TOKEN. Servern bör identifiera det här huvud och verifiera innehållet.

För att ASP.NET Core-API:et ska fungera med den här konventionen i programstarten:

  • Konfigurera appen så att den anger en token i en cookie som heter XSRF-TOKEN.
  • Konfigurera antiforgery-tjänsten så att den söker efter en rubrik med namnet X-XSRF-TOKEN, som är Angulars standardhuvudnamn för att skicka 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))
        {
            var tokens = antiforgery.GetAndStoreTokens(context);
            context.Response.Cookies.Append("XSRF-TOKEN", tokens.RequestToken, 
                new CookieOptions() { HttpOnly = false });
        }

        return next(context);
    });
}

public void ConfigureServices(IServiceCollection services)
{
    services.AddAntiforgery(options => options.HeaderName = "X-XSRF-TOKEN");
}

Obs

När anti-förfalsknings-token anges i både begärandehuvudet och i formulärets nyttolast verifieras endast tokenen i begärandehuvudet.

Windows-autentisering och förfalskningsskyddande cookies

När du använder Windows-autentisering måste programslutpunkter skyddas mot CSRF-attacker på samma sätt som för cookies. Webbläsaren skickar implicit autentiseringskontexten till servern och därför måste slutpunkter skyddas mot CSRF-attacker.

Utöka förfalskningsskydd

Med IAntiforgeryAdditionalDataProvider-typen kan utvecklare utöka beteendet för anti-CSRF-systemet genom att skicka ytterligare data fram och tillbaka med varje token. Metoden GetAdditionalData anropas varje gång en fälttoken genereras och returvärdet bäddas in i den genererade token. En implementer kan returnera en tidsstämpel, en nonce eller något annat värde och sedan anropa ValidateAdditionalData för att verifiera dessa data när token verifieras. Klientens användarnamn är redan inbäddat i de genererade token, så du behöver inte inkludera den här informationen. Om en token innehåller kompletterande data men ingen IAntiForgeryAdditionalDataProvider har konfigurerats verifieras inte tilläggsdata.

Ytterligare resurser