Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Autoři: Fiyaz Hasan a Rick Anderson
Zranitelnost zvaná cross-site request forgery (CSRF) je útok na webové aplikace, kdy škodlivá webová aplikace může ovlivnit interakci mezi klientským prohlížečem a webovou aplikací, která důvěřuje tomuto prohlížeči. Tyto útoky jsou možné, protože webové prohlížeče automaticky odesílají některé typy ověřovacích tokenů s každou žádostí na web. Tato forma zneužití se také označuje jako jednoklikový útok nebo únos relace, protože útok využívá dříve ověřenou relaci uživatele. Padělání požadavků mezi weby se také označuje jako XSRF nebo CSRF.
Příklad útoku CSRF:
Uživatel se přihlásí k
www.good-banking-site.example.compomocí ověření formulářem. Server ověřuje uživatele a vydává odpověď, která zahrnuje ověřování cookie. Web je zranitelný vůči útoku, protože důvěřuje všem požadavkem, který obdrží s platným ověřováním cookie.Uživatel navštíví škodlivý web.
www.bad-crook-site.example.comŠkodlivý web obsahuje
www.bad-crook-site.example.comformulář HTML podobný následujícímu příkladu:<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>Všimněte si, že formulář
actionodesílá na ohrožený web, nikoli na škodlivý web. Toto je "cross-site" část CSRF.Uživatel vybere tlačítko Odeslat. Prohlížeč vytvoří požadavek a automaticky zahrne ověřování cookie pro požadovanou doménu.
www.good-banking-site.example.comPožadavek se spustí na
www.good-banking-site.example.comserveru s kontextem ověřování uživatele a může provést jakoukoli akci, kterou může ověřený uživatel provést.
Kromě scénáře, ve kterém uživatel vybere tlačítko pro odeslání formuláře, může škodlivý web:
- Spusťte skript, který automaticky odešle formulář.
- Odešlete formulář jako požadavek AJAX.
- Skryjte formulář pomocí šablon stylů CSS.
Tyto alternativní scénáře nevyžadují žádnou akci ani vstup od jiného uživatele, než je počáteční návštěva škodlivého webu.
Použití PROTOKOLU HTTPS nezabrání útoku CSRF. Škodlivý web může odeslat https://www.good-banking-site.example.com/ požadavek stejně snadno, jako by mohl odeslat nezabezpečený požadavek.
Některé útoky cílí na koncové body, které reagují na požadavky GET, v takovém případě lze použít značku image k provedení akce. Tato forma útoku je běžná na webech fóra, které umožňují obrázky, ale blokují JavaScript. Aplikace, které mění stav požadavků GET, kde se mění proměnné nebo prostředky, jsou zranitelné vůči škodlivým útokům. Požadavky GET, které změní stav, jsou nezabezpečené. Osvědčeným postupem je nikdy změnit stav požadavku GET.
Útoky CSRF jsou možné vůči webovým aplikacím, které k ověřování používají soubory cookie, protože:
- Prohlížeče ukládají soubory cookie vydané webovou aplikací.
- Uložené soubory cookie obsahují soubory cookie relace pro ověřené uživatele.
- Prohlížeče odesílají všechny soubory cookie přidružené k doméně do webové aplikace bez ohledu na to, jak se požadavek na aplikaci vygeneroval v prohlížeči.
Útoky CSRF ale nejsou omezené na zneužití souborů cookie. Například základní ověřování a ověřování pomocí digest je také ohroženo. Jakmile se uživatel přihlásí pomocí ověřování Basic nebo Digest, prohlížeč automaticky odešle přihlašovací údaje, dokud relace neskončí.
V tomto kontextu relace odkazuje na relaci na straně klienta, ve které je uživatel ověřen. Nesouvisí to se serverovými relacemi ani s middlewarem relací ASP.NET Core.
Uživatelé mohou chránit před ohroženími zabezpečení CSRF pomocí bezpečnostních opatření:
- Po dokončení se odhlaste z webových aplikací.
- Pravidelně vymažte soubory cookie prohlížeče.
Ohrožení zabezpečení CSRF jsou ale v zásadě problém s webovou aplikací, nikoli koncovým uživatelem.
Základy ověřování
Cookie-založené ověřování je oblíbenou formou ověřování. Systémy ověřování založené na tokenech jsou stále oblíbenější, zejména pro jednostráňové aplikace (SPA).
Cookie-založené ověřování
Když se uživatel přihlásí pomocí uživatelského jména a hesla, je mu vydán token obsahující ověřovací autorizační lístek. Token lze použít k ověřování a autorizaci. Token se uloží jako cookie odesílaný s každým požadavkem, který klient provede. Generování a ověřování tohoto cookie se provádí pomocí middlewaru ověřování cookie. Middleware serializuje uživatelský principál do zašifrovaného cookie. V následných požadavcích middleware ověří cookie, znovu vytvoří hlavní objekt a přiřadí tento hlavní objekt k vlastnosti HttpContext.User.
Ověřování na základě tokenů
Když je uživatel ověřen, obdrží token, nikoli antiforgery token. Token obsahuje informace o uživateli ve formě deklarací identity nebo referenčního tokenu, který odkazuje aplikaci na stav uživatele udržovaný v aplikaci. Když se uživatel pokusí získat přístup k prostředku, který vyžaduje ověření, token se odešle do aplikace s extra autorizační hlavičkou ve formě tokenu Bearer . Díky tomuto přístupu je aplikace bezstavová. V každém dalším požadavku se token předá v požadavku na ověření na straně serveru. Tento token není šifrovaný, je zakódovaný. Na serveru je token dekódován pro přístup k jeho informacím. Pokud chcete token odeslat při dalších požadavcích, uložte ho do místního úložiště prohlížeče. Umístění tokenu do místního úložiště prohlížeče a jeho načtení a jeho použití jako nosný token poskytuje ochranu před útoky CSRF. Pokud je však aplikace zranitelná vůči injektáži skriptu prostřednictvím XSS nebo ohroženého externího javascriptového souboru, může kyberattacker načíst libovolnou hodnotu z místního úložiště a odeslat ji sama sobě. ASP.NET Core ve výchozím nastavení kóduje veškerý výstup na straně serveru z proměnných a snižuje riziko XSS. Pokud toto chování přepíšete pomocí Html.Raw nebo vlastního kódu s nedůvěryhodným vstupem, můžete zvýšit riziko XSS.
Nedělejte si starosti s ohrožením zabezpečení CSRF, pokud je token uložený v místním úložišti prohlížeče. CSRF je riziko, když je token uložen v cookie. Další informace najdete v problému GitHubu SPA code sample adds two cookies.
Více aplikací hostovaných v jedné doméně
Sdílené hostitelské prostředí jsou zranitelná vůči únosu relace, CSRF útokům při přihlášení a dalším útokům.
I když example1.contoso.net a example2.contoso.net jsou různí hostitelé, existuje implicitní vztah důvěryhodnosti mezi hostiteli v rámci *.contoso.net domény. Tento implicitní vztah důvěryhodnosti umožňuje potenciálně nedůvěryhodným hostitelům ovlivnit soubory cookie ostatních (zásady stejného původu, které řídí požadavky AJAX, se nemusí nutně vztahovat na soubory cookie HTTP).
Útoky, které zneužívají důvěryhodné soubory cookie mezi aplikacemi hostovanými ve stejné doméně, je možné zabránit tím, že nesdílí domény. Když je každá aplikace hostovaná ve vlastní doméně, neexistuje žádný implicitní cookie vztah důvěryhodnosti, který by bylo potřeba zneužít.
Načtení hlaviček metadat
Moderní prohlížeče připojují ke každému požadavku hlavičky požadavku Fetch Metadata — především Sec-Fetch-Site.
Sec-Fetch-Sitepopisuje vztah mezi původem, který inicioval požadavek, a požadovaným původem: same-origin identifikuje požadavek, který web provedl sám, a same-site zároveň cross-site identifikuje požadavky iniciované jiným původem. Hlavička Origin obsahuje původ iniciátora a slouží jako záložní řešení pro prohlížeče, které předcházejí technologii Fetch Metadata.
Sec-Fetch-Site a Originjsou zakázané hlavičky požadavků: prohlížeč je nastaví a JavaScript spuštěný na stránce je nemůže přepsat ani zprovoznit. Díky tomu představují spolehlivý signál pro rozlišení vlastních požadavků webu od požadavků z jiných webů bez tokenu vydaného serverem.
Automatická ochrana CSRF integrovaná v ASP.NET Core používá tento signál k odmítání odeslání formulářů z jiných webů, která nejsou výslovně považována za důvěryhodná.
Automatická ochrana CSRF v ASP.NET Core
ASP.NET Core dodává automatický middleware ochrany CSRF, který je ve výchozím nastavení povolený v aplikacích vytvořených pomocí WebApplication.CreateBuilder. Na rozdíl od antiforgery systému založeného na tokenech tento middleware nesdílí ani neověřuje tokeny. Místo toho zkontroluje Sec-Fetch-Site a Originhlavičky metadat Fetch a zaznamená výsledek ověření požadavku. Komponenty, které zpracovávají odeslaná data formuláře, toto rozhodnutí vynucují a odmítají odeslání formulářů z jiného původu, která nejsou výslovně považována za důvěryhodná.
U většiny aplikací se nevyžadují žádné změny kódu: požadavky na prohlížeč stejného původu, bezpečné metody HTTP a klienti bez prohlížeče (curl, server-server, mobilní aplikace) projdou bez ovlivnění. Middleware primárně ovlivňuje aplikace, které z prohlížeče přijímají odeslání formulářů mezi zdroji, například web, který odešle formulář do rozhraní API na jiném zdroji. Tyto scénáře musí buď nakonfigurovat CORS tak, aby deklarovali důvěryhodný původ, nebo odhlásit koncový bod.
Tento middleware se přičítá do antiforgery systému založeného na tokenech. Obě ochrany existují společně a oba můžou být aktivní ve stejném koncovém bodu. Porovnání toho, kdy se každý z nich použije, najdete v tématu Interakce s antiforgery založeným na tokenu.
Jak to funguje
U každého požadavku middleware vyhodnocuje krátký řetězec pravidel pro dosažení verdiktu – povolené nebo odepřené. Kontroly se provádějí v pořadí a první shoda vyhraje:
-
Bezpečné metody HTTP jsou vždy povoleny.
GET,HEAD,OPTIONSaTRACEpožadavky procházejí. To se řídí dokumentem RFC 9110 §9.2.1 a je konzistentní s dlouhodobým pravidlem, že koncové body by neměly měnit stavGET. -
Sec-Fetch-Site: same-originneboSec-Fetch-Site: noneje povolen. Moderní prohlížeče odesílajíSec-Fetch-Sites každým požadavkem.same-originzahrnuje normální navigaci v aplikaci a načítání anonepokrývá požadavky iniciované přímo uživatelem (zadáním adresy URL pomocí záložky). Toto je nejběžnější větev kódu – tudy prochází většina legitimního provozu prohlížeče. - Důvěryhodný původ z CORS je povolený. Pokud požadavek obsahuje hlavičku
Origina zásada CORS vyhodnocená pro daný koncový bod považuje tento původ za důvěryhodný, je požadavek povolen. Middleware určuje zásadu stejným způsobem jako middleware CORS: nejprve zásadu pro konkrétní koncový bod z[EnableCors("name")]a poté výchozí zásadu zaregistrovanou pomocíAddDefaultPolicy. Viz Povolení klientů z různých zdrojů, kde najdete důležitá omezení tohoto pravidla. - Jakákoli jiná
Sec-Fetch-Sitehodnota je odepřena. Pokud jeSec-Fetch-Sitecross-sitenebosame-sitea původ není prostřednictvím CORS důvěryhodný, požadavek je zamítnut. -
Žádné
Sec-Fetch-Site, aleOriginje přítomno: middleware porovnáváOriginsscheme://host[:port]vytvořeným z požadavku. Pokud se shodují, žádost je povolena; v opačném případě je zamítnuta. Toto je záložní cesta pro prohlížeče starší než specifikace Fetch Metadata (vydaná ~2020). - Ne
Sec-Fetch-Sitea neOrigin: Požadavek je povolený. Prohlížeče při požadavku na zápis vždy odesílají alespoň jednu z těchto hodnot, takže požadavek, v němž chybí obojí, je téměř jistě od neprohlížečového klienta, napříkladcurl, Postmanu, mobilní aplikace nebo z volání mezi servery. CSRF je vektor útoku omezený pouze na prohlížeč, proto tyto požadavky projdou.
Middleware toto rozhodnutí zaznamená u požadavku, místo aby požadavek samo ukončilo. Informace o tom, jak a kdy se zamítnutý verdikt změní na odpověď HTTP 400 Bad Request , najdete v tématu Odložené ověření.
Odložené ověření
Middleware sám neodmítá požadavek. Místo toho zaznamená svůj verdikt do atributu požadavku IAntiforgeryValidationFeature – stejného atributu, který používá systém ochrany proti padělání požadavků založený na tokenech – přičemž zamítavý verdikt se zaznamená jako invalid. Požadavek pokračuje dále v procesu. Neplatný výsledek se stane odpovědí HTTP 400 Bad Request pouze tehdy, když jej zaznamená komponenta, která zpracovává data formuláře. Toto odložení odpovídá chování systému založeného na tokenech: verdikt se vytváří v rané fázi, ale vynucuje se v okamžiku, kdy je formulář spotřebován.
Následující komponenty načítají IAntiforgeryValidationFeature a odmítnou požadavek s chybou 400 - Bad Request, pokud je zaznamenaný verdikt neplatný:
- Akce MVC chráněné ochranou proti padělání požadavků
- Minimální koncové body rozhraní API, které sváže parametr formuláře.
- Blazor Koncové body SSR.
- Jakýkoli kód, který přímo čte formulář požadavku, slouží jako pojistka.
Každá komponenta nejprve ověří, že se předtím skutečně spustil middleware antiforgery nebo CSRF, a teprve potom verdiktu důvěřuje, takže pipeline bez kteréhokoli z těchto middleware nevytváří falešná odmítnutí.
Důsledkem tohoto modelu je to, že koncový bod, který nikdy nečte data formuláře, se spustí i v případě, že je verdikt neplatný. Například koncový bod rozhraní JSON API, který získává tělo požadavku z JSON, nebo obslužná rutina, která ignoruje tělo požadavku, není při požadavku mezi zdroji automaticky odmítnut. Výsledek se stále zapisuje do IAntiforgeryValidationFeature, aby ho mohl zkontrolovat kód, který to potřebuje, ale nic to nevynucuje. CSRF je vektor útoku typu form-and-cookie, takže koncové body, které nezpracovávají formulář odeslaný prohlížečem, takové odmítnutí obvykle nepotřebují. Koncové body, které zpracovávají formuláře — Razor Pages, zobrazení MVC, Blazor SSR a vazba formulářů v Minimal API — získávají ochranu automaticky.
Výchozí chování
Middleware je automaticky registrován pomocí WebApplication.CreateBuilder a spouští se po autentizaci a autorizaci. Ověřuje každou žádost pomocí registrované ICsrfProtection implementace, která ve výchozím nastavení používá pravidla popsaná v části Jak funguje. Výchozí implementace může být nahrazena; Viz Přizpůsobení: implementace ICsrfProtection. Chcete-li middleware zcela vypnout, viz Globální zakázání.
Výsledkem je, že už je chráněná minimální aplikace s koncovým bodem pro zpracování formulářů, například následující:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapPost("/widgets", ([FromForm] Widget w) =>
Results.Created($"/widgets/{w.Id}", w));
app.Run();
Prohlížeč, který odesílá požadavek POST /widgets ze stejného původu, se na koncový bod dostane bez problémů. Prohlížeč při https://attacker.example.com odeslání stejného formuláře je odmítnut s 400 - Bad Request, když koncový bod naváže formulář, ještě než se spustí tělo obslužné rutiny. Žádost curl bez Sec-Fetch-Site nebo Origin je povolená.
Vzhledem k tomu, že odmítnutí je ponecháno na příjemcích dat formuláře, endpoint, který data formuláře nečte – například rozhraní JSON API, které váže tělo požadavku z JSON – není automaticky odmítnut ani při požadavku z jiného původu. Verdikt je stále zaznamenán na požadavku na kód, který ho chce zkontrolovat.
Middleware se integruje s existujícím antiforgerovým modelem:
-
Minimální rozhraní API: Voláním koncového bodu se tento koncový bod odhlásí z middlewaru založeného na tokenu i middlewaru ochrany CSRF.
.DisableAntiforgery()Stejná metadata (IAntiforgeryMetadata { RequiresValidation = false }) jsou kontrolována oběma. -
Kontrolery a akce MVC:
[IgnoreAntiforgeryToken]také vyjme koncový bod z obou ochran.
Povolení klientů různého původu
Nejběžnějším scénářem, který vyžaduje zásah, je klient běžící v prohlížeči, který odešle formulář napříč zdroji — například web na https://app.contoso.com, který odešle formulář do API na adrese https://api.contoso.com. Taková odeslání formuláře se ve výchozím nastavení zamítají, protože Sec-Fetch-Site je same-site nebo cross-site, nikoli same-origin, a zpracovatel formuláře toto rozhodnutí prosazuje pomocí 400 - Bad Request.
Middleware CSRF nezavádí vlastní seznam důvěryhodnosti. Použije stejnou zásadu CORS, kterou pro koncový bod určí middleware CORS: pokud tato zásada povoluje Origin požadavku, middleware CSRF zaznamená, že je požadavek povolen.
Zásada se pro každý koncový bod vybírá v tomto pořadí:
-
[EnableCors("api")](MVC) nebo.RequireCors("api")(Minimal API) → zásada s názvem"api". - U koncového bodu nejsou žádná metadata CORS → použije se výchozí zásada zaregistrovaná v
AddDefaultPolicy. - Nenalezena odpovídající zásada (pojmenovaná zásada není zaregistrována, neexistuje výchozí zásada nebo
services.AddCors()nebyla nikdy volána) → žádná důvěra odvozená z CORS. Middleware přejde naSec-Fetch-Sitea pravidla pro Origin vs. Host.
Minimální příklad použití výchozí zásady a minimálního koncového bodu rozhraní API:
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();
Pro pojmenované zásady v jednom koncovém bodu:
app.MapPost("/widgets", ([FromForm] Widget w) => Results.Created($"/widgets/{w.Id}", w))
.RequireCors("api");
Upozornění
AllowAnyOrigin není záměrně respektována jako signál důvěryhodnosti CSRF.
AllowAnyOrigin znamená „jakýkoli prohlížeč může tento prostředek číst“, což je jiná otázka než „libovolný původ může jménem uživatele měnit stav“. Považovat AllowAnyOrigin za důvěryhodný by z tohoto middlewaru udělalo no-op pro zápisy z jiného původu. Aplikace, které potřebují zásadu CORS s veřejným přístupem pro čtení v kombinaci se zápisy chráněnými proti CSRF, by měly explicitně uvést důvěryhodné zdroje pro zápis pomocí WithOrigins, nebo vyjmout koncové body pro zápis, pokud se nespoléhají na ověřování založené na cookie.
[DisableCors] u endpointu není výjimka z ochrany proti CSRF. Přeskočí krok ověření důvěryhodnosti odvozený z CORS a požadavek stále musí splňovat podmínku Sec-Fetch-Site a pravidla Origin-vs-Host. Pokud chcete koncový bod vyjmout z ochrany před útoky CSRF, přečtěte si článek Vyjmutí koncového bodu z ochrany.
Podrobnosti o konfiguraci samotného mechanismu CORS — AddCors, AddDefaultPolicy, AddPolicy, WithOrigins a dalších částí rozhraní API tvůrce zásad — najdete v tématu Povolení požadavků mezi zdroji (CORS) v ASP.NET Core.
Odhlášení koncového bodu
Pokud koncový bod není dostupný v prohlížeči nebo je zabezpečený jinýmcookie mechanismem, například nosným tokenem nebo klíčem rozhraní API, odhlaste ho jednotlivě místo globálního zakázání middlewaru.
Minimální rozhraní API – volání DisableAntiforgery koncového bodu nebo skupiny:
app.MapPost("/api/webhook", (WebhookPayload p) => Results.Accepted())
.DisableAntiforgery();
Kontrolery MVC – použijte [IgnoreAntiforgeryToken] u akce nebo kontroleru:
[ApiController]
[Route("api/[controller]")]
[IgnoreAntiforgeryToken]
public class WebhookController : ControllerBase
{
[HttpPost]
public IActionResult Post([FromBody] WebhookPayload payload) => Accepted();
}
V obou případech se ke koncovému bodu přidá IAntiforgeryMetadata { RequiresValidation = false }, což middleware CSRF respektuje tím, že přeskočí ověření.
Upozornění
Zakázání ochrany CSRF na koncovém bodu by se mělo provést jenom v případě, že koncový bod není zranitelný vůči útokům CSRF – například koncové body, které se nedají volat z prohlížeče nebo které jsou zabezpečené bezcookie ověřování, jako jsou nosné tokeny nebo klíče rozhraní API. Nezakažujte ochranu CSRF u koncových bodů s podporou prohlížeče, které při ověřování spoléhají na soubory cookie.
Globální zakázání
Middleware je možné zakázat v celé aplikaci pomocí konfiguračního DisableCsrfProtection klíče. Toto je nouzová možnost — upřednostněte vypnutí na úrovni jednotlivých endpointů.
V appsettings.json:
{
"DisableCsrfProtection": true
}
Nebo jako proměnná prostředí:
ASPNETCORE_DisableCsrfProtection=true
Pokud je tento klíč nastaven na true, WebApplication přeskočí registraci middlewaru v kanálu zpracování. Služba ICsrfProtection zůstane zaregistrovaná, takže vše, co ji vyřeší, bude dál fungovat.
Upozornění
Automatický middleware pro CSRF také splňuje požadavek na ochranu proti padělání požadavků u koncových bodů, které vyžadují ověření, i když aplikace nevolá app.UseAntiforgery(). Pokud aplikace spoléhá na antiforgery, ale nevolá app.UseAntiforgery(), globálně zakáže middleware CSRF nebo běží na hostiteli, který není vytvořen pomocí WebApplication, kde se middleware neinjektuje, zůstanou tyto endpointy bez middlewaru pro antiforgery. Požadavek na takový koncový bod pak vyvolá výjimku. Zavolejte app.UseAntiforgery() v dané konfiguraci.
Podpora prohlížečů
Sec-Fetch-Site podporuje všechny aktuální verze prohlížečů založených na Chromiu, Firefoxu a Safari. Tabulku autoritativní kompatibility najdete v referenčních informacích k MDN pro Sec-Fetch-Site.
Starší prohlížeče, které předcházejí Fetch Metadata, neodesílají Sec-Fetch-Site. U těchto klientů middleware v takovém případě porovnává hlavičku Origin se schématem a hostitelem požadavku. Prohlížeče už mnoho let odesílají Origin při požadavcích na zápis mezi různými zdroji, takže tento záložní mechanismus pokrývá prakticky veškerý provoz ze starších prohlížečů.
Neprohlížečoví klienti – curl, Postman, mobilní aplikace, volající server–server – obvykle neposílají ani Sec-Fetch-Site, ani Origin. Tyto požadavky jsou povolené, protože CSRF je vektor útoku omezený pouze na prohlížeč, který závisí na tom, že prohlížeč automaticky připojuje přihlašovací údaje, jako jsou soubory cookie. Klient bez prohlížeče, který chce napadnout rozhraní API, nepotřebuje CSRF; rozhraní API může jednoduše volat přímo s použitím přihlašovacích údajů, které má.
Přizpůsobení: implementovat ICsrfProtection
Rozhodovací logika se nachází za rozhraním jedné metody:
namespace Microsoft.AspNetCore.Antiforgery;
public interface ICsrfProtection
{
ValueTask<CsrfProtectionResult> ValidateAsync(HttpContext context);
}
Pokud chcete nahradit výchozí implementaci, zaregistrujte v DI singleton. Vzhledem k tomu, že architektura používá TryAddSingleton, explicitní AddSingleton volání přepíše výchozí:
builder.Services.AddSingleton<ICsrfProtection, AllowlistCsrfProtection>();
Vlastní implementace je užitečná, když model důvěryhodnosti nevyhovuje CORS – například když je upřednostňovaný pevný seznam povolených partnerských zdrojů nebo když jsou potřeba přísnější pravidla:
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());
}
}
Middleware stále respektuje .DisableAntiforgery() / [IgnoreAntiforgeryToken] bez ohledu na to, která implementace je registrována – odhlášení je zpracována samotným middlewarem před ValidateAsync zavoláním.
Interakce s ochranou proti padělání požadavků založenou na tokenech
Dvě ochrany CSRF cílí na různé vrstvy a jsou navržené tak, aby spoluexistily. Sdílejí také stejnou funkci požadavku: oba zaznamenávají svůj výsledek do IAntiforgeryValidationFeature a zpracovatelé formulářů vynucují jakýkoli přítomný verdikt.
| Aspect | Na základě tokenů AntiforgeryMiddleware |
Middleware pro automatickou ochranu proti CSRF |
|---|---|---|
| Představeno | ASP.NET Core 2,0+ | .NET 11 |
| Activation | Výslovný souhlas prostřednictvím app.UseAntiforgery() (nebo implicitně)AddMvc / MapRazorPages / AddRazorComponents |
Automaticky vloženo pomocí WebApplication.CreateBuilder |
| Ověřuje | Synchronizovaný token (pole formuláře + cookie pár) |
Sec-Fetch-Site
/
Origin Záhlaví |
| Requires | Přehled ochrany dat ASP.NET Core pro šifrování tokenů | Žádné tokeny, žádný stav |
| Rozsah prohlížeče | Všechny prohlížeče, které odesílají soubory cookie | Všechny moderní prohlížeče; Origin záložní řešení pro starší |
| Výslovný nesouhlas pro jednotlivé koncové body | .DisableAntiforgery() / [IgnoreAntiforgeryToken] |
Stejné – obě dodržují stejná metadata |
Middleware založený na tokenech konkrétně chrání před klasickým vzorem útoku CSRF, ve kterém škodlivý web aktivuje formulář POST na ohrožený web pomocí okolních souborů cookie uživatele. Automatický middleware CSRF řeší stejnou hrozbu ve vrstvě HTTP pomocí metadat zadaných prohlížečem. Oba můžou být aktivní ve stejném koncovém bodu a mnoho aplikací bude těžit z hloubkové ochrany:
- Razor Stránky, MVC a Blazor aplikace SSR, které už používají systém tokenů, získávají kontrolu založenou na hlavičce, která se spouští před ověřením tokenu, aniž by se změnil tok tokenu.
-
Aplikace Minimal API, které vážou data formulářů, mají k dispozici užitečné výchozí chování, aniž by bylo nutné volat
app.UseAntiforgery()nebo předávatIAntiforgerypřes koncové body. - Rozhraní API volaná z SPA z jiného původu mohou spoléhat na tento middleware v kombinaci se seznamem povolených zdrojů CORS a zcela vynechat tokenový systém, pokud rozhraní API nikdy neposkytuje formuláře HTML.
Automatický middleware CSRF nahrazuje systém založený na tokenech v mnoha scénářích, protože oba chrání stejné koncové body zpracování formulářů. Systém založený na tokenech ponechte v následujících případech:
- Aplikace musí podporovat prohlížeče, které neodesílají
Sec-Fetch-Site. Viz podpora prohlížeče. - Aplikace používá IAntiforgeryAdditionalDataProvider k přenosu dalších dat tam a zpět v rámci tokenu.
- Požadavek na kontrolu zabezpečení nebo dodržování předpisů určuje ochranu tokenů jako nezávislou vrstvu.
Podrobnosti o systému založeném na tokenech, včetně integrace formulářů, toků AJAX, konfigurace prostřednictvím AntiforgeryOptionsa IAntiforgery rozhraní API, najdete v tématu Antiforgery v ASP.NET Core.
Ověření tokenu má přednost
Poté, co aplikace zavolá app.UseAntiforgery(), se middleware založený na tokenech spustí po automatickém middlewaru CSRF. Middleware pro token vymaže jakýkoli verdikt zaznamenaný middlewarem CSRF a nahradí jej výsledkem validace tokenu. Výsledek tokenu je autoritativní:
- Požadavek, aby middleware CSRF označený jako neplatný byl platný, pokud má platný token.
- Požadavek, že je povolený middleware CSRF, je označený jako neplatný, pokud jeho token chybí nebo je neplatný.
Toto řazení znamená, že aplikace používající systém tokenů vykazují stejné chování v rámci celého procesu, jaké měly před zavedením automatického middlewaru, zatímco aplikace, které tokeny nepoužívají, se řídí rozhodnutím middlewaru CSRF.
Blazor statické vykreslování na straně serveru
Blazor Koncové body pro statické vykreslování na straně serveru (SSR) spadají do stejného odloženého modelu. Koncový bod Razor Components důvěřuje verdiktu zaznamenanému na IAntiforgeryValidationFeature nadřazenou vrstvou middleware a vrací 400 - Bad Request při odeslání formuláře pouze tehdy, když je tento verdikt neplatný. Koncový bod už samotný požadavek neověřuje.
Chování závisí na tom, který middleware běžel:
- Aplikace, které volají
app.UseAntiforgery(), se nemění. Middleware založené na tokenech ověřuje každý požadavek a pro vykreslené formuláře jsou stejně jako dříve generovány tokeny proti padělání požadavků. - Aplikace, které nezavolají
app.UseAntiforgery(), jsou chráněné automatickým middlewarem CSRF. V této konfiguraci koncový bod neprovede generování antiforgery tokenu, protože není přítomen žádný middleware, který by token ověřil v pozdějším požadavku.
Jde o změnu chování statického SSR, které dříve odstraňovalo app.UseAntiforgery(): nyní je chráněno middlewarem CSRF, místo aby zůstalo nechráněné, a přestává emitovat antiforgery tokeny. Pokyny k migraci najdete v tématu Migrace z ASP.NET Core v .NET 10 na ASP.NET Core v .NET 11. Formální oznámení o zásadní změně najdete v tématu Blazorvykreslování na straně serveru odkládá ověřování ochrany proti padělání na middleware.
Troubleshooting
Příznakem: Žádosti o stejný zdroj z prohlížeče jsou úspěšné, ale příspěvky formuláře mezi zdroji se vrátí 400 - Bad Request bez textu.
Příčina: Middleware CSRF zaznamenal neplatné vyhodnocení cross-origin požadavku a komponenta pro zpracování formulářů – například akce MVC, vazba formuláře v rozhraní Minimal API nebo odeslání formuláře SSR pomocí Blazor – toto vyhodnocení vynutila pomocí 400 - Bad Request. Toto je očekávané výchozí chování pro koncové body, které zpracovávají formuláře.
Řešení: V závislosti na scénáři zvolte jednu z následujících možností:
- Pokud je původ volání známý a důvěryhodný, povolte ho prostřednictvím CORS.
- Pokud koncový bod není dosažitelný z prohlížeče nebo používá ověřování jiné než cookie, vyřaďte ho pomocí
.DisableAntiforgery()nebo[IgnoreAntiforgeryToken]. - Pokud se celá aplikace musí odhlásit (například během okna migrace), zakažte ji globálně.
Diagnostika: Middleware zaznamenává každý neplatný výsledek na úrovni protokolování Debug v kategorii Microsoft.AspNetCore.Antiforgery.CsrfProtectionMiddleware s názvem události CsrfValidationFailed. Povolte Debug protokolování pro tuto kategorii v appsettings.Development.json:
{
"Logging": {
"LogLevel": {
"Microsoft.AspNetCore.Antiforgery.CsrfProtectionMiddleware": "Debug"
}
}
}
Zaznamenaný verdikt se pak zobrazí v protokolu jako:
dbug: Microsoft.AspNetCore.Antiforgery.CsrfProtectionMiddleware[1]
Cross-origin CSRF protection marked request POST /widgets from origin 'https://attacker.example.com' as invalid.
Reprodukce v lokálním prostředí: Použijte curl s explicitně zadanou hlavičkou Origin k simulaci cross-origin požadavku prohlížeče vůči koncovému bodu formuláře:
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"
Nahraďte {PORT} místním portem HTTPS aplikace.
400 - Bad Request je pozorován, protože koncový bod naváže formulář, který vynucuje zaznamenané rozhodnutí. Koncový bod, který není formulářem, vrátí svou normální odpověď, protože nic nečte verdikt. Bez hlavičky Origin je tentýž požadavek povolen, protože curl také neodesílá Sec-Fetch-Site a požadavek, který neobsahuje ani jednu z těchto hlaviček, je považován za neprohlížečového klienta.
Systém antiforgery založený na tokenech popsaný ve zbývající části tohoto článku předchází tomuto middlewaru a zůstane k dispozici. U většiny aplikací je automatická ochrana dostatečná sama o sobě. Pokyny k tomu, kdy zachovat systém založený na tokenech a postup migrace, najdete v tématu Migrace z ASP.NET Core v .NET 10 na ASP.NET Core v .NET 11.
Antiforgery v ASP.NET Core
Upozornění
ASP.NET Core implementuje antiforgery pomocí ASP.NET Core Data Protection. Zásobník ochrany dat musí být nakonfigurovaný tak, aby fungoval v serverové farmě. Další informace najdete v tématu Konfigurace ochrany dat.
Do kontejneru vkládání závislostí se middleware antiforgery přidá, když je voláno některé z následujících API rozhraní Program.cs:
Další informace naleznete v části Antiforgery s minimálními API rozhraními.
FormTagHelper vkládá do prvků formulářů HTML tokeny proti padělkům. Následující kód v Razor souboru automaticky generuje antiforgery tokeny:
<form method="post">
<!-- ... -->
</form>
Podobně IHtmlHelper.BeginForm ve výchozím nastavení generuje antiforgery tokeny, pokud metoda formuláře není GET.
Automatické generování tokenů antiforgery pro elementy formuláře HTML nastane, když <form> značka obsahuje method="post" atribut a některé z následujících hodnot jsou pravdivé:
- Atribut akce je prázdný (
action=""). - Atribut akce není zadán (
<form method="post">).
Automatické generování antiforgerických tokenů pro elementy formuláře HTML lze zakázat:
Explicitně zakažte antiforgery tokeny s atributem
asp-antiforgery:<form method="post" asp-antiforgery="false"> <!-- ... --> </form>Prvek formuláře je vyloučen z pomocníků značek pomocí symbolu ! opt-out symbol:
<!form method="post"> <!-- ... --> </!form>Odeberte
FormTagHelperze zobrazení.FormTagHelperlze ze zobrazení odebrat přidáním následující direktivy do Razor zobrazení.@removeTagHelper Microsoft.AspNetCore.Mvc.TagHelpers.FormTagHelper, Microsoft.AspNetCore.Mvc.TagHelpers
Poznámka:
Razor Stránky jsou automaticky chráněny před XSRF/CSRF. Další informace najdete v tématu XSRF/CSRF a Razor Pages.
Nejběžnějším přístupem k ochraně před útoky CSRF je použití vzoru tokenů synchronizátoru (STP). STP se používá, když uživatel požádá o stránku s daty formuláře:
- Server odešle klientovi token přidružený k identitě aktuálního uživatele.
- Klient odešle token zpět na server k ověření.
- Pokud server obdrží token, který neodpovídá identitě ověřeného uživatele, žádost se odmítne.
Token je jedinečný a nepředvídatelný. Token lze použít také k zajištění správného sekvencování řady požadavků (například k zajištění pořadí požadavků na stránce 1 > strana 2 > strana 3). Všechny formuláře v šablonách ASP.NET Core MVC a Razor Pages generují antiforgery tokeny. Následující dvojice příkladů zobrazení generuje antiforgery tokeny:
<form asp-action="Index" asp-controller="Home" method="post">
<!-- ... -->
</form>
@using (Html.BeginForm("Index", "Home"))
{
<!-- ... -->
}
Explicitně přidejte antiforgery token do prvku <form> bez použití značkového pomocníka s pomocnou rutinou HTML @Html.AntiForgeryToken:
<form asp-action="Index" asp-controller="Home" method="post">
@Html.AntiForgeryToken()
<!-- ... -->
</form>
V každém z předchozích případů ASP.NET Core přidá skryté pole formuláře podobné následujícímu příkladu:
<input name="__RequestVerificationToken" type="hidden" value="CfDJ8NrAkS ... s2-m9Yw">
ASP.NET Core obsahuje tři filtry pro práci s antiforgery tokeny:
Ochrana proti padělání s AddControllers
Volání AddControllers neaktivuje antiforgery tokeny. AddControllersWithViews musí být volána, aby byla podporována integrovaná antiforgery token.
Více karet prohlížeče a vzor synchronizačního tokenu
Nejsou podporovány více karty přihlášené jako různí uživatelé, nebo přihlášení jako anonymní uživatel.
Nakonfigurujte antiforgery pomocí AntiforgeryOptions
Přizpůsobte AntiforgeryOptions v souboru Program aplikace:
builder.Services.AddAntiforgery(options =>
{
// Set Cookie properties using CookieBuilder properties†.
options.FormFieldName = "AntiforgeryFieldname";
options.HeaderName = "X-CSRF-TOKEN-HEADERNAME";
options.SuppressXFrameOptionsHeader = false;
});
Nastavte vlastnosti antiforgery cookie pomocí vlastností CookieBuilder třídy, jak je uvedeno v následující tabulce.
| Možnost | Popis |
|---|---|
| Cookie | Určuje nastavení použitá k vytvoření ochranných cookies. |
| FormFieldName | Název skrytého pole formuláře používaného systémem antiforgery pro vykreslení tokenů antiforgery v zobrazeních. |
| HeaderName | Název hlavičky používané systémem antiforgery. Pokud null, systém považuje pouze data formuláře. |
| SuppressXFrameOptionsHeader | Určuje, jestli se má potlačit generování hlavičky X-Frame-Options . Ve výchozím nastavení se hlavička vygeneruje s hodnotou SAMEORIGIN. Výchozí hodnota je false. |
Některé prohlížeče neumožňují nezabezpečeným koncovým bodům nastavit soubory cookie s příznakem "secure" nebo přepsat soubory cookie, jejichž je nastavený příznak secure (další informace najdete v tématu Vyřazení změn zabezpečených souborů cookie z nezabezpečených zdrojů). Vzhledem k tomu, že kombinování zabezpečených a nezabezpečených koncových bodů je běžným scénářem v aplikacích, ASP.NET Core zmírňuje omezení zásad zabezpečení u některých souborů cookie, jako například u antiforgery cookie, tím, že nastavuje atribut cookie souboru SecurePolicy na hodnotu CookieSecurePolicy.None. Kdyby uživatel se zlými úmysly ukradl antiforgery cookie, musí také ukrást antiforgery token, který je obvykle odeslán prostřednictvím pole formuláře (běžnější) nebo samostatné hlavičky požadavku (méně běžné) plus autentizaci cookie.
Cookies související s ověřováním nebo autorizací používají silnější zásady než CookieSecurePolicy.None.
Volitelně můžete antiforgery cookie zabezpečit v jinýchDevelopment prostředích pomocí protokolu SSL (Secure Sockets Layer) pouze přes PROTOKOL HTTPS s následujícím AntiforgeryOptions.Cookie nastavením vlastnosti v souboru aplikace Program :
if (!builder.Environment.IsDevelopment())
{
builder.Services.AddAntiforgery(o =>
{
o.Cookie.SecurePolicy = CookieSecurePolicy.Always;
});
}
Další informace najdete na webu CookieAuthenticationOptions.
Generování antiforgery tokenů pomocí IAntiforgery
IAntiforgery poskytuje rozhraní API ke konfiguraci funkcí proti padělání.
IAntiforgery lze požádat v Program.cs pomocí WebApplication.Services. Následující příklad používá middleware z domovské stránky aplikace k vygenerování antiforgery tokenu a jeho odeslání v odpovědi jako 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);
});
Předchozí příklad nastaví cookie s názvem XSRF-TOKEN. Klient si to cookie může přečíst a zadat jeho hodnotu jako hlavičku připojenou k žádostem AJAX. Angular například obsahuje integrovanou ochranu XSRF, která ve výchozím nastavení čte pojmenovaný cookie.
Vyžadovat ověření proti padělání
Filtr akcí ValidateAntiForgeryToken lze použít u jednotlivé akce, kontroleru nebo globálně. Požadavky provedené na akce, které mají tento filtr použitý, jsou blokované, pokud požadavek neobsahuje platný antiforgery token:
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Index()
{
// ...
return RedirectToAction();
}
Atribut ValidateAntiForgeryToken vyžaduje token pro požadavky na metody akce, které označí, včetně požadavků HTTP GET. Pokud se atribut ValidateAntiForgeryToken použije na kontrolery aplikace, můžete ho přepsat pomocí atributu IgnoreAntiforgeryToken.
Automatické ověření tokenů antiforgery pouze pro nebezpečné metody HTTP
Místo široké aplikace atributu ValidateAntiForgeryToken a jeho přepsání pomocí atributů IgnoreAntiforgeryToken lze použít atribut AutoValidateAntiforgeryToken. Tento atribut funguje stejně jako ValidateAntiForgeryToken atribut s tím rozdílem, že nevyžaduje tokeny pro požadavky provedené pomocí následujících metod HTTP:
- GET
- Hlavička
- MOŽNOSTI
- TRACE
Pro scénáře, které nepoužívají rozhraní API, doporučujeme používat AutoValidateAntiforgeryToken široce. Tento atribut zajišťuje, že akce POST jsou ve výchozím nastavení chráněné. Alternativou je ignorovat antiforgery tokeny ve výchozím nastavení, pokud ValidateAntiForgeryToken není použita u jednotlivých metod akcí. V tomto scénáři je pravděpodobnější, že metoda akce POST zůstane nechráněná omylem, takže aplikace bude zranitelná vůči útokům CSRF. Všechny POSTy by měly odesílat antiforgery token.
Rozhraní API nemají automatický způsob odeslání části tokenu bez cookie. Implementace pravděpodobně závisí na implementaci klientského kódu. Tady je několik příkladů:
Příklad na úrovni třídy:
[AutoValidateAntiforgeryToken]
public class HomeController : Controller
Globální příklad:
builder.Services.AddControllersWithViews(options =>
{
options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute());
});
Přepsání atributů antiforgery globálního serveru nebo kontroleru
Filtr IgnoreAntiforgeryToken se používá k odstranění potřeby tokenu antiforgery pro danou akci (nebo kontroler). Při použití tento filtr přepíše filtry ValidateAntiForgeryToken a AutoValidateAntiforgeryToken zadané na vyšší úrovni (globálně nebo na řadiči).
[IgnoreAntiforgeryToken]
public IActionResult IndexOverride()
{
// ...
return RedirectToAction();
}
Aktualizace tokenů po ověření
Tokeny by se měly aktualizovat po ověření uživatele přesměrováním uživatele na stránku zobrazení nebo Razor stránky.
JavaScript, AJAX a SPA
V tradičních aplikacích založených na HTML se antiforgery tokeny předávají serveru pomocí skrytých polí formuláře. V moderních aplikacích založených na JavaScriptu a SA se mnoho požadavků provádí programově. Tyto požadavky AJAX mohou k odeslání tokenu použít jiné techniky, jako jsou hlavičky požadavků nebo soubory cookie.
Pokud se soubory cookie používají k ukládání ověřovacích tokenů a k ověřování požadavků rozhraní API na serveru, je csrF potenciálním problémem. Pokud se k uložení tokenu používá místní úložiště, může se zmírnit ohrožení zabezpečení CSRF, protože hodnoty z místního úložiště se na server neodesílají automaticky s každou žádostí. Použití místního úložiště k uložení anti-forgery tokenu na klientovi a odeslání tokenu hlavičkou požadavku je doporučený postup.
Blazor
Pro více informací si přečtěte ASP.NET Core Blazor autentizaci a autorizaci.
JavaScript
Pomocí JavaScriptu se zobrazeními lze token vytvořit pomocí služby v zobrazení. IAntiforgery Vložte službu do zobrazení a zavolejteGetAndStoreTokens:
@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>
}
Předchozí příklad používá JavaScript ke čtení skryté hodnoty pole hlavičky AJAX POST.
Tento přístup eliminuje nutnost zabývat se přímo nastavením souborů cookie ze serveru nebo jejich čtením z klienta. Pokud však vložení IAntiforgery služby není možné, použijte JavaScript pro přístup k tokenům v souborech cookie:
- Přístupové tokeny v dalším požadavku na server, obvykle
same-origin. - Použijte obsah cookie k vytvoření hlavičky s hodnotou tokenu.
Za předpokladu, že skript odešle token v hlavičce požadavku s názvem X-XSRF-TOKEN, nakonfigurujte službu antiforgery tak, aby hledala hlavičku X-XSRF-TOKEN :
builder.Services.AddAntiforgery(options => options.HeaderName = "X-XSRF-TOKEN");
Následující příklad přidá chráněný koncový bod, který zapíše token požadavku do javascriptově čitelného cookiekódu:
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();
Následující příklad používá JavaScript k vytvoření požadavku AJAX na získání tokenu a provedení dalšího požadavku s příslušnou hlavičkou:
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}`
}
Poznámka:
Pokud je token antiforgery zadaný v hlavičce požadavku i v datové části formuláře, ověří se pouze token v hlavičce.
Ochrana proti padělání s minimálními rozhraními API
Zavolejte AddAntiforgery a zaregistrujte služby ochrany proti padělání v DI. Antiforgery tokeny se používají ke zmírnění útoků proti padělání požadavků mezi weby.
var builder = WebApplication.CreateBuilder();
builder.Services.AddAntiforgery();
var app = builder.Build();
app.UseAntiforgery();
app.MapGet("/", () => "Hello World!");
app.Run();
Antiforgery middleware:
- Není-li zkráceno provádění zbývající části kanálu požadavku?
- Nastaví IAntiforgeryValidationFeature v HttpContext.Features aktuálního požadavku.
Antiforgery token je ověřen pouze v případě, že:
- Koncový bod obsahuje metadata, která implementují IAntiforgeryMetadata tam, kde
RequiresValidation=true. - Metoda HTTP přidružená ke koncovému bodu je relevantní metoda HTTP typu POST, PUT nebo PATCH.
- Požadavek je přidružený k platnému koncovému bodu.
Antiforgery middleware nezkracuje pipeline požadavků. Kód koncového bodu se vždy spustí, i když selže ověření tokenu. Pokud chcete sledovat výsledek ověření tokenu, vyřešte IAntiforgeryValidationFeature od HttpContext.Features a zkontrolujte jeho vlastnost IsValid nebo vlastnost Error pro podrobnosti o selhání. Tento přístup je užitečný v případě, že koncové body vyžadují vlastní zpracování pro selhavší ověření ochrany proti padělání.
Poznámka: Pokud je antiforgery middleware povolen manuálně, musí být spuštěn po autentizačním a autorizačním middlewaru, aby se zabránilo čtení dat formuláře, když uživatel není ověřený.
Ve výchozím nastavení minimální rozhraní API, která přijímají data formuláře, vyžadují ověření tokenu antiforgery a před spuštěním kódu aplikace selžou, pokud ověření antiforgery není úspěšné.
Zvažte následující GenerateForm metodu:
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>
";
}
Předchozí kód obsahuje tři argumenty, akci, token antiforgery a bool indikující, jestli se má token použít.
Podívejte se na následující ukázku:
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>
";
}
}
V předchozím kódu se příspěvky odesílají do:
-
/todovyžaduje platný token proti padělání. -
/todo2nevyžaduje platný antiforgery token, protože DisableAntiforgery je volána.
app.MapPost("/todo", ([FromForm] Todo todo) => Results.Ok(todo));
app.MapPost("/todo2", ([FromForm] Todo todo) => Results.Ok(todo))
.DisableAntiforgery();
Upozornění
Volání .DisableAntiforgery() deaktivuje ochranu proti falšování požadavků mezi weby (CSRF) pro daný koncový bod. To by se mělo použít jenom v případě, že koncový bod není zranitelný vůči útokům CSRF, například:
- Koncové body, které se nedají volat z prohlížeče (například interní rozhraní API)
- Koncové body zabezpečené pomocí ověřování nezaloženého na cookie (například bearer tokeny nebo klíče rozhraní API)
- Interní koncové body nebo koncové body infrastruktury, které nespoléhají na soubory cookie uživatelů
Nezakazujte ověřování antiforgery pro koncové body přístupné z prohlížeče, které spoléhají na soubory cookie pro ověřování nebo zpracovávají data formulářů odeslaná uživatelem, protože to zpřístupňuje vaši aplikaci útokům CSRF.
A POST pro:
-
/todoz formuláře vygenerovaného/koncovým bodem bude úspěšný, protože token antiforgery je platný. -
/todoz formuláře generovaného/SkipTokenselže, protože antiforgery není zahrnutý. -
/todo2z formuláře vytvořeného koncovým bodem/DisableAntiforgeryproběhne úspěšně, protože ochrana proti padělání není vyžadována.
app.MapPost("/todo", ([FromForm] Todo todo) => Results.Ok(todo));
app.MapPost("/todo2", ([FromForm] Todo todo) => Results.Ok(todo))
.DisableAntiforgery();
Při odeslání formuláře bez platného antiforgery tokenu:
- Ve prostředí
Developmentse vyvolá výjimka. - V prostředí
Productionje zaznamenána zpráva.
Omezení metod HTTP a interakce s HttpMethodOverrideMiddleware
Pro cestu AntiforgeryMiddleware ochrany proti padělání založenou na middlewaru UseAntiforgery() ověřují tokeny ochrany proti padělání pouze pro požadavky HTTP POST, PUT a PATCH. Jiné metody HTTP, například DELETE, se neověřují automaticky.
Pokud chcete ověřit tokeny proti padělání požadavků pro jiné metody HTTP, získejte IAntiforgery z DI a explicitně zavolejte ValidateRequestAsync nebo IsRequestValidAsync:
app.MapDelete("/item/{id}", async (int id, IAntiforgery antiforgery, HttpContext context) =>
{
await antiforgery.ValidateRequestAsync(context);
// Process the DELETE request
});
Upozornění
Pokud je HttpMethodOverrideMiddleware nakonfigurován s FormFieldName (režim pole formuláře) a umístěn před AntiforgeryMiddleware, lze požadavek POST přepsat na DELETE (nebo jinou neověřovanou metodu). Protože AntiforgeryMiddleware ověřuje pouze POST, PUT a PATCH, přepsaný požadavek obchází antiforgery ověřování.
Ochrana těchto koncových bodů:
- Preferujte umístění
HttpMethodOverrideMiddlewarepo ověření antiforgery, pokud to kanál umožňuje. - Vyhněte se přepsání polí formuláře pro koncové body, které spoléhají na ověřování proti padělání.
- Pokud se musí nejprve spustit přepsání pole formuláře, ověřte token antiforgery explicitně pomocí
IAntiforgery.ValidateRequestAsync.
Podrobnosti o konfiguraci najdete v ASP.NET Core middlewaru.
Ověřování systému Windows a antiforgery cookies
Při použití ověřování systému Windows musí být koncové body aplikací chráněné proti útokům CSRF stejným způsobem jako u souborů cookie. Prohlížeč implicitně odesílá kontext ověřování na server a koncové body, které musí být chráněné před útoky CSRF.
Rozšířit antifalšování
Tento IAntiforgeryAdditionalDataProvider typ umožňuje vývojářům rozšířit chování systému anti-CSRF tím, že v každém tokenu přetáhne další data. Metoda GetAdditionalData se volá při každém vygenerování tokenu pole a návratová hodnota se vloží do vygenerovaného tokenu. Implementátor by mohl vrátit časové razítko, náhodné číslo nebo jinou hodnotu a potom zavolat ValidateAdditionalData k ověření těchto dat, když se token ověřuje. Uživatelské jméno klienta je již vloženo do vygenerovaných tokenů, takže tyto informace nemusíte obsahovat. Pokud token obsahuje doplňková data, ale není nakonfigurovaná žádná IAntiForgeryAdditionalDataProvider , doplňková data se neověřují.
Další materiály
Padělání požadavků mezi weby (označované také jako XSRF nebo CSRF) je útok na aplikace hostované na webu, kdy škodlivá webová aplikace může ovlivnit interakci mezi klientským prohlížečem a webovou aplikací, která důvěřuje danému prohlížeči. Tyto útoky jsou možné, protože webové prohlížeče automaticky odesílají některé typy ověřovacích tokenů s každou žádostí na web. Tato forma zneužití se také označuje jako jednoklikový útok nebo únos relace, protože útok využívá dříve ověřenou relaci uživatele.
Příklad útoku CSRF:
Uživatel se přihlásí k
www.good-banking-site.example.compomocí ověření formulářem. Server ověřuje uživatele a vydává odpověď, která zahrnuje ověřování cookie. Web je zranitelný vůči útoku, protože důvěřuje všem požadavkem, který obdrží s platným ověřováním cookie.Uživatel navštíví škodlivý web.
www.bad-crook-site.example.comŠkodlivý web obsahuje
www.bad-crook-site.example.comformulář HTML podobný následujícímu příkladu:<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>Všimněte si, že formulář
actionodesílá na ohrožený web, nikoli na škodlivý web. Toto je "cross-site" část CSRF.Uživatel vybere tlačítko Odeslat. Prohlížeč vytvoří požadavek a automaticky zahrne ověřování cookie pro požadovanou doménu.
www.good-banking-site.example.comPožadavek se spustí na
www.good-banking-site.example.comserveru s kontextem ověřování uživatele a může provést jakoukoli akci, kterou může ověřený uživatel provést.
Kromě scénáře, ve kterém uživatel vybere tlačítko pro odeslání formuláře, může škodlivý web:
- Spusťte skript, který automaticky odešle formulář.
- Odešlete formulář jako požadavek AJAX.
- Skryjte formulář pomocí šablon stylů CSS.
Tyto alternativní scénáře nevyžadují žádnou akci ani vstup od jiného uživatele, než je počáteční návštěva škodlivého webu.
Použití PROTOKOLU HTTPS nezabrání útoku CSRF. Škodlivý web může odeslat https://www.good-banking-site.example.com/ požadavek stejně snadno, jako by mohl odeslat nezabezpečený požadavek.
Některé útoky cílí na koncové body, které reagují na požadavky GET, v takovém případě lze použít značku image k provedení akce. Tato forma útoku je běžná na webech fóra, které umožňují obrázky, ale blokují JavaScript. Aplikace, které mění stav požadavků GET, kde se mění proměnné nebo prostředky, jsou zranitelné vůči škodlivým útokům. Požadavky GET, které změní stav, jsou nezabezpečené. Osvědčeným postupem je nikdy změnit stav požadavku GET.
Útoky CSRF jsou možné vůči webovým aplikacím, které k ověřování používají soubory cookie, protože:
- Prohlížeče ukládají soubory cookie vydané webovou aplikací.
- Uložené soubory cookie obsahují soubory cookie relace pro ověřené uživatele.
- Prohlížeče odesílají všechny soubory cookie přidružené k doméně do webové aplikace bez ohledu na to, jak se požadavek na aplikaci vygeneroval v prohlížeči.
Útoky CSRF ale nejsou omezené na zneužití souborů cookie. Například základní ověřování a ověřování pomocí digest je také ohroženo. Jakmile se uživatel přihlásí pomocí ověřování Basic nebo Digest, prohlížeč automaticky odešle přihlašovací údaje, dokud relace neskončí.
V tomto kontextu relace odkazuje na relaci na straně klienta, ve které je uživatel ověřen. Nesouvisí to se serverovými relacemi ani s middlewarem relací ASP.NET Core.
Uživatelé mohou chránit před ohroženími zabezpečení CSRF pomocí bezpečnostních opatření:
- Po dokončení se odhlaste z webových aplikací.
- Pravidelně vymažte soubory cookie prohlížeče.
Ohrožení zabezpečení CSRF jsou ale v zásadě problém s webovou aplikací, nikoli koncovým uživatelem.
Základy ověřování
Cookie-založené ověřování je oblíbenou formou ověřování. Systémy ověřování založené na tokenech jsou stále oblíbenější, zejména pro jednostráňové aplikace (SPA).
Cookie-založené ověřování
Když se uživatel ověří pomocí uživatelského jména a hesla, vydá token obsahující ověřovací lístek, který se dá použít k ověřování a autorizaci. Token se uloží jako cookie odesílaný s každým požadavkem, který klient provede. Generování a ověřování tohoto cookie provádí middleware pro ověřování cookie. Middleware serializuje uživatelský principál do zašifrovaného cookie. V následných požadavcích middleware ověří cookie, znovu vytvoří hlavní objekt a přiřadí tento hlavní objekt k vlastnosti HttpContext.User.
Ověřování na základě tokenů
Když je uživatel ověřen, obdrží token, nikoli antiforgery token. Token obsahuje informace o uživateli ve formě deklarací identity nebo referenčního tokenu, který odkazuje aplikaci na stav uživatele udržovaný v aplikaci. Když se uživatel pokusí získat přístup k prostředku, který vyžaduje ověření, token se odešle do aplikace s extra autorizační hlavičkou ve formě tokenu Bearer . Díky tomuto přístupu je aplikace bezstavová. V každém dalším požadavku se token předá v požadavku na ověření na straně serveru. Tento token není šifrovaný, je zakódovaný. Na serveru je token dekódován pro přístup k jeho informacím. Pokud chcete token odeslat při dalších požadavcích, uložte ho do místního úložiště prohlížeče. Umístění tokenu do místního úložiště prohlížeče a jeho načtení a jeho použití jako nosný token poskytuje ochranu před útoky CSRF. Pokud je však aplikace zranitelná vůči injektáži skriptu prostřednictvím XSS nebo ohroženého externího javascriptového souboru, může kyberattacker načíst libovolnou hodnotu z místního úložiště a odeslat ji sama sobě. ASP.NET Core ve výchozím nastavení kóduje veškerý výstup na straně serveru z proměnných a snižuje riziko XSS. Pokud toto chování přepíšete pomocí Html.Raw nebo vlastního kódu s nedůvěryhodným vstupem, můžete zvýšit riziko XSS.
Nedělejte si starosti s ohrožením zabezpečení CSRF, pokud je token uložený v místním úložišti prohlížeče. CSRF je riziko, když je token uložen v cookie. Další informace najdete v problému GitHubu SPA code sample adds two cookies.
Více aplikací hostovaných v jedné doméně
Sdílená hostitelská prostředí jsou zranitelná vůči únosu relace, CSRF útokům na přihlašování a dalším útokům.
I když example1.contoso.net a example2.contoso.net jsou různí hostitelé, existuje implicitní vztah důvěryhodnosti mezi hostiteli v rámci *.contoso.net domény. Tento implicitní vztah důvěryhodnosti umožňuje potenciálně nedůvěryhodným hostitelům ovlivnit soubory cookie ostatních (zásady stejného původu, které řídí požadavky AJAX, se nemusí nutně vztahovat na soubory cookie HTTP).
Útoky, které zneužívají důvěryhodné soubory cookie mezi aplikacemi hostovanými ve stejné doméně, je možné zabránit tím, že nesdílí domény. Když je každá aplikace hostovaná ve vlastní doméně, neexistuje žádný implicitní cookie vztah důvěryhodnosti, který by bylo potřeba zneužít.
Antiforgery v ASP.NET Core
Upozornění
ASP.NET Core implementuje antiforgery pomocí ASP.NET Core Data Protection. Zásobník ochrany dat musí být nakonfigurovaný tak, aby fungoval v serverové farmě. Další informace najdete v tématu Konfigurace ochrany dat.
Do kontejneru vkládání závislostí se middleware antiforgery přidá, když je voláno některé z následujících API rozhraní Program.cs:
FormTagHelper vkládá do prvků formulářů HTML tokeny proti padělkům. Následující kód v Razor souboru automaticky generuje antiforgery tokeny:
<form method="post">
<!-- ... -->
</form>
Podobně IHtmlHelper.BeginForm ve výchozím nastavení generuje antiforgery tokeny, pokud metoda formuláře není GET.
Automatické generování tokenů antiforgery pro elementy formuláře HTML nastane, když <form> značka obsahuje method="post" atribut a některé z následujících hodnot jsou pravdivé:
- Atribut akce je prázdný (
action=""). - Atribut akce není zadán (
<form method="post">).
Automatické generování antiforgerických tokenů pro elementy formuláře HTML lze zakázat:
Explicitně zakažte antiforgery tokeny s atributem
asp-antiforgery:<form method="post" asp-antiforgery="false"> <!-- ... --> </form>Prvek formuláře je vyloučen z pomocníků značek pomocí symbolu ! opt-out symbol:
<!form method="post"> <!-- ... --> </!form>Odeberte
FormTagHelperze zobrazení.FormTagHelperlze ze zobrazení odebrat přidáním následující direktivy do Razor zobrazení.@removeTagHelper Microsoft.AspNetCore.Mvc.TagHelpers.FormTagHelper, Microsoft.AspNetCore.Mvc.TagHelpers
Poznámka:
Razor Stránky jsou automaticky chráněny před XSRF/CSRF. Další informace najdete v tématu XSRF/CSRF a Razor Pages.
Nejběžnějším přístupem k ochraně před útoky CSRF je použití vzoru tokenů synchronizátoru (STP). STP se používá, když uživatel požádá o stránku s daty formuláře:
- Server odešle klientovi token přidružený k identitě aktuálního uživatele.
- Klient odešle token zpět na server k ověření.
- Pokud server obdrží token, který neodpovídá identitě ověřeného uživatele, žádost se odmítne.
Token je jedinečný a nepředvídatelný. Token lze použít také k zajištění správného sekvencování řady požadavků (například k zajištění pořadí požadavků na stránce 1 > strana 2 > strana 3). Všechny formuláře v šablonách ASP.NET Core MVC a Razor Pages generují antiforgery tokeny. Následující dvojice příkladů zobrazení generuje antiforgery tokeny:
<form asp-action="Index" asp-controller="Home" method="post">
<!-- ... -->
</form>
@using (Html.BeginForm("Index", "Home"))
{
<!-- ... -->
}
Explicitně přidejte antiforgery token do prvku <form> bez použití značkového pomocníka s pomocnou rutinou HTML @Html.AntiForgeryToken:
<form asp-action="Index" asp-controller="Home" method="post">
@Html.AntiForgeryToken()
<!-- ... -->
</form>
V každém z předchozích případů ASP.NET Core přidá skryté pole formuláře podobné následujícímu příkladu:
<input name="__RequestVerificationToken" type="hidden" value="CfDJ8NrAkS ... s2-m9Yw">
ASP.NET Core obsahuje tři filtry pro práci s antiforgery tokeny:
Ochrana proti padělání s AddControllers
Volání AddControllers neaktivuje antiforgery tokeny. AddControllersWithViews musí být volána, aby byla podporována integrovaná antiforgery token.
Více karet prohlížeče a vzor synchronizačního tokenu
Pouze naposledy načtená stránka obsahuje platný token proti padělání dle vzoru Synchronizer Token. Použití více karet může být problematické. Pokud například uživatel otevře více karet:
- Pouze naposledy načtená záložka obsahuje platný token proti padělání.
- Požadavky provedené z dříve načtených záložek selžou s chybou:
Antiforgery token validation failed. The antiforgery cookie token and request token do not match
Pokud se jedná o problém, zvažte alternativní vzory ochrany CSRF.
Nakonfigurujte antiforgery pomocí AntiforgeryOptions
Přizpůsobte AntiforgeryOptions v souboru Program aplikace:
builder.Services.AddAntiforgery(options =>
{
// Set Cookie properties using CookieBuilder properties†.
options.FormFieldName = "AntiforgeryFieldname";
options.HeaderName = "X-CSRF-TOKEN-HEADERNAME";
options.SuppressXFrameOptionsHeader = false;
});
Nastavte vlastnosti antiforgery cookie pomocí vlastností CookieBuilder třídy, jak je uvedeno v následující tabulce.
| Možnost | Popis |
|---|---|
| Cookie | Určuje nastavení použitá k vytvoření ochranných cookies. |
| FormFieldName | Název skrytého pole formuláře používaného systémem antiforgery pro vykreslení tokenů antiforgery v zobrazeních. |
| HeaderName | Název hlavičky používané systémem antiforgery. Pokud null, systém považuje pouze data formuláře. |
| SuppressXFrameOptionsHeader | Určuje, jestli se má potlačit generování hlavičky X-Frame-Options . Ve výchozím nastavení se hlavička vygeneruje s hodnotou SAMEORIGIN. Výchozí hodnota je false. |
Některé prohlížeče neumožňují nezabezpečeným koncovým bodům nastavit soubory cookie s příznakem "secure" nebo přepsat soubory cookie, jejichž je nastavený příznak secure (další informace najdete v tématu Vyřazení změn zabezpečených souborů cookie z nezabezpečených zdrojů). Vzhledem k tomu, že kombinování zabezpečených a nezabezpečených koncových bodů je běžným scénářem v aplikacích, ASP.NET Core zmírňuje omezení zásad zabezpečení u některých souborů cookie, jako například u antiforgery cookie, tím, že nastavuje atribut cookie souboru SecurePolicy na hodnotu CookieSecurePolicy.None. Kdyby uživatel se zlými úmysly ukradl antiforgery cookie, musí také ukrást antiforgery token, který je obvykle odeslán prostřednictvím pole formuláře (běžnější) nebo samostatné hlavičky požadavku (méně běžné) plus autentizaci cookie.
Cookies související s ověřováním nebo autorizací používají silnější zásady než CookieSecurePolicy.None.
Volitelně můžete antiforgery cookie zabezpečit v jinýchDevelopment prostředích pomocí protokolu SSL (Secure Sockets Layer) pouze přes PROTOKOL HTTPS s následujícím AntiforgeryOptions.Cookie nastavením vlastnosti v souboru aplikace Program :
if (!builder.Environment.IsDevelopment())
{
builder.Services.AddAntiforgery(o =>
{
o.Cookie.SecurePolicy = CookieSecurePolicy.Always;
});
}
Další informace najdete na webu CookieAuthenticationOptions.
Generování antiforgery tokenů pomocí IAntiforgery
IAntiforgery poskytuje rozhraní API ke konfiguraci funkcí proti padělání.
IAntiforgery lze požádat v Program.cs pomocí WebApplication.Services. Následující příklad používá middleware z domovské stránky aplikace k vygenerování antiforgery tokenu a jeho odeslání v odpovědi jako 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);
});
Předchozí příklad nastaví cookie s názvem XSRF-TOKEN. Klient si to cookie může přečíst a zadat jeho hodnotu jako hlavičku připojenou k žádostem AJAX. Angular například obsahuje integrovanou ochranu XSRF, která ve výchozím nastavení čte pojmenovaný cookie.
Vyžadovat ověření proti padělání
Filtr akcí ValidateAntiForgeryToken lze použít u jednotlivé akce, kontroleru nebo globálně. Požadavky provedené na akce, které mají tento filtr použitý, jsou blokované, pokud požadavek neobsahuje platný antiforgery token:
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Index()
{
// ...
return RedirectToAction();
}
Atribut ValidateAntiForgeryToken vyžaduje token pro požadavky na metody akce, které označí, včetně požadavků HTTP GET. Pokud se atribut ValidateAntiForgeryToken použije na kontrolery aplikace, můžete ho přepsat pomocí atributu IgnoreAntiforgeryToken.
Automatické ověření tokenů antiforgery pouze pro nebezpečné metody HTTP
Místo široké aplikace atributu ValidateAntiForgeryToken a jeho přepsání pomocí atributů IgnoreAntiforgeryToken lze použít atribut AutoValidateAntiforgeryToken. Tento atribut funguje stejně jako ValidateAntiForgeryToken atribut s tím rozdílem, že nevyžaduje tokeny pro požadavky provedené pomocí následujících metod HTTP:
- GET
- Hlavička
- MOŽNOSTI
- TRACE
Pro scénáře, které nepoužívají rozhraní API, doporučujeme používat AutoValidateAntiforgeryToken široce. Tento atribut zajišťuje, že akce POST jsou ve výchozím nastavení chráněné. Alternativou je ignorovat antiforgery tokeny ve výchozím nastavení, pokud ValidateAntiForgeryToken není použita u jednotlivých metod akcí. V tomto scénáři je pravděpodobnější, že metoda akce POST zůstane nechráněná omylem, takže aplikace bude zranitelná vůči útokům CSRF. Všechny POSTy by měly odesílat antiforgery token.
Rozhraní API nemají automatický způsob odeslání části tokenu bez cookie. Implementace pravděpodobně závisí na implementaci klientského kódu. Tady je několik příkladů:
Příklad na úrovni třídy:
[AutoValidateAntiforgeryToken]
public class HomeController : Controller
Globální příklad:
builder.Services.AddControllersWithViews(options =>
{
options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute());
});
Přepsání atributů antiforgery globálního serveru nebo kontroleru
Filtr IgnoreAntiforgeryToken se používá k odstranění potřeby tokenu antiforgery pro danou akci (nebo kontroler). Při použití tento filtr přepíše filtry ValidateAntiForgeryToken a AutoValidateAntiforgeryToken zadané na vyšší úrovni (globálně nebo na řadiči).
[IgnoreAntiforgeryToken]
public IActionResult IndexOverride()
{
// ...
return RedirectToAction();
}
Aktualizace tokenů po ověření
Tokeny by se měly aktualizovat po ověření uživatele přesměrováním uživatele na stránku zobrazení nebo Razor stránky.
JavaScript, AJAX a SPA
V tradičních aplikacích založených na HTML se antiforgery tokeny předávají serveru pomocí skrytých polí formuláře. V moderních aplikacích založených na JavaScriptu a SA se mnoho požadavků provádí programově. Tyto požadavky AJAX mohou k odeslání tokenu použít jiné techniky (například hlavičky požadavku nebo soubory cookie).
Pokud se soubory cookie používají k ukládání ověřovacích tokenů a k ověřování požadavků rozhraní API na serveru, je csrF potenciálním problémem. Pokud se k uložení tokenu používá místní úložiště, může se zmírnit ohrožení zabezpečení CSRF, protože hodnoty z místního úložiště se na server neodesílají automaticky s každou žádostí. Použití místního úložiště k uložení anti-forgery tokenu na klientovi a odeslání tokenu hlavičkou požadavku je doporučený postup.
JavaScript
Pomocí JavaScriptu se zobrazeními lze token vytvořit pomocí služby v zobrazení. IAntiforgery Vložte službu do zobrazení a zavolejteGetAndStoreTokens:
@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>
}
Předchozí příklad používá JavaScript ke čtení skryté hodnoty pole hlavičky AJAX POST.
Tento přístup eliminuje nutnost zabývat se přímo nastavením souborů cookie ze serveru nebo jejich čtením z klienta. Pokud však vložení IAntiforgery služby není možné, použijte JavaScript pro přístup k tokenům v souborech cookie:
- Přístupové tokeny v dalším požadavku na server, obvykle
same-origin. - Použijte obsah cookie k vytvoření hlavičky s hodnotou tokenu.
Za předpokladu, že skript odešle token v hlavičce požadavku s názvem X-XSRF-TOKEN, nakonfigurujte službu antiforgery tak, aby hledala hlavičku X-XSRF-TOKEN :
builder.Services.AddAntiforgery(options => options.HeaderName = "X-XSRF-TOKEN");
Následující příklad přidá chráněný koncový bod, který zapíše token požadavku do javascriptově čitelného cookiekódu:
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();
Následující příklad používá JavaScript k vytvoření požadavku AJAX na získání tokenu a provedení dalšího požadavku s příslušnou hlavičkou:
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}`
}
Poznámka:
Pokud je token antiforgery zadaný v hlavičce požadavku i v datové části formuláře, ověří se pouze token v hlavičce.
Ochrana proti padělání s minimálními rozhraními API
Minimal APIsnepodporuje použití zahrnutých filtrů (ValidateAntiForgeryTokenAutoValidateAntiforgeryToken, , IgnoreAntiforgeryToken), IAntiforgery ale poskytuje požadovaná rozhraní API k ověření požadavku.
Následující příklad vytvoří filtr, který ověří token antiforgery:
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);
});
}
}
Filtr se pak dá použít na koncový bod:
app.MapPost("api/upload", (IFormFile name) => Results.Accepted())
.RequireAuthorization()
.ValidateAntiforgery();
Ověřování systému Windows a antiforgery cookies
Při použití ověřování systému Windows musí být koncové body aplikací chráněné proti útokům CSRF stejným způsobem jako u souborů cookie. Prohlížeč implicitně odesílá kontext ověřování na server a koncové body, které musí být chráněné před útoky CSRF.
Rozšířit antifalšování
Tento IAntiforgeryAdditionalDataProvider typ umožňuje vývojářům rozšířit chování systému anti-CSRF tím, že v každém tokenu přetáhne další data. Metoda GetAdditionalData se volá při každém vygenerování tokenu pole a návratová hodnota se vloží do vygenerovaného tokenu. Implementátor by mohl vrátit časové razítko, náhodné číslo nebo jinou hodnotu a potom zavolat ValidateAdditionalData k ověření těchto dat, když se token ověřuje. Uživatelské jméno klienta je již vloženo do vygenerovaných tokenů, takže tyto informace nemusíte obsahovat. Pokud token obsahuje doplňková data, ale není nakonfigurovaná žádná IAntiForgeryAdditionalDataProvider , doplňková data se neověřují.
Další materiály
Padělání požadavků mezi weby (označované také jako XSRF nebo CSRF) je útok na aplikace hostované na webu, kdy škodlivá webová aplikace může ovlivnit interakci mezi klientským prohlížečem a webovou aplikací, která důvěřuje danému prohlížeči. Tyto útoky jsou možné, protože webové prohlížeče automaticky odesílají některé typy ověřovacích tokenů s každou žádostí na web. Tato forma zneužití se také označuje jako jednoklikový útok nebo únos relace, protože útok využívá dříve ověřenou relaci uživatele.
Příklad útoku CSRF:
Uživatel se přihlásí k
www.good-banking-site.example.compomocí ověření formulářem. Server ověřuje uživatele a vydává odpověď, která zahrnuje ověřování cookie. Web je zranitelný vůči útoku, protože důvěřuje všem požadavkem, který obdrží s platným ověřováním cookie.Uživatel navštíví škodlivý web.
www.bad-crook-site.example.comŠkodlivý web obsahuje
www.bad-crook-site.example.comformulář HTML podobný následujícímu příkladu:<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>Všimněte si, že formulář
actionodesílá na ohrožený web, nikoli na škodlivý web. Toto je "cross-site" část CSRF.Uživatel vybere tlačítko Odeslat. Prohlížeč vytvoří požadavek a automaticky zahrne ověřování cookie pro požadovanou doménu.
www.good-banking-site.example.comPožadavek se spustí na
www.good-banking-site.example.comserveru s kontextem ověřování uživatele a může provést jakoukoli akci, kterou může ověřený uživatel provést.
Kromě scénáře, ve kterém uživatel vybere tlačítko pro odeslání formuláře, může škodlivý web:
- Spusťte skript, který automaticky odešle formulář.
- Odešlete formulář jako požadavek AJAX.
- Skryjte formulář pomocí šablon stylů CSS.
Tyto alternativní scénáře nevyžadují žádnou akci ani vstup od jiného uživatele, než je počáteční návštěva škodlivého webu.
Použití PROTOKOLU HTTPS nezabrání útoku CSRF. Škodlivý web může odeslat https://www.good-banking-site.example.com/ požadavek stejně snadno, jako by mohl odeslat nezabezpečený požadavek.
Některé útoky cílí na koncové body, které reagují na požadavky GET, v takovém případě lze použít značku image k provedení akce. Tato forma útoku je běžná na webech fóra, které umožňují obrázky, ale blokují JavaScript. Aplikace, které mění stav požadavků GET, kde se mění proměnné nebo prostředky, jsou zranitelné vůči škodlivým útokům. Požadavky GET, které změní stav, jsou nezabezpečené. Osvědčeným postupem je nikdy změnit stav požadavku GET.
Útoky CSRF jsou možné vůči webovým aplikacím, které k ověřování používají soubory cookie, protože:
- Prohlížeče ukládají soubory cookie vydané webovou aplikací.
- Uložené soubory cookie obsahují soubory cookie relace pro ověřené uživatele.
- Prohlížeče odesílají všechny soubory cookie přidružené k doméně do webové aplikace bez ohledu na to, jak se požadavek na aplikaci vygeneroval v prohlížeči.
Útoky CSRF ale nejsou omezené na zneužití souborů cookie. Například základní ověřování a ověřování pomocí digest je také ohroženo. Jakmile se uživatel přihlásí pomocí ověřování Basic nebo Digest, prohlížeč automaticky odešle přihlašovací údaje, dokud relace neskončí.
V tomto kontextu relace odkazuje na relaci na straně klienta, ve které je uživatel ověřen. Nesouvisí to se serverovými relacemi ani s middlewarem relací ASP.NET Core.
Uživatelé mohou chránit před ohroženími zabezpečení CSRF pomocí bezpečnostních opatření:
- Po dokončení se odhlaste z webových aplikací.
- Pravidelně vymažte soubory cookie prohlížeče.
Ohrožení zabezpečení CSRF jsou ale v zásadě problém s webovou aplikací, nikoli koncovým uživatelem.
Základy ověřování
Cookie-založené ověřování je oblíbenou formou ověřování. Systémy ověřování založené na tokenech jsou stále oblíbenější, zejména pro jednostráňové aplikace (SPA).
Cookie-založené ověřování
Když se uživatel ověří pomocí uživatelského jména a hesla, vydá token obsahující ověřovací lístek, který se dá použít k ověřování a autorizaci. Token se uloží jako cookie odesílaný s každým požadavkem, který klient provede. Generování a ověřování tohoto cookie provádí middleware pro ověřování cookie. Middleware serializuje uživatelský principál do zašifrovaného cookie. V následných požadavcích middleware ověří cookie, znovu vytvoří hlavní objekt a přiřadí tento hlavní objekt k vlastnosti HttpContext.User.
Ověřování na základě tokenů
Když je uživatel ověřen, obdrží token, nikoli antiforgery token. Token obsahuje informace o uživateli ve formě deklarací identity nebo referenčního tokenu, který odkazuje aplikaci na stav uživatele udržovaný v aplikaci. Když se uživatel pokusí získat přístup k prostředku, který vyžaduje ověření, token se odešle do aplikace s extra autorizační hlavičkou ve formě tokenu Bearer . Díky tomuto přístupu je aplikace bezstavová. V každém dalším požadavku se token předá v požadavku na ověření na straně serveru. Tento token není šifrovaný, je zakódovaný. Na serveru je token dekódován pro přístup k jeho informacím. Pokud chcete token odeslat při dalších požadavcích, uložte ho do místního úložiště prohlížeče. Nedělejte si starosti s ohrožením zabezpečení CSRF, pokud je token uložený v místním úložišti prohlížeče. CSRF je riziko, když je token uložen v cookie. Další informace najdete v problému GitHubu SPA code sample adds two cookies.
Více aplikací hostovaných v jedné doméně
Sdílená hostitelská prostředí jsou zranitelná vůči únosu relace, CSRF útokům na přihlašování a dalším útokům.
I když example1.contoso.net a example2.contoso.net jsou různí hostitelé, existuje implicitní vztah důvěryhodnosti mezi hostiteli v rámci *.contoso.net domény. Tento implicitní vztah důvěryhodnosti umožňuje potenciálně nedůvěryhodným hostitelům ovlivnit soubory cookie ostatních (zásady stejného původu, které řídí požadavky AJAX, se nemusí nutně vztahovat na soubory cookie HTTP).
Útoky, které zneužívají důvěryhodné soubory cookie mezi aplikacemi hostovanými ve stejné doméně, je možné zabránit tím, že nesdílí domény. Když je každá aplikace hostovaná ve vlastní doméně, neexistuje žádný implicitní cookie vztah důvěryhodnosti, který by bylo potřeba zneužít.
Antiforgery v ASP.NET Core
Upozornění
ASP.NET Core implementuje antiforgery pomocí ASP.NET Core Data Protection. Zásobník ochrany dat musí být nakonfigurovaný tak, aby fungoval v serverové farmě. Další informace najdete v tématu Konfigurace ochrany dat.
Do kontejneru vkládání závislostí se middleware antiforgery přidá, když je voláno některé z následujících API rozhraní Program.cs:
FormTagHelper vkládá do prvků formulářů HTML tokeny proti padělkům. Následující kód v Razor souboru automaticky generuje antiforgery tokeny:
<form method="post">
<!-- ... -->
</form>
Podobně IHtmlHelper.BeginForm ve výchozím nastavení generuje antiforgery tokeny, pokud metoda formuláře není GET.
Automatické generování tokenů antiforgery pro elementy formuláře HTML nastane, když <form> značka obsahuje method="post" atribut a některé z následujících hodnot jsou pravdivé:
- Atribut akce je prázdný (
action=""). - Atribut akce není zadán (
<form method="post">).
Automatické generování antiforgerických tokenů pro elementy formuláře HTML lze zakázat:
Explicitně zakažte antiforgery tokeny s atributem
asp-antiforgery:<form method="post" asp-antiforgery="false"> <!-- ... --> </form>Prvek formuláře je vyloučen z pomocníků značek pomocí symbolu ! opt-out symbol:
<!form method="post"> <!-- ... --> </!form>Odeberte
FormTagHelperze zobrazení.FormTagHelperlze ze zobrazení odebrat přidáním následující direktivy do Razor zobrazení.@removeTagHelper Microsoft.AspNetCore.Mvc.TagHelpers.FormTagHelper, Microsoft.AspNetCore.Mvc.TagHelpers
Poznámka:
Razor Stránky jsou automaticky chráněny před XSRF/CSRF. Další informace najdete v tématu XSRF/CSRF a Razor Pages.
Nejběžnějším přístupem k ochraně před útoky CSRF je použití vzoru tokenů synchronizátoru (STP). STP se používá, když uživatel požádá o stránku s daty formuláře:
- Server odešle klientovi token přidružený k identitě aktuálního uživatele.
- Klient odešle token zpět na server k ověření.
- Pokud server obdrží token, který neodpovídá identitě ověřeného uživatele, žádost se odmítne.
Token je jedinečný a nepředvídatelný. Token lze použít také k zajištění správného sekvencování řady požadavků (například k zajištění pořadí požadavků na stránce 1 > strana 2 > strana 3). Všechny formuláře v šablonách ASP.NET Core MVC a Razor Pages generují antiforgery tokeny. Následující dvojice příkladů zobrazení generuje antiforgery tokeny:
<form asp-action="Index" asp-controller="Home" method="post">
<!-- ... -->
</form>
@using (Html.BeginForm("Index", "Home"))
{
<!-- ... -->
}
Explicitně přidejte antiforgery token do prvku <form> bez použití značkového pomocníka s pomocnou rutinou HTML @Html.AntiForgeryToken:
<form asp-action="Index" asp-controller="Home" method="post">
@Html.AntiForgeryToken()
<!-- ... -->
</form>
V každém z předchozích případů ASP.NET Core přidá skryté pole formuláře podobné následujícímu příkladu:
<input name="__RequestVerificationToken" type="hidden" value="CfDJ8NrAkS ... s2-m9Yw">
ASP.NET Core obsahuje tři filtry pro práci s antiforgery tokeny:
Ochrana proti padělání s AddControllers
Volání AddControllers neaktivuje antiforgery tokeny. AddControllersWithViews musí být volána, aby byla podporována integrovaná antiforgery token.
Více karet prohlížeče a vzor synchronizačního tokenu
Pouze naposledy načtená stránka obsahuje platný token proti padělání dle vzoru Synchronizer Token. Použití více karet může být problematické. Pokud například uživatel otevře více karet:
- Pouze naposledy načtená záložka obsahuje platný token proti padělání.
- Požadavky provedené z dříve načtených záložek selžou s chybou:
Antiforgery token validation failed. The antiforgery cookie token and request token do not match
Pokud se jedná o problém, zvažte alternativní vzory ochrany CSRF.
Nakonfigurujte antiforgery pomocí AntiforgeryOptions
Přizpůsobte AntiforgeryOptions v souboru Program aplikace:
builder.Services.AddAntiforgery(options =>
{
// Set Cookie properties using CookieBuilder properties†.
options.FormFieldName = "AntiforgeryFieldname";
options.HeaderName = "X-CSRF-TOKEN-HEADERNAME";
options.SuppressXFrameOptionsHeader = false;
});
Nastavte vlastnosti antiforgery cookie pomocí vlastností CookieBuilder třídy, jak je uvedeno v následující tabulce.
| Možnost | Popis |
|---|---|
| Cookie | Určuje nastavení použitá k vytvoření ochranných cookies. |
| FormFieldName | Název skrytého pole formuláře používaného systémem antiforgery pro vykreslení tokenů antiforgery v zobrazeních. |
| HeaderName | Název hlavičky používané systémem antiforgery. Pokud null, systém považuje pouze data formuláře. |
| SuppressXFrameOptionsHeader | Určuje, jestli se má potlačit generování hlavičky X-Frame-Options . Ve výchozím nastavení se hlavička vygeneruje s hodnotou SAMEORIGIN. Výchozí hodnota je false. |
Některé prohlížeče neumožňují nezabezpečeným koncovým bodům nastavit soubory cookie s příznakem "secure" nebo přepsat soubory cookie, jejichž je nastavený příznak secure (další informace najdete v tématu Vyřazení změn zabezpečených souborů cookie z nezabezpečených zdrojů). Vzhledem k tomu, že kombinování zabezpečených a nezabezpečených koncových bodů je běžným scénářem v aplikacích, ASP.NET Core zmírňuje omezení zásad zabezpečení u některých souborů cookie, jako například u antiforgery cookie, tím, že nastavuje atribut cookie souboru SecurePolicy na hodnotu CookieSecurePolicy.None. Kdyby uživatel se zlými úmysly ukradl antiforgery cookie, musí také ukrást antiforgery token, který je obvykle odeslán prostřednictvím pole formuláře (běžnější) nebo samostatné hlavičky požadavku (méně běžné) plus autentizaci cookie.
Cookies související s ověřováním nebo autorizací používají silnější zásady než CookieSecurePolicy.None.
Volitelně můžete antiforgery cookie zabezpečit v jinýchDevelopment prostředích pomocí protokolu SSL (Secure Sockets Layer) pouze přes PROTOKOL HTTPS s následujícím AntiforgeryOptions.Cookie nastavením vlastnosti v souboru aplikace Program :
if (!builder.Environment.IsDevelopment())
{
builder.Services.AddAntiforgery(o =>
{
o.Cookie.SecurePolicy = CookieSecurePolicy.Always;
});
}
Další informace najdete na webu CookieAuthenticationOptions.
Generování antiforgery tokenů pomocí IAntiforgery
IAntiforgery poskytuje rozhraní API ke konfiguraci funkcí proti padělání.
IAntiforgery lze požádat v Program.cs pomocí WebApplication.Services. Následující příklad používá middleware z domovské stránky aplikace k vygenerování antiforgery tokenu a jeho odeslání v odpovědi jako 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);
});
Předchozí příklad nastaví cookie s názvem XSRF-TOKEN. Klient si to cookie může přečíst a zadat jeho hodnotu jako hlavičku připojenou k žádostem AJAX. Angular například obsahuje integrovanou ochranu XSRF, která ve výchozím nastavení čte pojmenovaný cookie.
Vyžadovat ověření proti padělání
Filtr akcí ValidateAntiForgeryToken lze použít u jednotlivé akce, kontroleru nebo globálně. Požadavky provedené na akce, které mají tento filtr použitý, jsou blokované, pokud požadavek neobsahuje platný antiforgery token:
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Index()
{
// ...
return RedirectToAction();
}
Atribut ValidateAntiForgeryToken vyžaduje token pro požadavky na metody akce, které označí, včetně požadavků HTTP GET. Pokud se atribut ValidateAntiForgeryToken použije na kontrolery aplikace, můžete ho přepsat pomocí atributu IgnoreAntiforgeryToken.
Automatické ověření tokenů antiforgery pouze pro nebezpečné metody HTTP
Místo široké aplikace atributu ValidateAntiForgeryToken a jeho přepsání pomocí atributů IgnoreAntiforgeryToken lze použít atribut AutoValidateAntiforgeryToken. Tento atribut funguje stejně jako ValidateAntiForgeryToken atribut s tím rozdílem, že nevyžaduje tokeny pro požadavky provedené pomocí následujících metod HTTP:
- GET
- Hlavička
- MOŽNOSTI
- TRACE
Pro scénáře, které nepoužívají rozhraní API, doporučujeme používat AutoValidateAntiforgeryToken široce. Tento atribut zajišťuje, že akce POST jsou ve výchozím nastavení chráněné. Alternativou je ignorovat antiforgery tokeny ve výchozím nastavení, pokud ValidateAntiForgeryToken není použita u jednotlivých metod akcí. V tomto scénáři je pravděpodobnější, že metoda akce POST zůstane nechráněná omylem, takže aplikace bude zranitelná vůči útokům CSRF. Všechny POSTy by měly odesílat antiforgery token.
Rozhraní API nemají automatický způsob odeslání části tokenu bez cookie. Implementace pravděpodobně závisí na implementaci klientského kódu. Tady je několik příkladů:
Příklad na úrovni třídy:
[AutoValidateAntiforgeryToken]
public class HomeController : Controller
Globální příklad:
builder.Services.AddControllersWithViews(options =>
{
options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute());
});
Přepsání atributů antiforgery globálního serveru nebo kontroleru
Filtr IgnoreAntiforgeryToken se používá k odstranění potřeby tokenu antiforgery pro danou akci (nebo kontroler). Při použití tento filtr přepíše filtry ValidateAntiForgeryToken a AutoValidateAntiforgeryToken zadané na vyšší úrovni (globálně nebo na řadiči).
[IgnoreAntiforgeryToken]
public IActionResult IndexOverride()
{
// ...
return RedirectToAction();
}
Aktualizace tokenů po ověření
Tokeny by se měly aktualizovat po ověření uživatele přesměrováním uživatele na stránku zobrazení nebo Razor stránky.
JavaScript, AJAX a SPA
V tradičních aplikacích založených na HTML se antiforgery tokeny předávají serveru pomocí skrytých polí formuláře. V moderních aplikacích založených na JavaScriptu a SA se mnoho požadavků provádí programově. Tyto požadavky AJAX mohou k odeslání tokenu použít jiné techniky (například hlavičky požadavku nebo soubory cookie).
Pokud se soubory cookie používají k ukládání ověřovacích tokenů a k ověřování požadavků rozhraní API na serveru, je csrF potenciálním problémem. Pokud se k uložení tokenu používá místní úložiště, může se zmírnit ohrožení zabezpečení CSRF, protože hodnoty z místního úložiště se na server neodesílají automaticky s každou žádostí. Použití místního úložiště k uložení anti-forgery tokenu na klientovi a odeslání tokenu hlavičkou požadavku je doporučený postup.
JavaScript
Pomocí JavaScriptu se zobrazeními lze token vytvořit pomocí služby v zobrazení. IAntiforgery Vložte službu do zobrazení a zavolejteGetAndStoreTokens:
@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>
}
Předchozí příklad používá JavaScript ke čtení skryté hodnoty pole hlavičky AJAX POST.
Tento přístup eliminuje nutnost zabývat se přímo nastavením souborů cookie ze serveru nebo jejich čtením z klienta. Pokud však vložení IAntiforgery služby není možné, JavaScript může také přistupovat k tokenu v souborech cookie, který se získá z dalšího požadavku na server (obvykle same-origin) a pomocí cookieobsahu tokenu vytvořit hlavičku s hodnotou tokenu.
Za předpokladu, že skript odešle token v hlavičce požadavku s názvem X-XSRF-TOKEN, nakonfigurujte službu antiforgery tak, aby hledala hlavičku X-XSRF-TOKEN :
builder.Services.AddAntiforgery(options => options.HeaderName = "X-XSRF-TOKEN");
Následující příklad přidá chráněný koncový bod, který zapíše token požadavku do JavaScriptu čitelného 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();
Následující příklad používá JavaScript k vytvoření požadavku AJAX na získání tokenu a provedení dalšího požadavku s příslušnou hlavičkou:
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}`
}
Ověřování systému Windows a antiforgery cookies
Při použití ověřování systému Windows musí být koncové body aplikací chráněné proti útokům CSRF stejným způsobem jako u souborů cookie. Prohlížeč implicitně odesílá kontext ověřování na server, takže koncové body musí být chráněné před útoky CSRF.
Rozšířit antifalšování
Tento IAntiforgeryAdditionalDataProvider typ umožňuje vývojářům rozšířit chování systému anti-CSRF tím, že v každém tokenu přetáhne další data. Metoda GetAdditionalData se volá při každém vygenerování tokenu pole a návratová hodnota se vloží do vygenerovaného tokenu. Implementátor by mohl vrátit časové razítko, náhodné číslo nebo jinou hodnotu a potom zavolat ValidateAdditionalData k ověření těchto dat, když se token ověřuje. Uživatelské jméno klienta je již vloženo do vygenerovaných tokenů, takže tyto informace nemusíte obsahovat. Pokud token obsahuje doplňková data, ale není nakonfigurovaná žádná IAntiForgeryAdditionalDataProvider , doplňková data se neověřují.
Další materiály
Padělání požadavků mezi weby (označované také jako XSRF nebo CSRF) je útok na aplikace hostované na webu, kdy škodlivá webová aplikace může ovlivnit interakci mezi klientským prohlížečem a webovou aplikací, která důvěřuje danému prohlížeči. Tyto útoky jsou možné, protože webové prohlížeče automaticky odesílají některé typy ověřovacích tokenů s každou žádostí na web. Tato forma zneužití se také označuje jako jednoklikový útok nebo únos relace, protože útok využívá dříve ověřenou relaci uživatele.
Příklad útoku CSRF:
Uživatel se přihlásí k
www.good-banking-site.example.compomocí ověření formulářem. Server ověřuje uživatele a vydává odpověď, která zahrnuje ověřování cookie. Web je zranitelný vůči útoku, protože důvěřuje všem požadavkem, který obdrží s platným ověřováním cookie.Uživatel navštíví škodlivý web.
www.bad-crook-site.example.comŠkodlivý web obsahuje
www.bad-crook-site.example.comformulář HTML podobný následujícímu příkladu:<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>Všimněte si, že formulář
actionodesílá na ohrožený web, nikoli na škodlivý web. Toto je "cross-site" část CSRF.Uživatel vybere tlačítko Odeslat. Prohlížeč vytvoří požadavek a automaticky zahrne ověřování cookie pro požadovanou doménu.
www.good-banking-site.example.comPožadavek se spustí na
www.good-banking-site.example.comserveru s kontextem ověřování uživatele a může provést jakoukoli akci, kterou může ověřený uživatel provést.
Kromě scénáře, ve kterém uživatel vybere tlačítko pro odeslání formuláře, může škodlivý web:
- Spusťte skript, který automaticky odešle formulář.
- Odešlete formulář jako požadavek AJAX.
- Skryjte formulář pomocí šablon stylů CSS.
Tyto alternativní scénáře nevyžadují žádnou akci ani vstup od jiného uživatele, než je počáteční návštěva škodlivého webu.
Použití PROTOKOLU HTTPS nezabrání útoku CSRF. Škodlivý web může odeslat https://www.good-banking-site.example.com/ požadavek stejně snadno, jako by mohl odeslat nezabezpečený požadavek.
Některé útoky cílí na koncové body, které reagují na požadavky GET, v takovém případě lze použít značku image k provedení akce. Tato forma útoku je běžná na webech fóra, které umožňují obrázky, ale blokují JavaScript. Aplikace, které mění stav požadavků GET, kde se mění proměnné nebo prostředky, jsou zranitelné vůči škodlivým útokům. Požadavky GET, které změní stav, jsou nezabezpečené. Osvědčeným postupem je nikdy změnit stav požadavku GET.
Útoky CSRF jsou možné vůči webovým aplikacím, které k ověřování používají soubory cookie, protože:
- Prohlížeče ukládají soubory cookie vydané webovou aplikací.
- Uložené soubory cookie obsahují soubory cookie relace pro ověřené uživatele.
- Prohlížeče odesílají všechny soubory cookie přidružené k doméně do webové aplikace bez ohledu na to, jak se požadavek na aplikaci vygeneroval v prohlížeči.
Útoky CSRF ale nejsou omezené na zneužití souborů cookie. Například základní ověřování a ověřování pomocí digest je také ohroženo. Jakmile se uživatel přihlásí pomocí ověřování Basic nebo Digest, prohlížeč automaticky odešle přihlašovací údaje, dokud relace neskončí.
V tomto kontextu relace odkazuje na relaci na straně klienta, ve které je uživatel ověřen. Nesouvisí to se serverovými relacemi ani s middlewarem relací ASP.NET Core.
Uživatelé mohou chránit před ohroženími zabezpečení CSRF pomocí bezpečnostních opatření:
- Po dokončení se odhlaste z webových aplikací.
- Pravidelně vymažte soubory cookie prohlížeče.
Ohrožení zabezpečení CSRF jsou ale v zásadě problém s webovou aplikací, nikoli koncovým uživatelem.
Základy ověřování
Cookie-založené ověřování je oblíbenou formou ověřování. Systémy ověřování založené na tokenech jsou stále oblíbenější, zejména pro jednostráňové aplikace (SPA).
Cookie-založené ověřování
Když se uživatel ověří pomocí uživatelského jména a hesla, vydá token obsahující ověřovací lístek, který se dá použít k ověřování a autorizaci. Token se uloží jako cookie odesílaný s každým požadavkem, který klient provede. Generování a ověřování tohoto cookie provádí middleware pro ověřování cookie. Middleware serializuje uživatelský principál do zašifrovaného cookie. V následných požadavcích middleware ověří cookie, znovu vytvoří hlavní objekt a přiřadí tento hlavní objekt k vlastnosti HttpContext.User.
Ověřování na základě tokenů
Když je uživatel ověřen, obdrží token, nikoli antiforgery token. Token obsahuje informace o uživateli ve formě deklarací identity nebo referenčního tokenu, který odkazuje aplikaci na stav uživatele udržovaný v aplikaci. Když se uživatel pokusí získat přístup k prostředku, který vyžaduje ověření, token se odešle do aplikace s extra autorizační hlavičkou ve formě tokenu Bearer . Díky tomuto přístupu je aplikace bezstavová. V každém dalším požadavku se token předá v požadavku na ověření na straně serveru. Tento token není šifrovaný, je zakódovaný. Na serveru je token dekódován pro přístup k jeho informacím. Pokud chcete token odeslat při dalších požadavcích, uložte ho do místního úložiště prohlížeče. Nedělejte si starosti s ohrožením zabezpečení CSRF, pokud je token uložený v místním úložišti prohlížeče. CSRF je riziko, když je token uložen v cookie. Další informace najdete v problému GitHubu SPA code sample adds two cookies.
Více aplikací hostovaných v jedné doméně
Sdílená hostitelská prostředí jsou zranitelná vůči únosu relace, CSRF útokům na přihlašování a dalším útokům.
I když example1.contoso.net a example2.contoso.net jsou různí hostitelé, existuje implicitní vztah důvěryhodnosti mezi hostiteli v rámci *.contoso.net domény. Tento implicitní vztah důvěryhodnosti umožňuje potenciálně nedůvěryhodným hostitelům ovlivnit soubory cookie ostatních (zásady stejného původu, které řídí požadavky AJAX, se nemusí nutně vztahovat na soubory cookie HTTP).
Útoky, které zneužívají důvěryhodné soubory cookie mezi aplikacemi hostovanými ve stejné doméně, je možné zabránit tím, že nesdílí domény. Když je každá aplikace hostovaná ve vlastní doméně, neexistuje žádný implicitní cookie vztah důvěryhodnosti, který by bylo potřeba zneužít.
Konfigurace antiforgery v ASP.NET Core
Upozornění
ASP.NET Core implementuje antiforgery pomocí ASP.NET Core Data Protection. Zásobník ochrany dat musí být nakonfigurovaný tak, aby fungoval v serverové farmě. Další informace najdete v tématu Konfigurace ochrany dat.
Do kontejneru vkládání závislostí se middleware antiforgery přidá, když je voláno některé z následujících API rozhraní Startup.ConfigureServices:
V ASP.NET Core 2.0 nebo novější FormTagHelper vloží antiforgery tokeny do HTML formulářových elementů. Následující kód v Razor souboru automaticky generuje antiforgery tokeny:
<form method="post">
...
</form>
Podobně IHtmlHelper.BeginForm ve výchozím nastavení generuje antiforgery tokeny, pokud metoda formuláře není GET.
Automatické generování tokenů antiforgery pro elementy formuláře HTML nastane, když <form> značka obsahuje method="post" atribut a některé z následujících hodnot jsou pravdivé:
- Atribut akce je prázdný (
action=""). - Atribut akce není zadán (
<form method="post">).
Automatické generování antiforgerických tokenů pro elementy formuláře HTML lze zakázat:
Explicitně zakažte antiforgery tokeny s atributem
asp-antiforgery:<form method="post" asp-antiforgery="false"> ... </form>Prvek formuláře je vyloučen z pomocníků značek pomocí symbolu ! opt-out symbol:
<!form method="post"> ... </!form>Odeberte
FormTagHelperze zobrazení.FormTagHelperlze ze zobrazení odebrat přidáním následující direktivy do Razor zobrazení.@removeTagHelper Microsoft.AspNetCore.Mvc.TagHelpers.FormTagHelper, Microsoft.AspNetCore.Mvc.TagHelpers
Poznámka:
Razor Stránky jsou automaticky chráněny před XSRF/CSRF. Další informace najdete v tématu XSRF/CSRF a Razor Pages.
Nejběžnějším přístupem k ochraně před útoky CSRF je použití vzoru tokenů synchronizátoru (STP). STP se používá, když uživatel požádá o stránku s daty formuláře:
- Server odešle klientovi token přidružený k identitě aktuálního uživatele.
- Klient odešle token zpět na server k ověření.
- Pokud server obdrží token, který neodpovídá identitě ověřeného uživatele, žádost se odmítne.
Token je jedinečný a nepředvídatelný. Token lze použít také k zajištění správného sekvencování řady požadavků (například k zajištění pořadí požadavků na stránce 1 > strana 2 > strana 3). Všechny formuláře v šablonách ASP.NET Core MVC a Razor Pages generují antiforgery tokeny. Následující dvojice příkladů zobrazení generuje antiforgery tokeny:
<form asp-controller="Todo" asp-action="Create" method="post">
...
</form>
@using (Html.BeginForm("Create", "Todo"))
{
...
}
Explicitně přidejte antiforgery token do prvku <form> bez použití značkového pomocníka s pomocnou rutinou HTML @Html.AntiForgeryToken:
<form action="/" method="post">
@Html.AntiForgeryToken()
</form>
V každém z předchozích případů ASP.NET Core přidá skryté pole formuláře podobné následujícímu příkladu:
<input name="__RequestVerificationToken" type="hidden" value="CfDJ8NrAkS ... s2-m9Yw">
ASP.NET Core obsahuje tři filtry pro práci s antiforgery tokeny:
Možnosti ochrany proti padělání
Přizpůsobit AntiforgeryOptions v Startup.ConfigureServices:
services.AddAntiforgery(options =>
{
options.FormFieldName = "AntiforgeryFieldname";
options.HeaderName = "X-CSRF-TOKEN-HEADERNAME";
options.SuppressXFrameOptionsHeader = false;
});
Nastavte vlastnosti antiforgery cookie pomocí vlastností CookieBuilder třídy, jak je uvedeno v následující tabulce.
| Možnost | Popis |
|---|---|
| Cookie | Určuje nastavení použitá k vytvoření ochranných cookies. |
| FormFieldName | Název skrytého pole formuláře používaného systémem antiforgery pro vykreslení tokenů antiforgery v zobrazeních. |
| HeaderName | Název hlavičky používané systémem antiforgery. Pokud null, systém považuje pouze data formuláře. |
| SuppressXFrameOptionsHeader | Určuje, jestli se má potlačit generování hlavičky X-Frame-Options . Ve výchozím nastavení se hlavička vygeneruje s hodnotou SAMEORIGIN. Výchozí hodnota je false. |
Některé prohlížeče neumožňují nezabezpečeným koncovým bodům nastavit soubory cookie s příznakem "secure" nebo přepsat soubory cookie, jejichž je nastavený příznak secure (další informace najdete v tématu Vyřazení změn zabezpečených souborů cookie z nezabezpečených zdrojů). Vzhledem k tomu, že kombinování zabezpečených a nezabezpečených koncových bodů je běžným scénářem v aplikacích, ASP.NET Core zmírňuje omezení zásad zabezpečení u některých souborů cookie, jako například u antiforgery cookie, tím, že nastavuje atribut cookie souboru SecurePolicy na hodnotu CookieSecurePolicy.None. Kdyby uživatel se zlými úmysly ukradl antiforgery cookie, musí také ukrást antiforgery token, který je obvykle odeslán prostřednictvím pole formuláře (běžnější) nebo samostatné hlavičky požadavku (méně běžné) plus autentizaci cookie.
Cookies související s ověřováním nebo autorizací používají silnější zásady než CookieSecurePolicy.None.
Volitelně můžete antiforgery cookie zabezpečit v ne-Development prostředích pomocí protokolu SSL (Secure Sockets Layer) pouze přes protokol HTTPS s následujícím AntiforgeryOptions.Cookie nastavením vlastnosti ve třídě aplikace Startup:
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
}
}
Další informace najdete na webu CookieAuthenticationOptions.
Konfigurace funkcí ochrany proti falšování pomocí IAntiforgery
IAntiforgery poskytuje rozhraní API ke konfiguraci funkcí proti padělání.
IAntiforgery lze požadovat v Configure metodě Startup třídy.
V následujícím příkladu:
- Middleware z domovské stránky aplikace se používá k tomu, aby vygenerovalo antiforgery token a odeslalo ho v odpovědi jako cookie.
- Token požadavku se odešle jako prvek čitelný v JavaScriptu cookie s výchozí konvencí pojmenování Angular popsannou v části 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);
});
}
Vyžadovat ověření proti padělání
ValidateAntiForgeryToken je filtr akcí, který lze použít u jednotlivé akce, kontroleru nebo globálně. Požadavky provedené u akcí, které mají tento filtr aplikovaný, jsou blokovány, pokud požadavek neobsahuje platný antiforgery token.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> RemoveLogin(RemoveLoginViewModel account)
{
ManageMessageId? message = ManageMessageId.Error;
var user = await GetCurrentUserAsync();
if (user != null)
{
var result =
await _userManager.RemoveLoginAsync(
user, account.LoginProvider, account.ProviderKey);
if (result.Succeeded)
{
await _signInManager.SignInAsync(user, isPersistent: false);
message = ManageMessageId.RemoveLoginSuccess;
}
}
return RedirectToAction(nameof(ManageLogins), new { Message = message });
}
Atribut ValidateAntiForgeryToken vyžaduje token pro požadavky na metody akce, které označí, včetně požadavků HTTP GET. Pokud se atribut ValidateAntiForgeryToken použije na kontrolery aplikace, můžete ho přepsat pomocí atributu IgnoreAntiforgeryToken.
Poznámka:
ASP.NET Core nepodporuje automatické přidávání antiforgery tokenů do požadavků GET.
Automatické ověření tokenů antiforgery pouze pro nebezpečné metody HTTP
ASP.NET aplikace Core negenerují antiforgery tokeny pro bezpečné metody HTTP (GET, HEAD, OPTIONS a TRACE). Místo široké aplikace atributu ValidateAntiForgeryToken a jeho přepsání pomocí atributů IgnoreAntiforgeryToken lze použít atribut AutoValidateAntiforgeryToken. Tento atribut funguje stejně jako ValidateAntiForgeryToken atribut s tím rozdílem, že nevyžaduje tokeny pro požadavky provedené pomocí následujících metod HTTP:
- GET
- Hlavička
- MOŽNOSTI
- TRACE
Pro scénáře, které nepoužívají rozhraní API, doporučujeme používat AutoValidateAntiforgeryToken široce. Tento atribut zajišťuje, že akce POST jsou ve výchozím nastavení chráněné. Alternativou je ignorovat antiforgery tokeny ve výchozím nastavení, pokud ValidateAntiForgeryToken není použita u jednotlivých metod akcí. V tomto scénáři je pravděpodobnější, že metoda akce POST zůstane nechráněná omylem, takže aplikace bude zranitelná vůči útokům CSRF. Všechny POSTy by měly odesílat antiforgery token.
Rozhraní API nemají automatický způsob odeslání části tokenu bez cookie. Implementace pravděpodobně závisí na implementaci klientského kódu. Tady je několik příkladů:
Příklad na úrovni třídy:
[Authorize]
[AutoValidateAntiforgeryToken]
public class ManageController : Controller
{
Globální příklad:
services.AddControllersWithViews(options =>
options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute()));
Přepsání atributů antiforgery globálního serveru nebo kontroleru
Filtr IgnoreAntiforgeryToken se používá k odstranění potřeby tokenu antiforgery pro danou akci (nebo kontroler). Při použití tento filtr přepíše filtry ValidateAntiForgeryToken a AutoValidateAntiforgeryToken zadané na vyšší úrovni (globálně nebo na řadiči).
[Authorize]
[AutoValidateAntiforgeryToken]
public class ManageController : Controller
{
[HttpPost]
[IgnoreAntiforgeryToken]
public async Task<IActionResult> DoSomethingSafe(SomeViewModel model)
{
// no antiforgery token required
}
}
Aktualizace tokenů po ověření
Tokeny by se měly aktualizovat po ověření uživatele přesměrováním uživatele na stránku zobrazení nebo Razor stránky.
JavaScript, AJAX a SPA
V tradičních aplikacích založených na HTML se antiforgery tokeny předávají serveru pomocí skrytých polí formuláře. V moderních aplikacích založených na JavaScriptu a SA se mnoho požadavků provádí programově. Tyto požadavky AJAX mohou k odeslání tokenu použít jiné techniky (například hlavičky požadavku nebo soubory cookie).
Pokud se soubory cookie používají k ukládání ověřovacích tokenů a k ověřování požadavků rozhraní API na serveru, je csrF potenciálním problémem. Pokud se k uložení tokenu používá místní úložiště, může se zmírnit ohrožení zabezpečení CSRF, protože hodnoty z místního úložiště se na server neodesílají automaticky s každou žádostí. Použití místního úložiště k uložení anti-forgery tokenu na klientovi a odeslání tokenu hlavičkou požadavku je doporučený postup.
JavaScript
Pomocí JavaScriptu se zobrazeními lze token vytvořit pomocí služby v zobrazení. IAntiforgery Vložte službu do zobrazení a zavolejteGetAndStoreTokens:
@{
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>
Tento přístup eliminuje nutnost zabývat se přímo nastavením souborů cookie ze serveru nebo jejich čtením z klienta.
Předchozí příklad používá JavaScript ke čtení skryté hodnoty pole hlavičky AJAX POST.
JavaScript může také přistupovat k tokenům v souborech cookie a pomocí cookieobsahu vytvořit hlavičku s hodnotou tokenu.
context.Response.Cookies.Append("CSRF-TOKEN", tokens.RequestToken,
new Microsoft.AspNetCore.Http.CookieOptions { HttpOnly = false });
Za předpokladu, že skript požádá o odeslání tokenu v hlavičce s názvem X-CSRF-TOKEN, nakonfigurujte službu antiforgery tak, aby hledala hlavičku X-CSRF-TOKEN :
services.AddAntiforgery(options => options.HeaderName = "X-CSRF-TOKEN");
Následující příklad používá JavaScript k vytvoření požadavku AJAX s příslušnou hlavičkou:
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 používá konvenci k řešení CSRF. Pokud server odešle cookie s názvem XSRF-TOKEN, servis AngularJS $http přidá hodnotu cookie do hlavičky při odeslání požadavku na server. Jedná se o automatický proces. Klient nemusí explicitně nastavit hlavičku. Název záhlaví je X-XSRF-TOKEN. Server by měl tuto hlavičku rozpoznat a ověřit jeho obsah.
Aby rozhraní API ASP.NET Core fungovalo s touto konvencí při spuštění aplikace:
- Nakonfigurujte aplikaci tak, aby poskytovala token nazvaný cookie
XSRF-TOKEN. - Nakonfigurujte službu antiforgery tak, aby hledala hlavičku s názvem
X-XSRF-TOKEN, což je výchozí název hlavičky Angular pro odeslání tokenu XSRF.
public void Configure(IApplicationBuilder app, IAntiforgery antiforgery)
{
app.Use(next => context =>
{
string path = context.Request.Path.Value;
if (
string.Equals(path, "/", StringComparison.OrdinalIgnoreCase) ||
string.Equals(path, "/index.html", StringComparison.OrdinalIgnoreCase))
{
var tokens = antiforgery.GetAndStoreTokens(context);
context.Response.Cookies.Append("XSRF-TOKEN", tokens.RequestToken,
new CookieOptions() { HttpOnly = false });
}
return next(context);
});
}
public void ConfigureServices(IServiceCollection services)
{
services.AddAntiforgery(options => options.HeaderName = "X-XSRF-TOKEN");
}
Poznámka:
Pokud je token antiforgery zadaný v hlavičce požadavku i v datové části formuláře, ověří se pouze token v hlavičce.
Ověřování systému Windows a antiforgery cookies
Při použití ověřování systému Windows musí být koncové body aplikací chráněné proti útokům CSRF stejným způsobem jako u souborů cookie. Prohlížeč implicitně odesílá kontext ověřování na server, takže koncové body musí být chráněné před útoky CSRF.
Rozšířit antifalšování
Tento IAntiforgeryAdditionalDataProvider typ umožňuje vývojářům rozšířit chování systému anti-CSRF tím, že v každém tokenu přetáhne další data. Metoda GetAdditionalData se volá při každém vygenerování tokenu pole a návratová hodnota se vloží do vygenerovaného tokenu. Implementátor by mohl vrátit časové razítko, náhodné číslo nebo jinou hodnotu a potom zavolat ValidateAdditionalData k ověření těchto dat, když se token ověřuje. Uživatelské jméno klienta je již vloženo do vygenerovaných tokenů, takže tyto informace nemusíte obsahovat. Pokud token obsahuje doplňková data, ale není nakonfigurovaná žádná IAntiForgeryAdditionalDataProvider , doplňková data se neověřují.