Sdílet prostřednictvím


Prevence XSRF/CSRF v ASP.NET MVC a na webových stránkách

Rick Anderson

Padělání požadavků mezi weby (označované také jako XSRF nebo CSRF) je útok na aplikace hostované na webu, kdy škodlivý web může ovlivnit interakci mezi klientským prohlížečem a webem, který prohlížeč považuje za důvěryhodný. Tyto útoky jsou možné, protože webové prohlížeče odesílají ověřovací tokeny automaticky s každým požadavkem na web. Kanonickým příkladem je ověřovací soubor cookie, například ASP. Lístek ověřování pomocí formulářů na platformě NET. Weby, které používají jakýkoli trvalý ověřovací mechanismus (například ověřování systému Windows, základní atd.), však mohou být cílem těchto útoků.

Útok XSRF se liší od útoku phishing. Útoky phishing vyžadují interakci oběti. Při útoku phishing bude škodlivý web napodobovat cílový web a oběť je oklamována, aby útočníkovi poskytla citlivé informace. Při útoku XSRF často není nutná žádná interakce oběti. Místo toho útočník spoléhá na to, že prohlížeč automaticky odešle všechny relevantní soubory cookie na cílový web.

Další informace najdete v tématu Open Web Application Security Project (OWASP) XSRF.

Anatomie útoku

Pokud chcete projít útokem XSRF, představte si uživatele, který chce provádět nějaké online bankovní transakce. Tento uživatel nejprve navštíví WoodgroveBank.com a přihlásí se. V tomto okamžiku bude hlavička odpovědi obsahovat ověřovací soubor cookie:

HTTP/1.1 200 OK
Date: Mon, 18 Jun 2012 21:22:33 GMT
X-AspNet-Version: 4.0.30319
Set-Cookie: .ASPXAUTH={authentication-token}; path=/; secure; HttpOnly;
{ Cache-Control, Content-Type, Location, Server and other keys/values not listed. }

Vzhledem k tomu, že ověřovací soubor cookie je soubor cookie relace, prohlížeč ho při ukončení procesu prohlížeče automaticky vymaže. Do té doby však prohlížeč automaticky zahrne soubor cookie s každou žádostí o WoodgroveBank.com. Uživatel teď chce převést $1000 na jiný účet, takže vyplní formulář na bankovním webu a prohlížeč odešle tento požadavek na server:

POST /DoTransfer HTTP/1.1
Host: WoodgroveBank.com
Content-Type: application/x-www-form-urlencoded
Cookie: .ASPXAUTH={authentication-token}
toAcct=12345&amount=1,000.00

Vzhledem k tomu, že tato operace má vedlejší účinek (inicializuje peněžní transakci), bankovní web se rozhodl vyžadovat HTTP POST k zahájení této operace. Server načte ověřovací token z požadavku, vyhledá číslo účtu aktuálního uživatele, ověří, zda existují dostatečné prostředky, a poté zahájí transakci do cílového účtu.

Její online bankovnictví dokončeno, uživatel přejde mimo bankovní stránky a navštíví další místa na webu. Jeden z těchto webů – fabrikam.com – obsahuje následující kód na stránce vložené do <prvku iframe>:

<form id="theForm" action="https://WoodgroveBank.com/DoTransfer" method="post">
    <input type="hidden" name="toAcct" value="67890" />
    <input type="hidden" name="amount" value="250.00" />
</form>
<script type="text/javascript">
    document.getElementById('theForm').submit();
</script>

To pak způsobí, že prohlížeč vytvoří tento požadavek:

POST /DoTransfer HTTP/1.1
Host: WoodgroveBank.com
Content-Type: application/x-www-form-urlencoded
Cookie: .ASPXAUTH={authentication-token}
toAcct=67890&amount=250.00

Útočník využívá skutečnost, že uživatel může mít stále platný ověřovací token pro cílový web, a používá malý fragment JavaScriptu k tomu, aby prohlížeč automaticky vytvořil HTTP POST na cílový web. Pokud je ověřovací token stále platný, bankovní web zahájí převod 250 USD na účet podle výběru útočníka.

Neúčinná zmírnění rizik

Je zajímavé si uvědomit, že ve výše uvedeném scénáři nebyla dostatečná skutečnost, že k WoodgroveBank.com přistupovalo přes SSL a měl ověřovací soubor cookie pouze SSL, aby se útok zmařil. Útočník může ve svém <elementu formuláře> zadat schéma identifikátorů URI (https) a prohlížeč bude dál odesílat soubory cookie, které nevyprchají, na cílový web, pokud jsou tyto soubory cookie konzistentní se schématem identifikátorů URI zamýšleného cíle.

Jeden by mohl argumentovat, že uživatel by prostě neměl navštěvovat nedůvěryhodné weby, protože návštěva pouze důvěryhodných webů pomáhá zůstat v bezpečí online. Existuje určitá pravda, ale bohužel tato rada není vždy praktická. Je možné, že uživatel "důvěřuje" místnímu zpravodajskému webu ConsolidatedMessenger.com a místo toho tento web navštíví, ale tento web má chybu zabezpečení XSS, která útočníkovi umožňuje vložit stejný fragment kódu, který běžel na fabrikam.com.

Můžete ověřit, že příchozí požadavky mají hlavičku Referer odkazující na vaši doménu. Tím se zastaví žádosti bezděčně odeslané z domény třetí strany. Někteří lidé ale z důvodu ochrany osobních údajů vypnou hlavičku refereru prohlížeče a útočníci někdy můžou tuto hlavičku zpochybnit, pokud má oběť nainstalovaný určitý nezabezpečený software. Ověření hlavičky Referer se nepovažuje za bezpečný přístup k prevenci útoků XSRF.

Zmírnění rizik modulu runtime webového zásobníku XSRF

Modul ASP.NET Web Stack Runtime používá variantu vzoru tokenu synchronizátoru k obraně před útoky XSRF. Obecná forma vzoru tokenu synchronizátoru je, že se na server odesílají dva tokeny anti-XSRF s každým protokolem HTTP POST (kromě ověřovacího tokenu): jedním tokenem jako soubor cookie a druhým jako hodnotou formuláře. Hodnoty tokenů vygenerované modulem runtime ASP.NET nejsou deterministické ani předvídatelné útočníkem. Po odeslání tokenů server umožní požadavek pokračovat pouze v případě, že oba tokeny projdou kontrolou porovnání.

Token relace ověření požadavku XSRF je uložený jako soubor cookie HTTP a v datové části aktuálně obsahuje následující informace:

  • Token zabezpečení, který se skládá z náhodného 128bitového identifikátoru.
    Následující obrázek znázorňuje token relace ověření požadavku XSRF zobrazený ve vývojářských nástrojích Internet ExplorerU F12: (Všimněte si, že se jedná o aktuální implementaci a je pravděpodobné, že se může změnit.)

Snímek obrazovky se stránkou My A S P dot NET M V C Application Index Karta Síť je otevřená.

Token pole se uloží jako a <input type="hidden" /> v datové části obsahuje následující informace:

Datové části tokenů anti-XSRF jsou šifrované a podepsané, takže při kontrole tokenů pomocí nástrojů nemůžete zobrazit uživatelské jméno. Pokud webová aplikace cílí na ASP.NET 4.0, kryptografické služby jsou poskytovány rutinou MachineKey.Encode . Pokud webová aplikace cílí na ASP.NET 4.5 nebo vyšší, kryptografické služby poskytuje rutina MachineKey.Protect , která nabízí lepší výkon, rozšiřitelnost a zabezpečení. Další podrobnosti najdete v následujících blogových příspěvcích:

Generování tokenů

Chcete-li vygenerovat tokeny anti-XSRF, zavolejte metodu @Html.AntiForgeryToken ze zobrazení MVC nebo @AntiForgery.GetHtml() ze stránky Razor Page. Modul runtime pak provede následující kroky:

  1. Pokud aktuální požadavek HTTP již obsahuje token relace anti-XSRF (soubor cookie anti-XSRF __RequestVerificationToken), token zabezpečení se z něj extrahuje. Pokud požadavek HTTP neobsahuje token relace anti-XSRF nebo pokud se extrakce tokenu zabezpečení nezdaří, vygeneruje se nový náhodný token anti-XSRF.
  2. Token pole anti-XSRF se generuje pomocí tokenu zabezpečení z kroku (1) výše a identity aktuálního přihlášeného uživatele. (Další informace o určení identity uživatele najdete níže v části Scénáře se speciální podporou .) Navíc pokud IAntiForgeryAdditionalDataProvider je nakonfigurována, modul runtime bude volat jeho GetAdditionalData metoda a zahrnout vrácený řetězec v tokenu pole. (Další informace najdete v části Konfigurace a rozšiřitelnost .)
  3. Pokud se v kroku (1) vygeneroval nový token anti-XSRF, vytvoří se nový token relace, který ho bude obsahovat a přidá se do kolekce odchozích souborů cookie HTTP. Token pole z kroku (2) se zabalí do elementu <input type="hidden" /> a tento kód HTML bude vrácenou hodnotou Html.AntiForgeryToken() nebo AntiForgery.GetHtml().

Ověřování tokenů

Aby vývojář ověřil příchozí tokeny anti-XSRF, zahrne do své akce nebo kontroleru MVC atribut ValidateAntiForgeryToken , nebo zavolá @AntiForgery.Validate() ze stránky Razor Page. Modul runtime provede následující kroky:

  1. Načtou se tokeny příchozí relace a token pole a z každého z nich se extrahuje token anti-XSRF. Tokeny anti-XSRF musí být identické v každém kroku (2) v rutině generování.
  2. Pokud je aktuální uživatel ověřený, porovná se jeho uživatelské jméno s uživatelským jménem uloženým v tokenu pole. Uživatelská jména se musí shodovat.
  3. Pokud IAntiForgeryAdditionalDataProvider je nakonfigurován, modul runtime volá jeho ValidateAdditionalData metoda. Metoda musí vrátit logickou hodnotu true.

Pokud ověření proběhne úspěšně, může požadavek pokračovat. Pokud se ověření nezdaří, rozhraní vyvolá Výjimku HttpAntiForgeryException.

Podmínky selhání

Počínaje modulem ASP.NET Web Stack Runtime v2 budou všechny výjimky HttpAntiForgeryException vyvolané během ověřování obsahovat podrobné informace o tom, co se nepovedlo. Aktuálně definované podmínky selhání jsou:

  • Token relace nebo token formuláře se v požadavku nenachází.
  • Token relace nebo token formuláře je nečitelný. Nejpravděpodobnější příčinou je, že farma používá neshodné verze modulu runtime webového zásobníku ASP.NET nebo farmu, kde <se prvek machineKey> v Web.config mezi počítači liší. K vynucení této výjimky můžete použít nástroj, jako je Fiddler, a to manipulací s tokenem anti-XSRF.
  • Token relace a token pole byly prohozeny.
  • Token relace a token pole obsahují neshodné tokeny zabezpečení.
  • Uživatelské jméno vložené v tokenu pole neodpovídá aktuálnímu uživatelskému jménu přihlášeného uživatele.
  • Metoda IAntiForgeryAdditionalDataProvider.ValidateAdditionalData vrátila hodnotu false.

Zařízení anti-XSRF mohou také provádět další kontroly během generování nebo ověřování tokenů a selhání během těchto kontrol mohou vést k vyvolání výjimek. Další informace najdete v částech Ověřování na základě deklarací identity a Konfigurace a rozšiřitelnost technologie WIF/ ACS/ .

Scénáře se speciální podporou

Anonymní ověření

Systém anti-XSRF obsahuje speciální podporu pro anonymní uživatele, kde "anonymní" je definován jako uživatel, kde IIdentity.IsAuthenticated vrátí vlastnost false. Scénáře zahrnují zajištění ochrany XSRF pro přihlašovací stránku (před ověřením uživatele) a vlastní schémata ověřování, kdy aplikace používá k identifikaci uživatelů jiný mechanismus než IIdentity .

Pro podporu těchto scénářů si připomeňme, že tokeny relace a pole jsou spojené tokenem zabezpečení, což je 128bitový náhodně vygenerovaný neprůshlený identifikátor. Tento token zabezpečení slouží ke sledování relace jednotlivého uživatele při procházení webu, takže efektivně slouží k účelu anonymního identifikátoru. Prázdný řetězec se používá místo uživatelského jména pro výše popsané rutiny generování a ověřování.

WiF / ACS / ověřování na základě deklarací identity

Za normálních okolností IIdentity třídy integrované do rozhraní .NET Framework mají vlastnost, která IIdentity.Name je dostatečná k jedinečné identifikaci konkrétního uživatele v rámci konkrétní aplikace. Například FormsIdentity.Name vrátí uživatelské jméno uložené v databázi členství (které je jedinečné pro všechny aplikace v závislosti na dané databázi), WindowsIdentity.Name vrátí identitu uživatele kvalifikovanou pro doménu atd. Tyto systémy poskytují nejen ověřování; identifikují také uživatele aplikace.

Ověřování na základě deklarací identity naopak nemusí nutně vyžadovat identifikaci konkrétního uživatele. Typy ClaimsPrincipal a ClaimsIdentity jsou místo toho přidruženy k sadě instancí deklarací identity , kde jednotlivé deklarace identity můžou být "je starší než 18 let" nebo "je správcem" k čemukoli jinému. Vzhledem k tomu, že uživatel nebyl nutně identifikován, nemůže modul runtime použít vlastnost ClaimsIdentity.Name jako jedinečný identifikátor pro tohoto konkrétního uživatele. Tým viděl reálné příklady, kdy ClaimsIdentity.Name vrátí hodnotu null, vrátí popisný (zobrazovaný) název nebo jinak vrátí řetězec, který není vhodný pro použití jako jedinečný identifikátor uživatele.

Mnoho nasazení, která používají ověřování na základě deklarací identity, používá zejména službu Azure Access Control Service (ACS). Služba ACS umožňuje vývojáři konfigurovat jednotlivé zprostředkovatele identity (například ADFS, zprostředkovatel účtu Microsoft, zprostředkovatele OpenID, jako je Yahoo!, atd.) a zprostředkovatelé identity vracejí identifikátory názvů. Tyto identifikátory jmen můžou obsahovat identifikovatelné osobní údaje (PII), jako je e-mailová adresa, nebo mohou být anonymizované jako soukromý osobní identifikátor (PPID). Bez ohledu na to, řazená kolekce členů (zprostředkovatel identity, identifikátor názvu) dostatečně slouží jako vhodný token sledování pro konkrétního uživatele při procházení webu, takže ASP.NET Web Stack Runtime může při generování a ověřování tokenů pole anti-XSRF používat místo uživatelského jména řazenou kolekci členů. Konkrétní identifikátory URI pro zprostředkovatele identity a identifikátor názvu jsou :

  • https://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider
  • http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier

(Další informace najdete na této stránce s dokumentem služby ACS .)

Při generování nebo ověřování tokenu se modul ASP.NET Web Stack Runtime za běhu pokusí vytvořit vazbu na typy:

  • Microsoft.IdentityModel.Claims.IClaimsIdentity, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35 (Pro sadu WIF SDK.)
  • System.Security.Claims.ClaimsIdentity (Pro .NET 4.5).

Pokud tyto typy existují a pokud iiiIdentity aktuálního uživatele implementuje nebo podtřídy některé z těchto typů, anti-XSRF zařízení použije místo uživatelského jména při generování a ověřování tokenů řazenou kolekci členů (zprostředkovatele identity, identifikátor názvu). Pokud taková řazená kolekce členů neexistuje, požadavek selže s chybou popisující vývojáři, jak nakonfigurovat anti-XSRF systém, aby porozuměl konkrétnímu používanému mechanismu ověřování založenému na deklarací identity. Další informace najdete v části Konfigurace a rozšiřitelnost .

Ověřování OAuth / OpenID

A konečně, anti-XSRF zařízení má zvláštní podporu pro aplikace, které používají ověřování OAuth nebo OpenID. Tato podpora je založená na heuristice: Pokud aktuální IIdentity.Name začíná http:// nebo https://, bude porovnávání uživatelských jmen provedeno pomocí porovnávače ordinal, nikoli pomocí výchozího porovnávače OrdinalIgnoreCase.

Konfigurace a rozšiřitelnost

Někdy můžou vývojáři chtít přísnější kontrolu nad generováním a ověřováním anti-XSRF. Například výchozí chování pomocníků MVC a webových stránek automatického přidávání souborů cookie HTTP do odpovědi je nežádoucí a vývojář může chtít tokeny zachovat jinde. Existují dvě rozhraní API, která vám s tím pomůžou:

AntiForgery.GetTokens(string oldCookieToken, out string newCookieToken, out string formToken);
AntiForgery.Validate(string cookieToken, string formToken);

Metoda GetTokens přijímá jako vstup existující token relace ověření požadavku XSRF (který může mít hodnotu null) a vytvoří jako výstup nový token relace ověření požadavku XSRF a token pole. Tokeny jsou jednoduše neprůsvné řetězce bez dekorace; hodnota formToken nebude například zabalena do <vstupní> značky. Hodnota newCookieToken může být null; Pokud k tomu dojde, pak je hodnota oldCookieToken stále platná a není nutné nastavit nový soubor cookie odpovědi. Volající GetTokens je zodpovědný za zachování všech potřebných souborů cookie odpovědi nebo generování jakýchkoli nezbytných značek; Samotná metoda GetTokens nezmění odpověď jako vedlejší efekt. Metoda Validate převezme příchozí tokeny relace a pole a spustí na nich výše uvedenou logiku ověřování.

AntiForgeryConfig

Vývojář může nakonfigurovat anti-XSRF systém z Application_Start. Konfigurace je programová. Vlastnosti statického typu AntiForgeryConfig jsou popsány níže. Většina uživatelů používajících deklarace identity bude chtít nastavit vlastnost UniqueClaimTypeIdentifier.

Vlastnost Popis
AdditionalDataProvider IAntiForgeryAdditionalDataProvider, který poskytuje další data během generování tokenu a využívá další data během ověřování tokenu. Výchozí hodnota je null. Další informace najdete v části IAntiForgeryAdditionalDataProvider .
Cookiename Řetězec, který poskytuje název souboru cookie HTTP, který se používá k uložení tokenu relace anti-XSRF. Pokud tato hodnota není nastavená, název se automaticky vygeneruje na základě nasazené virtuální cesty aplikace. Výchozí hodnota je null.
RequireSsl Logická hodnota, která určuje, jestli se vyžaduje odeslání tokenů anti-XSRF přes kanál zabezpečený protokolem SSL. Pokud je tato hodnota true, všechny automaticky generované soubory cookie budou mít nastavený příznak "secure" a rozhraní API pro ochranu proti XSRF se vyvolá, pokud je volána z požadavku, který není odeslán prostřednictvím protokolu SSL. Výchozí hodnota je false (nepravda).
SuppressIdentityHeuristicChecks Logická hodnota, která určuje, jestli má systém anti-XSRF deaktivovat podporu identit založených na deklaracích. Pokud je tato hodnota true, systém bude předpokládat, že IIdentity.Name je vhodný pro použití jako jedinečný identifikátor pro uživatele, a nebude se pokoušet o zvláštní případ IClaimsIdentity nebo ClClaimsIdentity , jak je popsáno v části WIF / ACS / ověřování na základě deklarací identity. Výchozí hodnota je false.
UniqueClaimTypeIdentifier Řetězec, který označuje, který typ deklarace identity je vhodný pro použití jako jedinečný identifikátor uživatele. Pokud je tato hodnota nastavená a aktuální IIdentity je založená na deklaracích, systém se pokusí extrahovat deklaraci identity typu určeného parametrem UniqueClaimTypeIdentifier a odpovídající hodnota se použije místo uživatelského jména uživatele při generování tokenu pole. Pokud se typ deklarace identity nenajde, systém požadavek selže. Výchozí hodnota je null, což znamená, že systém by měl místo uživatelského jména uživatele používat řazenou kolekci členů (zprostředkovatele identity, identifikátor názvu).

IAntiForgeryAdditionalDataProvider

Typ IAntiForgeryAdditionalDataProvider umožňuje vývojářům rozšířit chování systému anti-XSRF tím, že v každém tokenu zaokrouhlí další data. Metoda GetAdditionalData je volána při každém vygenerování tokenu pole a návratová hodnota je vložena do vygenerovaného tokenu. Implementátor může z této metody vrátit časové razítko, nonce nebo jinou hodnotu, kterou si přeje.

Podobně je metoda ValidateAdditionalData volána při každém ověření tokenu pole a do metody se předá řetězec "další data", který byl vložen v tokenu. Ověřovací rutina může implementovat časový limit (kontrolou aktuálního času oproti času, který byl uložen při vytvoření tokenu), rutiny kontroly nonce nebo jakékoli jiné požadované logiky.

Rozhodnutí o návrhu a aspekty zabezpečení

Token zabezpečení, který propojuje tokeny relace a pole, je technicky nutný pouze při pokusu o ochranu anonymních nebo neověřených uživatelů před útoky XSRF. Když je uživatel ověřený, samotný ověřovací token (pravděpodobně odeslaný ve formě souboru cookie) by se mohl použít jako polovina páru tokenů synchronizátoru. Existují však platné scénáře ochrany přihlašovacích stránek, na které by narazili neověření uživatelé, a logika ochrany proti XSRF byla jednodušší tím, že vždy vygenerovala a ověřovala token zabezpečení, a to i pro ověřené uživatele. Poskytuje také určitou dodatečnou ochranu v případě, že je token pole ohrožen útočníkem, protože nastavení nebo odhad tokenu relace by bylo další překážkou, kterou by útočník mohl překonat.

Vývojáři by měli být opatrní, pokud je v jedné doméně hostováno více aplikací. I když example1.cloudapp.net a example2.cloudapp.net jsou například různí hostitelé, existuje implicitní vztah důvěryhodnosti mezi všemi hostiteli v doméně *.cloudapp.net . Tento vztah implicitní důvěryhodnosti umožňuje potenciálně nedůvěryhodným hostitelům vzájemně ovlivňovat soubory cookie (zásady stejného původu, které řídí požadavky AJAX, se nemusí nutně vztahovat na soubory cookie HTTP). Modul ASP.NET Web Stack Runtime poskytuje určité omezení v tom, že uživatelské jméno je vloženo do tokenu pole, takže i když je škodlivá subdoména schopna přepsat token relace, nebude možné pro uživatele vygenerovat platný token pole. Pokud jsou však v takovém prostředí hostovány integrované rutiny anti-XSRF, stále nemohou bránit před napadením relace nebo přihlášením XSRF.

Anti-XSRF rutiny v současné době nebrání proti kliknutí. Aplikace, které se chtějí bránit proti clickjackingu, to mohou snadno udělat odesláním hlavičky X-Frame-Options: SAMEORIGIN s každou odpovědí. Tato hlavička je podporována všemi nedávnými prohlížeči. Další informace najdete na blogu IE, blogu SDL a OWASP. ASP.NET Web Stack Runtime může v některé budoucí verzi způsobit, že pomocníky MVC a Webových stránek anti-XSRF automaticky nastaví tuto hlavičku tak, aby aplikace byly automaticky chráněny proti tomuto útoku.

Weboví vývojáři by měli i nadále zajistit, aby jejich web nebyl zranitelný vůči útokům XSS. Útoky XSS jsou velmi výkonné a úspěšné zneužití by také narušovalo ASP.NET ochranu modulu Web Stack Runtime proti útokům XSRF.

Potvrzení

@LeviBroderick, který napsal většinu ASP.NET bezpečnostních kódů.