Megosztás a következőn keresztül:


Keresztoldalas kéréshamisítás (XSRF/CSRF) támadások megakadályozása az ASP.NET Core-ban

Fiyaz Hasan és Rick Anderson

A webhelyek közötti kéréshamisítás a webalkalmazások elleni támadás, amely során egy rosszindulatú webalkalmazás befolyásolhatja az ügyfélböngésző és a böngésző által megbízhatónak hitt webalkalmazás közötti interakciót. Ezek a támadások azért lehetségesek, mert a webböngészők minden kéréssel automatikusan küldenek bizonyos hitelesítési jogkivonatokat egy webhelyre. Ezt a biztonsági rést egykattintásos támadásnak is nevezik, vagy munkamenet-eltérítésnek, mert kihasználja a felhasználó korábban hitelesített munkamenetét. A helyek közötti kérelemhamisítást XSRF-nek vagy CSRF-nek is nevezik.

Példa CSRF-támadásra:

  1. A felhasználó űrlap-hitelesítéssel jelentkezik be www.good-banking-site.example.com. A kiszolgáló hitelesíti a felhasználót, és egy hitelesítési cookietartalmazó választ ad ki. A webhely sebezhető a támadásokkal szemben, mert megbízik minden olyan kérésben, amelyet érvényes hitelesítési cookiekap.

  2. A felhasználó meglátogat egy rosszindulatú webhelyet, www.bad-crook-site.example.com.

    A kártékony webhely (www.bad-crook-site.example.com) az alábbi példához hasonló HTML-űrlapot tartalmaz:

    <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>
    

    Figyelje meg, hogy az űrlap action a sebezhető webhelyre, nem pedig a rosszindulatú webhelyre. Ez a CSRF "keresztoldali" része.

  3. A felhasználó kiválasztja a Küldés gombot. A böngésző a kérést végrehajtja, és automatikusan tartalmazza a cookie hitelesítést a kért tartományhoz, www.good-banking-site.example.com.

  4. A kérés a www.good-banking-site.example.com kiszolgálón fut a felhasználó hitelesítési környezetével, és bármilyen műveletet végrehajthat, amelyet egy hitelesített felhasználó végrehajthat.

Azon forgatókönyv mellett, amikor a felhasználó kiválasztja az űrlap elküldéséhez a gombot, a rosszindulatú webhely a következőt teheti:

  • Futtasson egy szkriptet, amely automatikusan elküldi az űrlapot.
  • Küldje el az űrlap beküldését AJAX-kérelemként.
  • Rejtse el az űrlapot a CSS használatával.

Ezek az alternatív forgatókönyvek nem igényelnek semmilyen műveletet vagy bemenetet a felhasználótól, kivéve, ha eredetileg meglátogatják a rosszindulatú webhelyet.

A HTTPS használata nem akadályozza meg a CSRF-támadást. A rosszindulatú webhely épp olyan könnyen küldhet https://www.good-banking-site.example.com/ kérést, mint ahogy nem biztonságos kérést küld.

Egyes támadások a GET-kérelmekre reagáló végpontokat támadják meg, ebben az esetben egy képcímke használható a művelet végrehajtásához. Ez a támadási forma gyakori a fórumwebhelyeken, amelyek lehetővé teszik a képeket, de letiltják a JavaScriptet. A GET-kérések állapotát módosító alkalmazások, amelyek változókat vagy erőforrásokat módosítanak, sebezhetők a rosszindulatú támadásokkal szemben. Az állapotot módosító GET-kérelmek nem biztonságosak. Ajánlott eljárás, hogy soha ne változtassunk állapotot GET-kérés során.

A CSRF-támadások a hitelesítéshez cookie-kat használó webalkalmazások ellen lehetségesek, mert:

  • A böngészők egy webalkalmazás által kibocsátott cookie-kat tárolnak.
  • A tárolt cookie-k munkamenet-cookie-kat tartalmaznak a hitelesített felhasználók számára.
  • A böngészők minden, tartományhoz társított cookie-t elküldenek a webalkalmazásnak, függetlenül attól, hogy az alkalmazáskérés hogyan jött létre a böngészőben.

A CSRF-támadások azonban nem korlátozódnak a cookie-k kihasználására. Az alapszintű és a kivonatoló hitelesítés például sebezhető. Miután egy felhasználó bejelentkezett alapszintű vagy kivonatoló hitelesítéssel, a böngésző automatikusan elküldi a hitelesítő adatokat, amíg a munkamenet véget nem ér.

Ebben az összefüggésben munkamenet arra az ügyféloldali munkamenetre vonatkozik, amely során a felhasználó hitelesítése megtörtént. Nem kapcsolódik kiszolgálóoldali munkamenetekhez vagy ASP.NET Core Session Middleware.

A felhasználók óvintézkedéseket tehetnek a CSRF biztonsági rései ellen:

  • Kijelentkezés a webalkalmazásból, ha befejezte a használatukat.
  • A böngésző cookie-inak rendszeres törlése.

A CSRF biztonsági rései azonban alapvetően a webalkalmazással, nem pedig a végfelhasználóval kapcsolatos problémák.

A hitelesítés alapjai

Cookie-alapú hitelesítés a hitelesítés népszerű formája. A token alapú hitelesítési rendszerek egyre népszerűbbek, különösen az egyoldalas alkalmazások (SPA-k) esetében.

Amikor egy felhasználó a felhasználónevével és jelszavával hitelesít, egy hitelesítési jegyet tartalmazó jogkivonatot kap. A token használható hitelesítéshez és engedélyezéshez. A tokent egy cookie-ként tárolják, amelyet minden kérésnél az ügyféllel együtt küldenek. A cookie létrehozása és érvényesítése a Cookie Hitelesítési köztes szoftverrel történik. A köztes szoftver egy felhasználónevet titkosított cookieszerializál. A következő kérések során a köztes szoftver ellenőrzi a cookie-t, újra létrehozza a főkomponenst, és hozzárendeli a főkomponenst a HttpContext.User tulajdonsághoz.

Tokenalapú hitelesítés

Ha egy felhasználó hitelesítése megtörtént, a rendszer tokent ad ki (nem pedig antiforgery tokent). A jogkivonat felhasználói adatokat tartalmaz jogcímek formájában, vagy egy hivatkozási jogkivonat formájában, amely az alkalmazást az alkalmazásban fenntartott felhasználói állapotra mutatja. Amikor egy felhasználó megpróbál hozzáférni egy hitelesítést igénylő erőforráshoz, a rendszer a jogkivonatot egy további engedélyezési fejléccel továbbítja az alkalmazásnak tulajdonosi jogkivonat formájában. Ez a megközelítés állapot nélkülivé teszi az alkalmazást. Minden további kérésben a jogkivonat továbbításra kerül a kiszolgálóoldali érvényesítéshez. Ez a jogkivonat nem titkosított; kódolt. A kiszolgálón a rendszer dekódolja a jogkivonatot, hogy hozzáférjen az adataihoz. A jogkivonat későbbi kérésekre való elküldéséhez tárolja a jogkivonatot a böngésző helyi tárolójában. Ha a jogkivonatot a böngésző helyi tárolójában helyezi el, lekérte és tulajdonosi jogkivonatként használja, védelmet nyújt a CSRF-támadások ellen. Ha azonban az alkalmazás sebezhető az XSS-en vagy egy feltört külső JavaScript-fájlon keresztüli szkriptinjektálással szemben, a kiberbűnözők bármilyen értéket lekérhetnek a helyi tárolóból, és elküldhetik őket maguknak. ASP.NET Core alapértelmezés szerint a változók összes kiszolgálóoldali kimenetét kódolja, így csökkenti az XSS kockázatát. Ha ezt a viselkedést Html.Raw vagy nem megbízható bemenettel rendelkező egyéni kóddal bírálja felül, akkor növelheti az XSS kockázatát.

Ne aggódjon a CSRF biztonsági rése miatt, ha a jogkivonat a böngésző helyi tárolójában van tárolva. A CSRF aggodalomra ad okot, ha a tokent egy cookie-ban tárolják. További információért lásd a GitHub probléma oldalt: az SPA kódminta két cookie-t ad hozzá.

Több, egy tartományban üzemeltetett alkalmazás

A megosztott üzemeltetési környezetek ki vannak téve a munkamenet-eltérítésnek, a bejelentkezési CSRF-nek és más támadásoknak.

Bár example1.contoso.net és example2.contoso.net különböző gazdagépek, implicit megbízhatósági kapcsolat áll fenn a *.contoso.net tartománybeli gazdagépek között. Ez az implicit megbízhatósági kapcsolat lehetővé teszi, hogy a potenciálisan nem megbízható gazdagépek befolyásolják egymás cookie-jait (az AJAX-kéréseket szabályozó azonos eredetű szabályzatok nem feltétlenül vonatkoznak a HTTP-cookie-kra).

Az ugyanazon a tartományon üzemeltetett alkalmazások közötti megbízható cookie-kat kihasználó támadások megelőzhetők, ha nem osztanak meg tartományokat. Ha az egyes alkalmazásokat a saját tartományában üzemeltetik, nincs kihasználandó implicit cookie megbízhatósági kapcsolat.

Antiforgery az ASP.NET Core-ban

Figyelmeztetés

ASP.NET Core a ASP.NET Core Data Protectionhasználatával implementálja a hamisítás elleni védelmet. Az adatvédelmi vermet úgy kell konfigurálni, hogy egy kiszolgálófarmban működjön. További információért lásd: Az adatvédelem konfigurálása.

Antiforgery middleware kerül be a függőség-injektálási tárolóba, ha az alábbi API-k egyikét meghívják Program.cs:

További információ: Antiforgery minimális API-kkal.

A FormTagHelper hamisításgátló tokeneket injektál a HTML-űrlapelemekbe. Egy Razor fájlban a következő korrektúra automatikusan létrehozza az antiforgery tokeneket:

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

Hasonlóképpen, IHtmlHelper.BeginForm alapértelmezés szerint antiforgery tokeneket hoz létre, ha az űrlap metódusa nem GET.

A HTML-űrlapelemek antiforgery tokenjeinek automatikus létrehozása akkor történik, ha a <form> címke tartalmazza a method="post" attribútumot, és az alábbiak bármelyike igaz:

  • A műveletattribútum üres (action="").
  • A műveletattribútum nincs megadva (<form method="post">).

A HTML-űrlapelemekhez tartozó antiforgery tokenek automatikus létrehozása letiltható:

  • Explicit módon tiltsa le az antiforgery tokeneket a asp-antiforgery attribútummal:

    <form method="post" asp-antiforgery="false">
        <!-- ... -->
    </form>
    
  • Az űrlapelem ki van zárva a Címkesegítők közül a Tag Helper ! opt-out szimbólumokhasználatával.

    <!form method="post">
        <!-- ... -->
    </!form>
    
  • Távolítsa el a FormTagHelper a nézetből. A FormTagHelper eltávolítható egy nézetből az alábbi irányelv Razor nézethez való hozzáadásával:

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

Jegyzet

Razor lapok automatikusan védettek az XSRF/CSRF támadások ellen. További információ: XSRF/CSRF és Razor Pages.

A CSRF-támadások elleni védelem leggyakoribb módja a szinkronizáló jogkivonat-minta (STP) használata. Az STP akkor használatos, ha a felhasználó űrlapadatokat tartalmazó lapot kér:

  1. A kiszolgáló egy, az aktuális felhasználó identitásához társított jogkivonatot küld a kliensnek.
  2. Az ügyfél visszaküldi a jogkivonatot a kiszolgálónak ellenőrzés céljából.
  3. Ha a kiszolgáló olyan jogkivonatot kap, amely nem egyezik a hitelesített felhasználó identitásával, a rendszer elutasítja a kérést.

A token egyedi és kiszámíthatatlan. A jogkivonat arra is használható, hogy biztosítsa a kérelmek sorozatának megfelelő sorrendjét (például a következő kérelmek sorrendjének biztosításához: 1. oldal > 2. oldal > 3. oldal). Az összes ASP.NET Core MVC és Razor Pages sablonú űrlap valahogy antiforgery tokeneket hoz létre. A következő példanézet-páros antiforgery biztonsági tokeneket hoz létre:

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

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

Kifejezetten adjon hozzá egy hamisítás elleni tokent egy <form> elemhez a Tag Helper és a HTML-segéd használata nélkül @Html.AntiForgeryToken.

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

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

Az előző esetekben ASP.NET Core az alábbi példához hasonló rejtett űrlapmezőt ad hozzá:

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

ASP.NET Core három szűrőt tartalmaz, az antiforgery tokenek használatát:

Hamisításvédelem AddControllers

A AddControllers hívása nem engedélyezni az antiforgery tokeneket. A AddControllersWithViews-t meg kell hívni, hogy beépített hamisításgátló token-támogatással rendelkezzen.

Több böngészőlap és a szinkronizáló token sablon

Nem támogatott a több fül, amelyben különböző felhasználókként, vagy az egyik fülben névtelenként van bejelentkezve.

Antiforgery konfigurálása AntiforgeryOptions

AntiforgeryOptions testreszabása a Program.cs-en:

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

Állítsa be az antiforgery Cookie tulajdonságokat a CookieBuilder osztály tulajdonságaival, ahogyan az az alábbi táblázatban látható.

Opció Leírás
Cookie Meghatározza az antiforgery cookie-k létrehozásához használt beállításokat.
FormFieldName Annak a rejtett űrlapmezőnek a neve, amelyet az antiforgery rendszer használ az antiforgery tokenek nézetekben való megjelenítéséhez.
HeaderName Az antiforgery rendszer által használt fejléc neve. Ha null, a rendszer csak az űrlapadatokat veszi figyelembe.
SuppressXFrameOptionsHeader Megadja, hogy el kívánja-e tiltani a X-Frame-Options fejléc generálását. Alapértelmezés szerint a fejléc "SAMEORIGIN" értékkel jön létre. Alapértelmezés szerint false.

További információ: CookieAuthenticationOptions.

Antiforgery tokenek létrehozása IAntiforgery

IAntiforgery biztosítja az API-t az antiforgery funkciók konfigurálásához. IAntiforgery a Program.cshasználatával kérhető meg WebApplication.Services-ben. Az alábbi példa az alkalmazás kezdőlapján használt köztes szoftvert használja egy antiforgery token létrehozásához, és cookie-ként küldi el a válaszban.

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

Az előző példa egy cookie nevű XSRF-TOKEN-et állít be. Az ügyfél elolvashatja ezt a cookie, és az AJAX-kérelmekhez csatolt fejlécként megadhatja az értékét. Az Angular például beépített XSRF-védelmet tartalmaz, amely alapértelmezés szerint egy cookie nevű XSRF-TOKEN-t olvas be.

Hamisítás elleni ellenőrzés megkövetelése

Az ValidateAntiForgeryToken műveletszűrő egyéni műveletekre, vezérlőkre vagy globálisan alkalmazható. A szűrőt alkalmazó műveletekre irányuló kérések le lesznek tiltva, kivéve, ha a kérés érvényes antiforgery-jogkivonatot tartalmaz:

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

    return RedirectToAction();
}

A ValidateAntiForgeryToken attribútumhoz jogkivonatra van szükség az általa jelölt műveleti módszerekre irányuló kérelmekhez, beleértve a HTTP GET-kérelmeket is. Ha az alkalmazás vezérlőire a ValidateAntiForgeryToken attribútum van alkalmazva, akkor a IgnoreAntiforgeryToken attribútummal felülírható.

Az antiforgery tokenek automatikus ellenőrzése csak a nem biztonságos HTTP-metódusok esetén történik meg.

Ahelyett, hogy a ValidateAntiForgeryToken attribútumot általánosan alkalmazná, majd felülírná IgnoreAntiforgeryToken attribútumokkal, az AutoValidateAntiforgeryToken attribútum használható. Ez az attribútum ugyanúgy működik, mint a ValidateAntiForgeryToken attribútum, azzal a különbségkel, hogy nem igényel jogkivonatokat a következő HTTP-metódusokkal végrehajtott kérelmekhez:

  • SZEREZZ
  • FEJ
  • OPCIÓK
  • NYOM

Javasoljuk a AutoValidateAntiforgeryToken széles körű használatát nem API-szcenáriókhoz. Ez az attribútum biztosítja, hogy a POST-műveletek alapértelmezés szerint védettek legyenek. A másik lehetőség az, hogy alapértelmezés szerint figyelmen kívül hagyja az antiforgery tokeneket, kivéve, ha ValidateAntiForgeryToken az egyes műveleti módszerekre van alkalmazva. Ebben a forgatókönyvben valószínűbb, hogy egy POST-műveletmetódus véletlenül védtelen marad, így az alkalmazás sebezhető lesz a CSRF-támadásokkal szemben. Minden POST-nak el kell küldenie a hamisítás elleni tokent.

Az API-k nem rendelkeznek automatikus mechanizmusokkal a jogkivonat nemcookie részének küldéséhez. A megvalósítás valószínűleg az ügyfélkód implementálásától függ. Néhány példa alább látható:

Osztályszintű példa:

[AutoValidateAntiforgeryToken]
public class HomeController : Controller

Globális példa:

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

Globális vagy vezérlő antiforgery attribútumok felülbírálása

Az IgnoreAntiforgeryToken szűrővel kiküszöbölhető az adott művelethez (vagy vezérlőhöz) tartozó antiforgery token szükségessége. Alkalmazásakor ez a szűrő felülbírálja a magasabb szinten (globálisan vagy vezérlőn) megadott ValidateAntiForgeryToken és AutoValidateAntiforgeryToken szűrőket.

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

    return RedirectToAction();
}

Jogkivonatok frissítése a hitelesítés után

A tokeneket a felhasználó hitelesítése után frissíteni kell úgy, hogy a felhasználót átirányítja egy felületre vagy Razor Pages oldalra.

JavaScript, AJAX és SLA-k

Hagyományos HTML-alapú alkalmazásokban rejtett űrlapmezőkön keresztül továbbítják az antiforgery jogkivonatokat a kiszolgálónak. A modern JavaScript-alapú alkalmazásokban és SLA-kban számos kérés programozott módon történik. Ezek az AJAX-kérések más technikákat, például kérésfejléceket vagy cookie-kat is használhatnak a jogkivonat elküldéséhez.

Ha a cookie-kat hitelesítési jogkivonatok tárolására és API-kérések hitelesítésére használják a kiszolgálón, a CSRF potenciális probléma. Ha a helyi tárolót a jogkivonat tárolására használják, a CSRF biztonsági rése csökkenthető, mivel a rendszer nem küldi el automatikusan a helyi tárolóból származó értékeket a kiszolgálónak minden kéréssel együtt. A helyi tároló használata az antiforgery token ügyfélen való tárolására és a token kérésfejlécben történő elküldésére ajánlott módszer.

Blazor

További információért lásd: ASP.NET Core Blazor hitelesítés és engedélyezés.

JavaScript

JavaScript nézetek használata esetén az azonosító egy szolgáltatás segítségével hozható létre a nézeten belül. Injektálja a IAntiforgery szolgáltatást a nézetbe, és hívja meg GetAndStoreTokens:

@inject Microsoft.AspNetCore.Antiforgery.IAntiforgery Antiforgery

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

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

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

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

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

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

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

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

Az előző példa JavaScript használatával olvassa be az AJAX POST fejléc rejtett mezőértékét.

Ez a megközelítés szükségtelenné teszi a cookie-k szerverről történő közvetlen beállítását vagy kliensről való közvetlen olvasását. Amikor azonban a IAntiforgery szolgáltatás injektálása nem lehetséges, használja a JavaScriptet a jogkivonatok eléréséhez a cookie-kban.

  • Hozzáférési jogkivonatok a kiszolgálóra irányuló további kérésekben, általában same-origin.
  • A cookietartalmát felhasználva hozzon létre egy fejlécet a token értékével.

Feltéve, hogy a szkript egy X-XSRF-TOKENnevű kérelemfejlécben küldi el a jogkivonatot, konfigurálja az antiforgery szolgáltatást a X-XSRF-TOKEN fejléc keresésére:

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

Az alábbi példa hozzáad egy védett végpontot, amely a kérés jogkivonatát egy JavaScript által olvasható cookie-ba írja.

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();

Az alábbi példa JavaScript használatával küld egy AJAX-kérést a token megszerzésére, és egy másik kérést a megfelelő fejléc alkalmazásával.

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}`
}

Jegyzet

Ha az antiforgery token mind a kérelem fejlécben, mind az űrlap hasznos adataiban szerepel, csak a fejlécben lévő token kerül érvényesítésre.

Az API-k minimálisra csökkentésével történő csalás elleni védelem

Hívja a AddAntiforgery és UseAntiforgery(IApplicationBuilder) elemeket az antiforgery szolgáltatások regisztrálására a DI-ben. Az antiforgery tokenek helyek közötti hamisítási támadásokmérséklésére szolgálnak.

var builder = WebApplication.CreateBuilder();

builder.Services.AddAntiforgery();

var app = builder.Build();

app.UseAntiforgery();

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

app.Run();

Az hamisításgátló köztesréteg:

Az antiforgery token csak akkor érvényes, ha:

  • A végpont olyan metaadatokat tartalmaz, amelyek implementálják az IAntiforgeryMetadata, ahol RequiresValidation=true.
  • A végponthoz társított HTTP-metódus egy releváns HTTP-metódus. A vonatkozó metódusok mind HTTP-metódusok, kivéve a TRACE, a OPTIONS, a HEAD és a GET metódusokat.
  • A kérés egy érvényes végponthoz van társítva.

Megjegyzés: Ha manuálisan van engedélyezve, az antiforgery köztes szoftvernek a hitelesítés és az engedélyezési köztes szoftver után kell futnia, hogy megakadályozza az űrlapadatok olvasását, ha a felhasználó nincs hitelesítve.

Az űrlapadatokat elfogadó minimális API-k alapértelmezés szerint hamisítás elleni token ellenőrzést igényelnek.

Fontolja meg a következő GenerateForm metódust:

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>
";
}

Az előző kód három argumentuma a művelet, az antiforgery token, és egy bool, amely jelzi, hogy a tokent használni kell-e.

Vegye figyelembe a következő mintát:

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>
    ";
    }
}

Az előző kódban a következő bejegyzéseket írja be:

  • /todo érvényes hamisítás elleni token szükséges.
  • /todo2 nem érvényes antiforgery tokent igényelnek, mert DisableAntiforgery van meghívva.
app.MapPost("/todo", ([FromForm] Todo todo) => Results.Ok(todo));

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

POST küldés címe:

  • /todo a / végpont által létrehozott űrlapból sikeres lesz, mert az antiforgery token érvényes.
  • /todo a /SkipToken által létrehozott űrlapon nem működik, mert a hamisítás elleni védelem nem szerepel.
  • /todo2 a /DisableAntiforgery végpont által létrehozott űrlapból sikeres lesz, mert nincs szükség antiforgery-ra.
app.MapPost("/todo", ([FromForm] Todo todo) => Results.Ok(todo));

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

Ha egy űrlapot hamisítás elleni token nélkül küldenek el:

  • A fejlesztési környezetben kivétel történik.
  • Az éles környezetben a rendszer naplózza az üzenetet.

Windows-hitelesítés és hamisítást gátló sütik

A Windows-hitelesítés használatakor az alkalmazásvégpontokat ugyanúgy kell védeni a CSRF-támadások ellen, mint a cookie-k esetében. A böngésző implicit módon elküldi a hitelesítési környezetet a kiszolgálónak, és a végpontokat védeni kell a CSRF-támadások ellen.

Antiforgery kiterjesztése

A IAntiforgeryAdditionalDataProvider típus lehetővé teszi a fejlesztők számára a CSRF-ellenes rendszer viselkedésének kiterjesztését az egyes tokenekben történő további adatcserével. A GetAdditionalData metódust minden alkalommal meghívják, amikor létrehoz egy mezőt, és a visszatérési érték a létrehozott mezőben van beágyazva. A megvalósító visszaadhat egy időbélyeget, egy egyedi azonosítót vagy bármilyen más értéket, majd meghívhatja a ValidateAdditionalData függvényt, amikor a jogkivonat érvényesítésre kerül, hogy érvényesítse ezeket az adatokat. Az ügyfél felhasználóneve már be van ágyazva a létrehozott tokenekbe, így nincs szükség ezen információk külön feltüntetésére. Ha egy token kiegészítő adatokat tartalmaz, de nincs konfigurálva IAntiForgeryAdditionalDataProvider, akkor a kiegészítő adatokat nem érvényesítik.

További erőforrások

A webhelyek közötti kérelemhamisítás (más néven XSRF vagy CSRF) a webalkalmazások elleni támadás, amelynek során egy rosszindulatú webalkalmazás befolyásolhatja az ügyfélböngésző és az a böngésző által megbízhatónak tartott webalkalmazás közötti interakciót. Ezek a támadások azért lehetségesek, mert a webböngészők minden kéréssel automatikusan küldenek bizonyos hitelesítési jogkivonatokat egy webhelyre. Ezt a biztonsági rést egykattintásos támadásnak is nevezik, vagy munkamenet-eltérítésnek, mert kihasználja a felhasználó korábban hitelesített munkamenetét.

Példa CSRF-támadásra:

  1. A felhasználó űrlap-hitelesítéssel jelentkezik be www.good-banking-site.example.com. A kiszolgáló hitelesíti a felhasználót, és egy hitelesítési cookietartalmazó választ ad ki. A webhely sebezhető a támadásokkal szemben, mert megbízik minden olyan kérésben, amelyet érvényes hitelesítési cookiekap.

  2. A felhasználó meglátogat egy rosszindulatú webhelyet, www.bad-crook-site.example.com.

    A kártékony webhely (www.bad-crook-site.example.com) az alábbi példához hasonló HTML-űrlapot tartalmaz:

    <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>
    

    Figyelje meg, hogy az űrlap action a sebezhető webhelyre, nem pedig a rosszindulatú webhelyre. Ez a CSRF "keresztoldali" része.

  3. A felhasználó kiválasztja a Küldés gombot. A böngésző a kérést végrehajtja, és automatikusan tartalmazza a cookie hitelesítést a kért tartományhoz, www.good-banking-site.example.com.

  4. A kérés a www.good-banking-site.example.com kiszolgálón fut a felhasználó hitelesítési környezetével, és bármilyen műveletet végrehajthat, amelyet egy hitelesített felhasználó végrehajthat.

Azon forgatókönyv mellett, amikor a felhasználó kiválasztja az űrlap elküldéséhez a gombot, a rosszindulatú webhely a következőt teheti:

  • Futtasson egy szkriptet, amely automatikusan elküldi az űrlapot.
  • Küldje el az űrlap beküldését AJAX-kérelemként.
  • Rejtse el az űrlapot a CSS használatával.

Ezek az alternatív forgatókönyvek nem igényelnek semmilyen műveletet vagy bemenetet a felhasználótól, kivéve, ha eredetileg meglátogatják a rosszindulatú webhelyet.

A HTTPS használata nem akadályozza meg a CSRF-támadást. A rosszindulatú webhely éppoly könnyen küldhet https://www.good-banking-site.example.com/ kérést, mint egy nem biztonságosat.

Egyes támadások a GET-kérelmekre reagáló végpontokat támadják meg, ebben az esetben egy képcímke használható a művelet végrehajtásához. Ez a támadási forma gyakori a fórumwebhelyeken, amelyek lehetővé teszik a képeket, de letiltják a JavaScriptet. A GET-kérések állapotát módosító alkalmazások, amelyek változókat vagy erőforrásokat módosítanak, sebezhetők a rosszindulatú támadásokkal szemben. Az állapotot módosító GET-kérelmek nem biztonságosak. Ajánlott eljárás, hogy soha ne változtassunk állapotot GET-kérés során.

A CSRF-támadások a hitelesítéshez cookie-kat használó webalkalmazások ellen lehetségesek, mert:

  • A böngészők egy webalkalmazás által kibocsátott cookie-kat tárolnak.
  • A tárolt cookie-k munkamenet-cookie-kat tartalmaznak a hitelesített felhasználók számára.
  • A böngészők minden, tartományhoz társított cookie-t elküldenek a webalkalmazásnak, függetlenül attól, hogy az alkalmazáskérés hogyan jött létre a böngészőben.

A CSRF-támadások azonban nem korlátozódnak a cookie-k kihasználására. Az alapszintű és a kivonatoló hitelesítés például sebezhető. Miután egy felhasználó bejelentkezett alapszintű vagy kivonatoló hitelesítéssel, a böngésző automatikusan elküldi a hitelesítő adatokat, amíg a munkamenet véget nem ér.

Ebben az összefüggésben munkamenet arra az ügyféloldali munkamenetre vonatkozik, amely során a felhasználó hitelesítése megtörtént. Nem kapcsolódik kiszolgálóoldali munkamenetekhez vagy ASP.NET Core Session Middleware.

A felhasználók óvintézkedéseket tehetnek a CSRF biztonsági rései ellen:

  • Kijelentkezés a webalkalmazásból, ha befejezte a használatukat.
  • A böngésző cookie-inak rendszeres törlése.

A CSRF biztonsági rései azonban alapvetően a webalkalmazással, nem pedig a végfelhasználóval kapcsolatos problémák.

A hitelesítés alapjai

Cookie-alapú hitelesítés a hitelesítés népszerű formája. A token alapú hitelesítési rendszerek egyre népszerűbbek, különösen az egyoldalas alkalmazások (SPA-k) esetében.

Amikor egy felhasználó a saját felhasználónevével és jelszavával hitelesít, a rendszer egy jogkivonatot ad ki, amely tartalmaz egy hitelesítési jegyet, és ez felhasználható további hitelesítéshez és engedélyezéshez. A tokent egy cookie-ként tárolják, amelyet minden kérésnél az ügyféllel együtt küldenek. A cookie generálását és érvényesítését a Cookie Hitelesítési köztes szoftver végzi. A köztes szoftver egy felhasználónevet titkosított cookieszerializál. A következő kérések során a köztes szoftver ellenőrzi a cookie-t, újra létrehozza a főkomponenst, és hozzárendeli a főkomponenst a HttpContext.User tulajdonsághoz.

Tokenalapú hitelesítés

Ha egy felhasználó hitelesítése megtörtént, a rendszer tokent ad ki (nem pedig antiforgery tokent). A jogkivonat felhasználói adatokat tartalmaz jogcímek formájában, vagy egy hivatkozási jogkivonat formájában, amely az alkalmazást az alkalmazásban fenntartott felhasználói állapotra mutatja. Amikor egy felhasználó megpróbál hozzáférni egy hitelesítést igénylő erőforráshoz, a rendszer a jogkivonatot egy további engedélyezési fejléccel továbbítja az alkalmazásnak tulajdonosi jogkivonat formájában. Ez a megközelítés állapot nélkülivé teszi az alkalmazást. Minden további kérésben a jogkivonat továbbításra kerül a kiszolgálóoldali érvényesítéshez. Ez a jogkivonat nem titkosított; kódolt. A kiszolgálón a rendszer dekódolja a jogkivonatot, hogy hozzáférjen az adataihoz. A jogkivonat későbbi kérésekre való elküldéséhez tárolja a jogkivonatot a böngésző helyi tárolójában. Ha a jogkivonatot a böngésző helyi tárolójában helyezi el, lekérte és tulajdonosi jogkivonatként használja, védelmet nyújt a CSRF-támadások ellen. Ha azonban az alkalmazás sebezhető az XSS-en keresztüli szkriptinjektálással vagy egy feltört külső JavaScript-fájllal, a kibertámadás bármilyen értéket lekérhet a helyi tárolóból, és elküldheti saját magának. ASP.NET Core alapértelmezés szerint a változók összes kiszolgálóoldali kimenetét kódolja, így csökkenti az XSS kockázatát. Ha ezt a viselkedést Html.Raw vagy nem megbízható bemenettel rendelkező egyéni kóddal bírálja felül, akkor növelheti az XSS kockázatát.

Ne aggódjon a CSRF biztonsági rése miatt, ha a jogkivonat a böngésző helyi tárolójában van tárolva. A CSRF aggodalomra ad okot, ha a tokent egy cookie-ban tárolják. További információért lásd a GitHub probléma oldalt: az SPA kódminta két cookie-t ad hozzá.

Több, egy tartományban üzemeltetett alkalmazás

A megosztott üzemeltetési környezetek sebezhetők a munkamenet-eltérítés, a bejelentkezési CSRF és más támadások ellen.

Bár example1.contoso.net és example2.contoso.net különböző gazdagépek, implicit megbízhatósági kapcsolat áll fenn a *.contoso.net tartománybeli gazdagépek között. Ez az implicit megbízhatósági kapcsolat lehetővé teszi, hogy a potenciálisan nem megbízható gazdagépek befolyásolják egymás cookie-jait (az AJAX-kéréseket szabályozó azonos eredetű szabályzatok nem feltétlenül vonatkoznak a HTTP-cookie-kra).

Az ugyanazon a tartományon üzemeltetett alkalmazások közötti megbízható cookie-kat kihasználó támadások megelőzhetők, ha nem osztanak meg tartományokat. Ha az egyes alkalmazásokat a saját tartományában üzemeltetik, nincs kihasználandó implicit cookie megbízhatósági kapcsolat.

Antiforgery az ASP.NET Core-ban

Figyelmeztetés

ASP.NET Core a ASP.NET Core Data Protectionhasználatával implementálja a hamisítás elleni védelmet. Az adatvédelmi vermet úgy kell konfigurálni, hogy egy kiszolgálófarmban működjön. További információért lásd: Az adatvédelem konfigurálása.

Antiforgery middleware kerül be a függőség-injektálási tárolóba, ha az alábbi API-k egyikét meghívják Program.cs:

A FormTagHelper hamisításgátló tokeneket injektál a HTML-űrlapelemekbe. Egy Razor fájlban a következő korrektúra automatikusan létrehozza az antiforgery tokeneket:

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

Hasonlóképpen, IHtmlHelper.BeginForm alapértelmezés szerint antiforgery tokeneket hoz létre, ha az űrlap metódusa nem GET.

A HTML-űrlapelemek antiforgery tokenjeinek automatikus létrehozása akkor történik, ha a <form> címke tartalmazza a method="post" attribútumot, és az alábbiak bármelyike igaz:

  • A műveletattribútum üres (action="").
  • A műveletattribútum nincs megadva (<form method="post">).

A HTML-űrlapelemekhez tartozó antiforgery tokenek automatikus létrehozása letiltható:

  • Explicit módon tiltsa le az antiforgery tokeneket a asp-antiforgery attribútummal:

    <form method="post" asp-antiforgery="false">
        <!-- ... -->
    </form>
    
  • Az űrlapelem ki van zárva a Címkesegítők közül a Tag Helper ! opt-out szimbólumokhasználatával.

    <!form method="post">
        <!-- ... -->
    </!form>
    
  • Távolítsa el a FormTagHelper a nézetből. A FormTagHelper eltávolítható egy nézetből az alábbi irányelv Razor nézethez való hozzáadásával:

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

Jegyzet

Razor lapok automatikusan védettek az XSRF/CSRF támadások ellen. További információ: XSRF/CSRF és Razor Pages.

A CSRF-támadások elleni védelem leggyakoribb módja a szinkronizáló jogkivonat-minta (STP) használata. Az STP akkor használatos, ha a felhasználó űrlapadatokat tartalmazó lapot kér:

  1. A kiszolgáló egy jogkivonatot küld a kliensnek, amely az aktuális felhasználó identitásához van társítva.
  2. Az ügyfél visszaküldi a jogkivonatot a kiszolgálónak ellenőrzés céljából.
  3. Ha a kiszolgáló olyan jogkivonatot kap, amely nem egyezik a hitelesített felhasználó identitásával, a rendszer elutasítja a kérést.

A token egyedi és kiszámíthatatlan. A jogkivonat arra is használható, hogy biztosítsa a kérelmek sorozatának megfelelő sorrendjét (például a következő kérelmek sorrendjének biztosításához: 1. oldal > 2. oldal > 3. oldal). Az összes ASP.NET Core MVC és Razor Pages sablonú űrlap valahogy antiforgery tokeneket hoz létre. A következő példanézet-páros antiforgery biztonsági tokeneket hoz létre:

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

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

Kifejezetten adjon hozzá egy hamisítás elleni tokent egy <form> elemhez a Tag Helper és a HTML-segéd használata nélkül @Html.AntiForgeryToken.

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

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

Az előző esetekben ASP.NET Core az alábbi példához hasonló rejtett űrlapmezőt ad hozzá:

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

ASP.NET Core három szűrőt tartalmaz, az antiforgery tokenek használatát:

Hamisításvédelem AddControllers

A AddControllers hívása nem engedélyezni az antiforgery tokeneket. A AddControllersWithViews-t meg kell hívni, hogy beépített hamisításgátló token-támogatással rendelkezzen.

Több böngészőlap és a szinkronizáló token sablon

A Szinkronizáló Token Mintázat esetében csak a legutóbb betöltött oldal tartalmaz érvényes hamisítás elleni tokent. Több lap használata problémás lehet. Ha például egy felhasználó több lapot nyit meg:

  • Csak a legutóbb betöltött lap tartalmaz érvényes antiforgery tokent.
  • A korábban betöltött lapokról érkező kérések hiba miatt meghiúsulnak: Antiforgery token validation failed. The antiforgery cookie token and request token do not match

Ha ez problémát okoz, fontolja meg az alternatív CSRF-védelmi mintákat.

Antiforgery konfigurálása AntiforgeryOptions

AntiforgeryOptions testreszabása a Program.cs-en:

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

Állítsa be az antiforgery Cookie tulajdonságokat a CookieBuilder osztály tulajdonságaival, ahogyan az az alábbi táblázatban látható.

Opció Leírás
Cookie Meghatározza az antiforgery cookie-k létrehozásához használt beállításokat.
FormFieldName Annak a rejtett űrlapmezőnek a neve, amelyet az antiforgery rendszer használ az antiforgery tokenek nézetekben való megjelenítéséhez.
HeaderName Az antiforgery rendszer által használt fejléc neve. Ha null, a rendszer csak az űrlapadatokat veszi figyelembe.
SuppressXFrameOptionsHeader Megadja, hogy el kívánja-e tiltani a X-Frame-Options fejléc generálását. Alapértelmezés szerint a fejléc "SAMEORIGIN" értékkel jön létre. Alapértelmezés szerint false.

További információ: CookieAuthenticationOptions.

Antiforgery tokenek létrehozása IAntiforgery

IAntiforgery biztosítja az API-t az antiforgery funkciók konfigurálásához. IAntiforgery a Program.cshasználatával kérhető meg WebApplication.Services-ben. Az alábbi példa az alkalmazás kezdőlapjáról származó köztes szoftvereket használ egy antiforgery jogkivonat létrehozásához, és cookieként küldi el a válaszba:

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

Az előző példa egy cookie nevű XSRF-TOKEN-et állít be. Az ügyfél elolvashatja ezt a cookie, és az AJAX-kérelmekhez csatolt fejlécként megadhatja az értékét. Az Angular például beépített XSRF-védelmet tartalmaz, amely alapértelmezés szerint egy cookie nevű XSRF-TOKEN-t olvas be.

Hamisítás elleni ellenőrzés megkövetelése

Az ValidateAntiForgeryToken műveletszűrő egyéni műveletekre, vezérlőkre vagy globálisan alkalmazható. A szűrőt alkalmazó műveletekre irányuló kérések le lesznek tiltva, kivéve, ha a kérés érvényes antiforgery-jogkivonatot tartalmaz:

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

    return RedirectToAction();
}

A ValidateAntiForgeryToken attribútumhoz jogkivonatra van szükség az általa jelölt műveleti módszerekre irányuló kérelmekhez, beleértve a HTTP GET-kérelmeket is. Ha az alkalmazás vezérlőire a ValidateAntiForgeryToken attribútum van alkalmazva, akkor a IgnoreAntiforgeryToken attribútummal felülírható.

Az antiforgery tokenek automatikus ellenőrzése csak a nem biztonságos HTTP-metódusok esetén történik meg.

Ahelyett, hogy a ValidateAntiForgeryToken attribútumot általánosan alkalmazná, majd felülírná IgnoreAntiforgeryToken attribútumokkal, az AutoValidateAntiforgeryToken attribútum használható. Ez az attribútum ugyanúgy működik, mint a ValidateAntiForgeryToken attribútum, azzal a különbségkel, hogy nem igényel jogkivonatokat a következő HTTP-metódusokkal végrehajtott kérelmekhez:

  • SZEREZZ
  • FEJ
  • OPCIÓK
  • NYOM

Javasoljuk a AutoValidateAntiforgeryToken széles körű használatát nem API-szcenáriókhoz. Ez az attribútum biztosítja, hogy a POST-műveletek alapértelmezés szerint védettek legyenek. A másik lehetőség az, hogy alapértelmezés szerint figyelmen kívül hagyja az antiforgery tokeneket, kivéve, ha ValidateAntiForgeryToken az egyes műveleti módszerekre van alkalmazva. Ebben a forgatókönyvben valószínűbb, hogy egy POST-műveletmetódus véletlenül védtelen marad, így az alkalmazás sebezhető lesz a CSRF-támadásokkal szemben. Minden POST-nak el kell küldenie a hamisítás elleni tokent.

Az API-k nem rendelkeznek automatikus mechanizmusokkal a jogkivonat nemcookie részének küldéséhez. A megvalósítás valószínűleg az ügyfélkód implementálásától függ. Néhány példa alább látható:

Osztályszintű példa:

[AutoValidateAntiforgeryToken]
public class HomeController : Controller

Globális példa:

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

Globális vagy vezérlő antiforgery attribútumok felülbírálása

Az IgnoreAntiforgeryToken szűrővel kiküszöbölhető az adott művelethez (vagy vezérlőhöz) tartozó antiforgery token szükségessége. Alkalmazásakor ez a szűrő felülbírálja a magasabb szinten (globálisan vagy vezérlőn) megadott ValidateAntiForgeryToken és AutoValidateAntiforgeryToken szűrőket.

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

    return RedirectToAction();
}

Jogkivonatok frissítése a hitelesítés után

A tokeneket a felhasználó hitelesítése után frissíteni kell úgy, hogy a felhasználót átirányítja egy felületre vagy Razor Pages oldalra.

JavaScript, AJAX és SLA-k

Hagyományos HTML-alapú alkalmazásokban rejtett űrlapmezőkön keresztül továbbítják az antiforgery jogkivonatokat a kiszolgálónak. A modern JavaScript-alapú alkalmazásokban és SLA-kban számos kérés programozott módon történik. Ezek az AJAX-kérések más technikákat (például kérésfejléceket vagy cookie-kat) is használhatnak a jogkivonat elküldéséhez.

Ha a cookie-kat hitelesítési jogkivonatok tárolására és API-kérések hitelesítésére használják a kiszolgálón, a CSRF potenciális probléma. Ha a helyi tárolót a jogkivonat tárolására használják, a CSRF biztonsági rése csökkenthető, mivel a rendszer nem küldi el automatikusan a helyi tárolóból származó értékeket a kiszolgálónak minden kéréssel együtt. A helyi tároló használata az antiforgery token ügyfélen való tárolására és a token kérésfejlécben történő elküldésére ajánlott módszer.

JavaScript

JavaScript nézetek használata esetén az azonosító egy szolgáltatás segítségével hozható létre a nézeten belül. Injektálja a IAntiforgery szolgáltatást a nézetbe, és hívja meg GetAndStoreTokens:

@inject Microsoft.AspNetCore.Antiforgery.IAntiforgery Antiforgery

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

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

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

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

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

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

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

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

Az előző példa JavaScript használatával olvassa be az AJAX POST fejléc rejtett mezőértékét.

Ez a megközelítés szükségtelenné teszi a cookie-k szerverről történő közvetlen beállítását vagy kliensről való közvetlen olvasását. Amikor azonban a IAntiforgery szolgáltatás injektálása nem lehetséges, használja a JavaScriptet a jogkivonatok eléréséhez a cookie-kban.

  • Hozzáférési jogkivonatok a kiszolgálóra irányuló további kérésekben, általában same-origin.
  • A cookietartalmát felhasználva hozzon létre egy fejlécet a token értékével.

Feltéve, hogy a szkript egy X-XSRF-TOKENnevű kérelemfejlécben küldi el a jogkivonatot, konfigurálja az antiforgery szolgáltatást a X-XSRF-TOKEN fejléc keresésére:

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

Az alábbi példa hozzáad egy védett végpontot, amely a kérés jogkivonatát egy JavaScript által olvasható cookie-ba írja.

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();

Az alábbi példa JavaScript használatával küld egy AJAX-kérést a token megszerzésére, és egy másik kérést a megfelelő fejléc alkalmazásával.

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}`
}

Jegyzet

Ha az antiforgery token mind a kérelem fejlécben, mind az űrlap hasznos adataiban szerepel, csak a fejlécben lévő token kerül érvényesítésre.

Az API-k minimálisra csökkentésével történő csalás elleni védelem

Minimal APIs nem támogatják a mellékelt szűrők (ValidateAntiForgeryToken, AutoValidateAntiforgeryToken, IgnoreAntiforgeryToken) használatát, azonban IAntiforgery biztosítja a kérések érvényesítéséhez szükséges API-kat.

Az alábbi példa létrehoz egy szűrőt, amely ellenőrzi az antiforgery tokent:

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

        });
    }
}

A szűrő ezután alkalmazható egy végpontra:

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

Windows-hitelesítés és hamisítást gátló sütik

A Windows-hitelesítés használatakor az alkalmazásvégpontokat ugyanúgy kell védeni a CSRF-támadások ellen, mint a cookie-k esetében. A böngésző implicit módon elküldi a hitelesítési környezetet a kiszolgálónak, és a végpontokat védeni kell a CSRF-támadások ellen.

Antiforgery kiterjesztése

A IAntiforgeryAdditionalDataProvider típus lehetővé teszi a fejlesztők számára a CSRF-ellenes rendszer viselkedésének kiterjesztését az egyes tokenekben történő további adatcserével. A GetAdditionalData metódust minden alkalommal meghívják, amikor létrehoz egy mezőt, és a visszatérési érték a létrehozott mezőben van beágyazva. A megvalósító visszaadhat egy időbélyeget, egy egyedi azonosítót vagy bármilyen más értéket, majd meghívhatja a ValidateAdditionalData függvényt, amikor a jogkivonat érvényesítésre kerül, hogy érvényesítse ezeket az adatokat. Az ügyfél felhasználóneve már be van ágyazva a létrehozott tokenekbe, így nincs szükség ezen információk külön feltüntetésére. Ha egy token kiegészítő adatokat tartalmaz, de nincs konfigurálva IAntiForgeryAdditionalDataProvider, akkor a kiegészítő adatokat nem érvényesítik.

További erőforrások

A webhelyek közötti kérelemhamisítás (más néven XSRF vagy CSRF) a webalkalmazások elleni támadás, amelynek során egy rosszindulatú webalkalmazás befolyásolhatja az ügyfélböngésző és az a böngésző által megbízhatónak tartott webalkalmazás közötti interakciót. Ezek a támadások azért lehetségesek, mert a webböngészők minden kéréssel automatikusan küldenek bizonyos hitelesítési jogkivonatokat egy webhelyre. Ezt a biztonsági rést egykattintásos támadásnak is nevezik, vagy munkamenet-eltérítésnek, mert kihasználja a felhasználó korábban hitelesített munkamenetét.

Példa CSRF-támadásra:

  1. A felhasználó űrlap-hitelesítéssel jelentkezik be www.good-banking-site.example.com. A kiszolgáló hitelesíti a felhasználót, és egy hitelesítési cookietartalmazó választ ad ki. A webhely sebezhető a támadásokkal szemben, mert megbízik minden olyan kérésben, amelyet érvényes hitelesítési cookiekap.

  2. A felhasználó meglátogat egy rosszindulatú webhelyet, www.bad-crook-site.example.com.

    A kártékony webhely (www.bad-crook-site.example.com) az alábbi példához hasonló HTML-űrlapot tartalmaz:

    <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>
    

    Figyelje meg, hogy az űrlap action a sebezhető webhelyre, nem pedig a rosszindulatú webhelyre. Ez a CSRF "keresztoldali" része.

  3. A felhasználó kiválasztja a Küldés gombot. A böngésző a kérést végrehajtja, és automatikusan tartalmazza a cookie hitelesítést a kért tartományhoz, www.good-banking-site.example.com.

  4. A kérés a www.good-banking-site.example.com kiszolgálón fut a felhasználó hitelesítési környezetével, és bármilyen műveletet végrehajthat, amelyet egy hitelesített felhasználó végrehajthat.

Azon forgatókönyv mellett, amikor a felhasználó kiválasztja az űrlap elküldéséhez a gombot, a rosszindulatú webhely a következőt teheti:

  • Futtasson egy szkriptet, amely automatikusan elküldi az űrlapot.
  • Küldje el az űrlap beküldését AJAX-kérelemként.
  • Rejtse el az űrlapot a CSS használatával.

Ezek az alternatív forgatókönyvek nem igényelnek semmilyen műveletet vagy bemenetet a felhasználótól, kivéve, ha eredetileg meglátogatják a rosszindulatú webhelyet.

A HTTPS használata nem akadályozza meg a CSRF-támadást. A rosszindulatú webhely ugyanúgy küldhet https://www.good-banking-site.example.com/ kérést, mint egy nem biztonságos kérést.

Egyes támadások a GET-kérelmekre reagáló végpontokat támadják meg, ebben az esetben egy képcímke használható a művelet végrehajtásához. Ez a támadási forma gyakori a fórumwebhelyeken, amelyek lehetővé teszik a képeket, de letiltják a JavaScriptet. A GET-kérések állapotát módosító alkalmazások, amelyek változókat vagy erőforrásokat módosítanak, sebezhetők a rosszindulatú támadásokkal szemben. Az állapotot módosító GET-kérelmek nem biztonságosak. Ajánlott eljárás, hogy soha ne változtassunk állapotot GET-kérés során.

A CSRF-támadások a hitelesítéshez cookie-kat használó webalkalmazások ellen lehetségesek, mert:

  • A böngészők egy webalkalmazás által kibocsátott cookie-kat tárolnak.
  • A tárolt cookie-k munkamenet-cookie-kat tartalmaznak a hitelesített felhasználók számára.
  • A böngészők minden, tartományhoz társított cookie-t elküldenek a webalkalmazásnak, függetlenül attól, hogy az alkalmazáskérés hogyan jött létre a böngészőben.

A CSRF-támadások azonban nem korlátozódnak a cookie-k kihasználására. Az alapszintű és a kivonatoló hitelesítés például sebezhető. Miután egy felhasználó bejelentkezett alapszintű vagy kivonatoló hitelesítéssel, a böngésző automatikusan elküldi a hitelesítő adatokat, amíg a munkamenet véget nem ér.

Ebben az összefüggésben munkamenet arra az ügyféloldali munkamenetre vonatkozik, amely során a felhasználó hitelesítése megtörtént. Nem kapcsolódik kiszolgálóoldali munkamenetekhez vagy ASP.NET Core Session Middleware.

A felhasználók óvintézkedéseket tehetnek a CSRF biztonsági rései ellen:

  • Kijelentkezés a webalkalmazásból, ha befejezte a használatukat.
  • A böngésző cookie-inak rendszeres törlése.

A CSRF biztonsági rései azonban alapvetően a webalkalmazással, nem pedig a végfelhasználóval kapcsolatos problémák.

A hitelesítés alapjai

Cookie-alapú hitelesítés a hitelesítés népszerű formája. A token alapú hitelesítési rendszerek egyre népszerűbbek, különösen az egyoldalas alkalmazások (SPA-k) esetében.

Amikor egy felhasználó a saját felhasználónevével és jelszavával hitelesít, a rendszer egy jogkivonatot ad ki, amely tartalmaz egy hitelesítési jegyet, és ez felhasználható további hitelesítéshez és engedélyezéshez. A tokent egy cookie-ként tárolják, amelyet minden kérésnél az ügyféllel együtt küldenek. A cookie generálását és érvényesítését a Cookie Hitelesítési köztes szoftver végzi. A köztes szoftver egy felhasználónevet titkosított cookieszerializál. A következő kérések során a köztes szoftver ellenőrzi a cookie-t, újra létrehozza a főkomponenst, és hozzárendeli a főkomponenst a HttpContext.User tulajdonsághoz.

Tokenalapú hitelesítés

Ha egy felhasználó hitelesítése megtörtént, a rendszer tokent ad ki (nem pedig antiforgery tokent). A jogkivonat felhasználói adatokat tartalmaz jogcímek formájában, vagy egy hivatkozási jogkivonat formájában, amely az alkalmazást az alkalmazásban fenntartott felhasználói állapotra mutatja. Amikor egy felhasználó megpróbál hozzáférni egy hitelesítést igénylő erőforráshoz, a rendszer a jogkivonatot egy további engedélyezési fejléccel továbbítja az alkalmazásnak tulajdonosi jogkivonat formájában. Ez a megközelítés állapot nélkülivé teszi az alkalmazást. Minden további kérésben a jogkivonat továbbításra kerül a kiszolgálóoldali érvényesítéshez. Ez a jogkivonat nem titkosított; kódolt. A kiszolgálón a rendszer dekódolja a jogkivonatot, hogy hozzáférjen az adataihoz. A jogkivonat későbbi kérésekre való elküldéséhez tárolja a jogkivonatot a böngésző helyi tárolójában. Ne aggódjon a CSRF biztonsági rése miatt, ha a jogkivonat a böngésző helyi tárolójában van tárolva. A CSRF aggodalomra ad okot, ha a tokent egy cookie-ban tárolják. További információért lásd a GitHub probléma oldalt: az SPA kódminta két cookie-t ad hozzá.

Több, egy tartományban üzemeltetett alkalmazás

A megosztott üzemeltetési környezetek sebezhetők a munkamenet-eltérítés, a bejelentkezési CSRF és más támadások ellen.

Bár example1.contoso.net és example2.contoso.net különböző gazdagépek, implicit megbízhatósági kapcsolat áll fenn a *.contoso.net tartománybeli gazdagépek között. Ez az implicit megbízhatósági kapcsolat lehetővé teszi, hogy a potenciálisan nem megbízható gazdagépek befolyásolják egymás cookie-jait (az AJAX-kéréseket szabályozó azonos eredetű szabályzatok nem feltétlenül vonatkoznak a HTTP-cookie-kra).

Az ugyanazon a tartományon üzemeltetett alkalmazások közötti megbízható cookie-kat kihasználó támadások megelőzhetők, ha nem osztanak meg tartományokat. Ha az egyes alkalmazásokat a saját tartományában üzemeltetik, nincs kihasználandó implicit cookie megbízhatósági kapcsolat.

Antiforgery az ASP.NET Core-ban

Figyelmeztetés

ASP.NET Core a ASP.NET Core Data Protectionhasználatával implementálja a hamisítás elleni védelmet. Az adatvédelmi vermet úgy kell konfigurálni, hogy egy kiszolgálófarmban működjön. További információért lásd: Az adatvédelem konfigurálása.

Antiforgery middleware kerül be a függőség-injektálási tárolóba, ha az alábbi API-k egyikét meghívják Program.cs:

A FormTagHelper hamisításgátló tokeneket injektál a HTML-űrlapelemekbe. Egy Razor fájlban a következő korrektúra automatikusan létrehozza az antiforgery tokeneket:

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

Hasonlóképpen, IHtmlHelper.BeginForm alapértelmezés szerint antiforgery tokeneket hoz létre, ha az űrlap metódusa nem GET.

A HTML-űrlapelemek antiforgery tokenjeinek automatikus létrehozása akkor történik, ha a <form> címke tartalmazza a method="post" attribútumot, és az alábbiak bármelyike igaz:

  • A műveletattribútum üres (action="").
  • A műveletattribútum nincs megadva (<form method="post">).

A HTML-űrlapelemekhez tartozó antiforgery tokenek automatikus létrehozása letiltható:

  • Explicit módon tiltsa le az antiforgery tokeneket a asp-antiforgery attribútummal:

    <form method="post" asp-antiforgery="false">
        <!-- ... -->
    </form>
    
  • Az űrlapelem ki van zárva a Címkesegítők közül a Tag Helper ! opt-out szimbólumokhasználatával.

    <!form method="post">
        <!-- ... -->
    </!form>
    
  • Távolítsa el a FormTagHelper a nézetből. A FormTagHelper eltávolítható egy nézetből az alábbi irányelv Razor nézethez való hozzáadásával:

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

Jegyzet

Razor lapok automatikusan védettek az XSRF/CSRF támadások ellen. További információ: XSRF/CSRF és Razor Pages.

A CSRF-támadások elleni védelem leggyakoribb módja a szinkronizáló jogkivonat-minta (STP) használata. Az STP akkor használatos, ha a felhasználó űrlapadatokat tartalmazó lapot kér:

  1. A kiszolgáló az aktuális felhasználó identitásához társított jogkivonatot küld a kliensnek.
  2. Az ügyfél visszaküldi a jogkivonatot a kiszolgálónak ellenőrzés céljából.
  3. Ha a kiszolgáló olyan jogkivonatot kap, amely nem egyezik a hitelesített felhasználó identitásával, a rendszer elutasítja a kérést.

A token egyedi és kiszámíthatatlan. A jogkivonat arra is használható, hogy biztosítsa a kérelmek sorozatának megfelelő sorrendjét (például a következő kérelmek sorrendjének biztosításához: 1. oldal > 2. oldal > 3. oldal). Az összes ASP.NET Core MVC és Razor Pages sablonú űrlap valahogy antiforgery tokeneket hoz létre. A következő példanézet-páros antiforgery biztonsági tokeneket hoz létre:

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

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

Kifejezetten adjon hozzá egy hamisítás elleni tokent egy <form> elemhez a Tag Helper és a HTML-segéd használata nélkül @Html.AntiForgeryToken.

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

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

Az előző esetekben ASP.NET Core az alábbi példához hasonló rejtett űrlapmezőt ad hozzá:

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

ASP.NET Core három szűrőt tartalmaz, az antiforgery tokenek használatát:

Hamisítás elleni védelem az AddControllers használatával

A AddControllers hívása nem engedélyezni az antiforgery tokeneket. A AddControllersWithViews-t meg kell hívni, hogy beépített hamisításgátló token-támogatással rendelkezzen.

Több böngészőlap és a szinkronizáló token sablon

A Szinkronizáló Token Mintázat esetében csak a legutóbb betöltött oldal tartalmaz érvényes hamisítás elleni tokent. Több lap használata problémás lehet. Ha például egy felhasználó több lapot nyit meg:

  • Csak a legutóbb betöltött lap tartalmaz érvényes antiforgery tokent.
  • A korábban betöltött lapokról érkező kérések hiba miatt meghiúsulnak: Antiforgery token validation failed. The antiforgery cookie token and request token do not match

Ha ez problémát okoz, fontolja meg az alternatív CSRF-védelmi mintákat.

Antiforgery konfigurálása AntiforgeryOptions

AntiforgeryOptions testreszabása a Program.cs-en:

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

Állítsa be az antiforgery Cookie tulajdonságokat a CookieBuilder osztály tulajdonságaival, ahogyan az az alábbi táblázatban látható.

Opció Leírás
Cookie Meghatározza az antiforgery cookie-k létrehozásához használt beállításokat.
FormFieldName Annak a rejtett űrlapmezőnek a neve, amelyet az antiforgery rendszer használ az antiforgery tokenek nézetekben való megjelenítéséhez.
HeaderName Az antiforgery rendszer által használt fejléc neve. Ha null, a rendszer csak az űrlapadatokat veszi figyelembe.
SuppressXFrameOptionsHeader Megadja, hogy el kívánja-e tiltani a X-Frame-Options fejléc generálását. Alapértelmezés szerint a fejléc "SAMEORIGIN" értékkel jön létre. Alapértelmezés szerint false.

További információ: CookieAuthenticationOptions.

Antiforgery tokenek létrehozása IAntiforgery

IAntiforgery biztosítja az API-t az antiforgery funkciók konfigurálásához. IAntiforgery a Program.cshasználatával kérhető meg WebApplication.Services-ben. Az alábbi példa az alkalmazás kezdőlapján található köztes szoftvert használja egy antiforgery token létrehozásához, és a válasz részeként küldi el mint 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);
});

Az előző példa egy cookie nevű XSRF-TOKEN-et állít be. Az ügyfél elolvashatja ezt a cookie, és az AJAX-kérelmekhez csatolt fejlécként megadhatja az értékét. Az Angular például beépített XSRF-védelmet tartalmaz, amely alapértelmezés szerint egy cookie nevű XSRF-TOKEN-t olvas be.

Hamisítás elleni ellenőrzés megkövetelése

Az ValidateAntiForgeryToken műveletszűrő egyéni műveletekre, vezérlőkre vagy globálisan alkalmazható. A szűrőt alkalmazó műveletekre irányuló kérések le lesznek tiltva, kivéve, ha a kérés érvényes antiforgery-jogkivonatot tartalmaz:

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

    return RedirectToAction();
}

A ValidateAntiForgeryToken attribútumhoz jogkivonatra van szükség az általa jelölt műveleti módszerekre irányuló kérelmekhez, beleértve a HTTP GET-kérelmeket is. Ha az alkalmazás vezérlőire a ValidateAntiForgeryToken attribútum van alkalmazva, akkor a IgnoreAntiforgeryToken attribútummal felülírható.

Az antiforgery tokenek automatikus ellenőrzése csak a nem biztonságos HTTP-metódusok esetén történik meg.

Ahelyett, hogy a ValidateAntiForgeryToken attribútumot általánosan alkalmazná, majd felülírná IgnoreAntiforgeryToken attribútumokkal, az AutoValidateAntiforgeryToken attribútum használható. Ez az attribútum ugyanúgy működik, mint a ValidateAntiForgeryToken attribútum, azzal a különbségkel, hogy nem igényel jogkivonatokat a következő HTTP-metódusokkal végrehajtott kérelmekhez:

  • SZEREZZ
  • FEJ
  • OPCIÓK
  • NYOM

Javasoljuk a AutoValidateAntiforgeryToken széles körű használatát nem API-szcenáriókhoz. Ez az attribútum biztosítja, hogy a POST-műveletek alapértelmezés szerint védettek legyenek. A másik lehetőség az, hogy alapértelmezés szerint figyelmen kívül hagyja az antiforgery tokeneket, kivéve, ha ValidateAntiForgeryToken az egyes műveleti módszerekre van alkalmazva. Ebben a forgatókönyvben valószínűbb, hogy egy POST-műveletmetódus véletlenül védtelen marad, így az alkalmazás sebezhető lesz a CSRF-támadásokkal szemben. Minden POST-nak el kell küldenie a hamisítás elleni tokent.

Az API-k nem rendelkeznek automatikus mechanizmusokkal a jogkivonat nemcookie részének küldéséhez. A megvalósítás valószínűleg az ügyfélkód implementálásától függ. Néhány példa alább látható:

Osztályszintű példa:

[AutoValidateAntiforgeryToken]
public class HomeController : Controller

Globális példa:

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

Globális vagy vezérlő antiforgery attribútumok felülbírálása

Az IgnoreAntiforgeryToken szűrővel kiküszöbölhető az adott művelethez (vagy vezérlőhöz) tartozó antiforgery token szükségessége. Alkalmazásakor ez a szűrő felülbírálja a magasabb szinten (globálisan vagy vezérlőn) megadott ValidateAntiForgeryToken és AutoValidateAntiforgeryToken szűrőket.

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

    return RedirectToAction();
}

Jogkivonatok frissítése a hitelesítés után

A tokeneket a felhasználó hitelesítése után frissíteni kell úgy, hogy a felhasználót átirányítja egy felületre vagy Razor Pages oldalra.

JavaScript, AJAX és SLA-k

Hagyományos HTML-alapú alkalmazásokban rejtett űrlapmezőkön keresztül továbbítják az antiforgery jogkivonatokat a kiszolgálónak. A modern JavaScript-alapú alkalmazásokban és SLA-kban számos kérés programozott módon történik. Ezek az AJAX-kérések más technikákat (például kérésfejléceket vagy cookie-kat) is használhatnak a jogkivonat elküldéséhez.

Ha a cookie-kat hitelesítési jogkivonatok tárolására és API-kérések hitelesítésére használják a kiszolgálón, a CSRF potenciális probléma. Ha a helyi tárolót a jogkivonat tárolására használják, a CSRF biztonsági rése csökkenthető, mivel a rendszer nem küldi el automatikusan a helyi tárolóból származó értékeket a kiszolgálónak minden kéréssel együtt. A helyi tároló használata az antiforgery token ügyfélen való tárolására és a token kérésfejlécben történő elküldésére ajánlott módszer.

JavaScript

JavaScript nézetek használata esetén az azonosító egy szolgáltatás segítségével hozható létre a nézeten belül. Injektálja a IAntiforgery szolgáltatást a nézetbe, és hívja meg GetAndStoreTokens:

@inject Microsoft.AspNetCore.Antiforgery.IAntiforgery Antiforgery

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

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

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

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

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

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

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

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

Az előző példa JavaScript használatával olvassa be az AJAX POST fejléc rejtett mezőértékét.

Ez a megközelítés szükségtelenné teszi a cookie-k szerverről történő közvetlen beállítását vagy kliensről való közvetlen olvasását. Ha azonban a IAntiforgery szolgáltatás injektálása nem lehetséges, a JavaScript a cookie-kban is hozzáférhet a jogkivonathoz, amely a kiszolgálóhoz érkező további kérésből (általában same-origin) származik, és a cookietartalmának használatával létrehozhat egy fejlécet a jogkivonat értékével.

Feltéve, hogy a szkript egy X-XSRF-TOKENnevű kérelemfejlécben küldi el a jogkivonatot, konfigurálja az antiforgery szolgáltatást a X-XSRF-TOKEN fejléc keresésére:

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

Az alábbi példa hozzáad egy védett végpontot, amely a kérés jogkivonatát egy JavaScript által olvasható módon a cookie-ba írja.

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();

Az alábbi példa JavaScript használatával küld egy AJAX-kérést a token megszerzésére, és egy másik kérést a megfelelő fejléc alkalmazásával.

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

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

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

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

Windows-hitelesítés és hamisítást gátló sütik

A Windows-hitelesítés használatakor az alkalmazásvégpontokat ugyanúgy kell védeni a CSRF-támadások ellen, mint a cookie-k esetében. A böngésző implicit módon elküldi a hitelesítési környezetet a kiszolgálónak, ezért a végpontokat védeni kell a CSRF-támadások ellen.

Antiforgery kiterjesztése

A IAntiforgeryAdditionalDataProvider típus lehetővé teszi a fejlesztők számára a CSRF-ellenes rendszer viselkedésének kiterjesztését az egyes tokenekben történő további adatcserével. A GetAdditionalData metódust minden alkalommal meghívják, amikor létrehoz egy mezőt, és a visszatérési érték a létrehozott mezőben van beágyazva. A megvalósító visszaadhat egy időbélyeget, egy egyedi azonosítót vagy bármilyen más értéket, majd meghívhatja a ValidateAdditionalData függvényt, amikor a jogkivonat érvényesítésre kerül, hogy érvényesítse ezeket az adatokat. Az ügyfél felhasználóneve már be van ágyazva a létrehozott tokenekbe, így nincs szükség ezen információk külön feltüntetésére. Ha egy token kiegészítő adatokat tartalmaz, de nincs konfigurálva IAntiForgeryAdditionalDataProvider, akkor a kiegészítő adatokat nem érvényesítik.

További erőforrások

A webhelyek közötti kérelemhamisítás (más néven XSRF vagy CSRF) a webalkalmazások elleni támadás, amelynek során egy rosszindulatú webalkalmazás befolyásolhatja az ügyfélböngésző és az a böngésző által megbízhatónak tartott webalkalmazás közötti interakciót. Ezek a támadások azért lehetségesek, mert a webböngészők minden kéréssel automatikusan küldenek bizonyos hitelesítési jogkivonatokat egy webhelyre. Ezt a biztonsági rést egykattintásos támadásnak is nevezik, vagy munkamenet-eltérítésnek, mert kihasználja a felhasználó korábban hitelesített munkamenetét.

Példa CSRF-támadásra:

  1. A felhasználó űrlap-hitelesítéssel jelentkezik be www.good-banking-site.example.com. A kiszolgáló hitelesíti a felhasználót, és egy hitelesítési cookietartalmazó választ ad ki. A webhely sebezhető a támadásokkal szemben, mert megbízik minden olyan kérésben, amelyet érvényes hitelesítési cookiekap.

  2. A felhasználó meglátogat egy rosszindulatú webhelyet, www.bad-crook-site.example.com.

    A kártékony webhely (www.bad-crook-site.example.com) az alábbi példához hasonló HTML-űrlapot tartalmaz:

    <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>
    

    Figyelje meg, hogy az űrlap action a sebezhető webhelyre, nem pedig a rosszindulatú webhelyre. Ez a CSRF "keresztoldali" része.

  3. A felhasználó kiválasztja a Küldés gombot. A böngésző a kérést végrehajtja, és automatikusan tartalmazza a cookie hitelesítést a kért tartományhoz, www.good-banking-site.example.com.

  4. A kérés a www.good-banking-site.example.com kiszolgálón fut a felhasználó hitelesítési környezetével, és bármilyen műveletet végrehajthat, amelyet egy hitelesített felhasználó végrehajthat.

Azon forgatókönyv mellett, amikor a felhasználó kiválasztja az űrlap elküldéséhez a gombot, a rosszindulatú webhely a következőt teheti:

  • Futtasson egy szkriptet, amely automatikusan elküldi az űrlapot.
  • Küldje el az űrlap beküldését AJAX-kérelemként.
  • Rejtse el az űrlapot a CSS használatával.

Ezek az alternatív forgatókönyvek nem igényelnek semmilyen műveletet vagy bemenetet a felhasználótól, kivéve, ha eredetileg meglátogatják a rosszindulatú webhelyet.

A HTTPS használata nem akadályozza meg a CSRF-támadást. A rosszindulatú webhely ugyanolyan könnyen küldhet egy https://www.good-banking-site.example.com/ kérést, mint egy nem biztonságos kérést.

Egyes támadások a GET-kérelmekre reagáló végpontokat támadják meg, ebben az esetben egy képcímke használható a művelet végrehajtásához. Ez a támadási forma gyakori a fórumwebhelyeken, amelyek lehetővé teszik a képeket, de letiltják a JavaScriptet. A GET-kérések állapotát módosító alkalmazások, amelyek változókat vagy erőforrásokat módosítanak, sebezhetők a rosszindulatú támadásokkal szemben. Az állapotot módosító GET-kérelmek nem biztonságosak. Ajánlott eljárás, hogy soha ne változtassunk állapotot GET-kérés során.

A CSRF-támadások a hitelesítéshez cookie-kat használó webalkalmazások ellen lehetségesek, mert:

  • A böngészők egy webalkalmazás által kibocsátott cookie-kat tárolnak.
  • A tárolt cookie-k munkamenet-cookie-kat tartalmaznak a hitelesített felhasználók számára.
  • A böngészők minden, tartományhoz társított cookie-t elküldenek a webalkalmazásnak, függetlenül attól, hogy az alkalmazáskérés hogyan jött létre a böngészőben.

A CSRF-támadások azonban nem korlátozódnak a cookie-k kihasználására. Az alapszintű és a kivonatoló hitelesítés például sebezhető. Miután egy felhasználó bejelentkezett alapszintű vagy kivonatoló hitelesítéssel, a böngésző automatikusan elküldi a hitelesítő adatokat, amíg a munkamenet véget nem ér.

Ebben az összefüggésben munkamenet arra az ügyféloldali munkamenetre vonatkozik, amely során a felhasználó hitelesítése megtörtént. Nem kapcsolódik kiszolgálóoldali munkamenetekhez vagy ASP.NET Core Session Middleware.

A felhasználók óvintézkedéseket tehetnek a CSRF biztonsági rései ellen:

  • Kijelentkezés a webalkalmazásból, ha befejezte a használatukat.
  • A böngésző cookie-inak rendszeres törlése.

A CSRF biztonsági rései azonban alapvetően a webalkalmazással, nem pedig a végfelhasználóval kapcsolatos problémák.

A hitelesítés alapjai

Cookie-alapú hitelesítés a hitelesítés népszerű formája. A token alapú hitelesítési rendszerek egyre népszerűbbek, különösen az egyoldalas alkalmazások (SPA-k) esetében.

Amikor egy felhasználó a saját felhasználónevével és jelszavával hitelesít, a rendszer egy jogkivonatot ad ki, amely tartalmaz egy hitelesítési jegyet, és ez felhasználható további hitelesítéshez és engedélyezéshez. A tokent egy cookie-ként tárolják, amelyet minden kérésnél az ügyféllel együtt küldenek. A cookie generálását és érvényesítését a Cookie Hitelesítési köztes szoftver végzi. A köztes szoftver egy felhasználónevet titkosított cookieszerializál. A következő kérések során a köztes szoftver ellenőrzi a cookie-t, újra létrehozza a főkomponenst, és hozzárendeli a főkomponenst a HttpContext.User tulajdonsághoz.

Tokenalapú hitelesítés

Ha egy felhasználó hitelesítése megtörtént, a rendszer tokent ad ki (nem pedig antiforgery tokent). A jogkivonat felhasználói adatokat tartalmaz jogcímek formájában, vagy egy hivatkozási jogkivonat formájában, amely az alkalmazást az alkalmazásban fenntartott felhasználói állapotra mutatja. Amikor egy felhasználó megpróbál hozzáférni egy hitelesítést igénylő erőforráshoz, a rendszer a jogkivonatot egy további engedélyezési fejléccel továbbítja az alkalmazásnak tulajdonosi jogkivonat formájában. Ez a megközelítés állapot nélkülivé teszi az alkalmazást. Minden további kérésben a jogkivonat továbbításra kerül a kiszolgálóoldali érvényesítéshez. Ez a jogkivonat nem titkosított; kódolt. A kiszolgálón a rendszer dekódolja a jogkivonatot, hogy hozzáférjen az adataihoz. A jogkivonat későbbi kérésekre való elküldéséhez tárolja a jogkivonatot a böngésző helyi tárolójában. Ne aggódjon a CSRF biztonsági rése miatt, ha a jogkivonat a böngésző helyi tárolójában van tárolva. A CSRF aggodalomra ad okot, ha a tokent egy cookie-ban tárolják. További információért lásd a GitHub probléma oldalt: az SPA kódminta két cookie-t ad hozzá.

Több, egy tartományban üzemeltetett alkalmazás

A megosztott üzemeltetési környezetek sebezhetők a munkamenet-eltérítés, a bejelentkezési CSRF és más támadások ellen.

Bár example1.contoso.net és example2.contoso.net különböző gazdagépek, implicit megbízhatósági kapcsolat áll fenn a *.contoso.net tartománybeli gazdagépek között. Ez az implicit megbízhatósági kapcsolat lehetővé teszi, hogy a potenciálisan nem megbízható gazdagépek befolyásolják egymás cookie-jait (az AJAX-kéréseket szabályozó azonos eredetű szabályzatok nem feltétlenül vonatkoznak a HTTP-cookie-kra).

Az ugyanazon a tartományon üzemeltetett alkalmazások közötti megbízható cookie-kat kihasználó támadások megelőzhetők, ha nem osztanak meg tartományokat. Ha az egyes alkalmazásokat a saját tartományában üzemeltetik, nincs kihasználandó implicit cookie megbízhatósági kapcsolat.

ASP.NET Core antiforgery konfigurációja

Figyelmeztetés

ASP.NET Core a ASP.NET Core Data Protectionhasználatával implementálja a hamisítás elleni védelmet. Az adatvédelmi vermet úgy kell konfigurálni, hogy egy kiszolgálófarmban működjön. További információért lásd: Az adatvédelem konfigurálása.

Antiforgery middleware kerül be a függőség-injektálási tárolóba, ha az alábbi API-k egyikét meghívják Startup.ConfigureServices:

A ASP.NET Core 2.0-s vagy újabb verzióiban a FormTagHelper injektálja az antiforgery tokeneket HTML-űrlapelemekbe. Egy Razor fájlban a következő korrektúra automatikusan létrehozza az antiforgery tokeneket:

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

Hasonlóképpen, IHtmlHelper.BeginForm alapértelmezés szerint antiforgery tokeneket hoz létre, ha az űrlap metódusa nem GET.

A HTML-űrlapelemek antiforgery tokenjeinek automatikus létrehozása akkor történik, ha a <form> címke tartalmazza a method="post" attribútumot, és az alábbiak bármelyike igaz:

  • A műveletattribútum üres (action="").
  • A műveletattribútum nincs megadva (<form method="post">).

A HTML-űrlapelemekhez tartozó antiforgery tokenek automatikus létrehozása letiltható:

  • Explicit módon tiltsa le az antiforgery tokeneket a asp-antiforgery attribútummal:

    <form method="post" asp-antiforgery="false">
        ...
    </form>
    
  • Az űrlapelem ki van zárva a Címkesegítők közül a Tag Helper ! opt-out szimbólumokhasználatával.

    <!form method="post">
        ...
    </!form>
    
  • Távolítsa el a FormTagHelper a nézetből. A FormTagHelper eltávolítható egy nézetből az alábbi irányelv Razor nézethez való hozzáadásával:

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

Jegyzet

Razor lapok automatikusan védettek az XSRF/CSRF támadások ellen. További információ: XSRF/CSRF és Razor Pages.

A CSRF-támadások elleni védelem leggyakoribb módja a szinkronizáló jogkivonat-minta (STP) használata. Az STP akkor használatos, ha a felhasználó űrlapadatokat tartalmazó lapot kér:

  1. A kiszolgáló egy, az aktuális felhasználó identitásához társított jogkivonatot küld az ügyfélnek.
  2. Az ügyfél visszaküldi a jogkivonatot a kiszolgálónak ellenőrzés céljából.
  3. Ha a kiszolgáló olyan jogkivonatot kap, amely nem egyezik a hitelesített felhasználó identitásával, a rendszer elutasítja a kérést.

A token egyedi és kiszámíthatatlan. A jogkivonat arra is használható, hogy biztosítsa a kérelmek sorozatának megfelelő sorrendjét (például a következő kérelmek sorrendjének biztosításához: 1. oldal > 2. oldal > 3. oldal). Az összes ASP.NET Core MVC és Razor Pages sablonú űrlap valahogy antiforgery tokeneket hoz létre. A következő példanézet-páros antiforgery biztonsági tokeneket hoz létre:

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

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

Kifejezetten adjon hozzá egy hamisítás elleni tokent egy <form> elemhez a Tag Helper és a HTML-segéd használata nélkül @Html.AntiForgeryToken.

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

Az előző esetekben ASP.NET Core az alábbi példához hasonló rejtett űrlapmezőt ad hozzá:

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

ASP.NET Core három szűrőt tartalmaz, az antiforgery tokenek használatát:

Antiforgery beállítások

AntiforgeryOptions testreszabása a Startup.ConfigureServices-en:

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

Állítsa be az antiforgery Cookie tulajdonságokat a CookieBuilder osztály tulajdonságaival, ahogyan az az alábbi táblázatban látható.

Opció Leírás
Cookie Meghatározza az antiforgery cookie-k létrehozásához használt beállításokat.
FormFieldName Annak a rejtett űrlapmezőnek a neve, amelyet az antiforgery rendszer használ az antiforgery tokenek nézetekben való megjelenítéséhez.
HeaderName Az antiforgery rendszer által használt fejléc neve. Ha null, a rendszer csak az űrlapadatokat veszi figyelembe.
SuppressXFrameOptionsHeader Megadja, hogy el kívánja-e tiltani a X-Frame-Options fejléc generálását. Alapértelmezés szerint a fejléc "SAMEORIGIN" értékkel jön létre. Alapértelmezés szerint false.

További információ: CookieAuthenticationOptions.

Antiforgery-funkciók konfigurálása az IAntiforgery használatával

IAntiforgery biztosítja az API-t az antiforgery funkciók konfigurálásához. IAntiforgery a Configure osztály Startup metódusában kérhető.

Az alábbi példában:

  • Az alkalmazás kezdőlapján futó köztes szoftver egy antiforgery tokent hoz létre, és a válaszban cookie-ként küldi el.
  • A kérés tokenje JavaScript-olvasható -ként lesz elküldve, az alapértelmezett Angular elnevezési konvencióval, amint az az AngularJS szakaszban, le van írva.
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);
    });
}

Hamisítás elleni ellenőrzés megkövetelése

ValidateAntiForgeryToken egy műveletszűrő, amely egyéni műveletekre, vezérlőkre vagy globálisan alkalmazható. A szűrőt alkalmazó műveletekre irányuló kérések le lesznek tiltva, kivéve, ha a kérés érvényes antiforgery-jogkivonatot tartalmaz.

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

A ValidateAntiForgeryToken attribútumhoz jogkivonatra van szükség az általa jelölt műveleti módszerekre irányuló kérelmekhez, beleértve a HTTP GET-kérelmeket is. Ha az alkalmazás vezérlőire a ValidateAntiForgeryToken attribútum van alkalmazva, akkor a IgnoreAntiforgeryToken attribútummal felülírható.

Jegyzet

ASP.NET Core nem támogatja az antiforgery tokenek automatikus hozzáadását a GET-kérelmekhez.

Az antiforgery tokenek automatikus ellenőrzése csak a nem biztonságos HTTP-metódusok esetén történik meg.

ASP.NET Core-alkalmazások nem hoznak létre antiforgery tokeneket a biztonságos HTTP-metódusokhoz (GET, HEAD, OPTIONS és TRACE). Ahelyett, hogy a ValidateAntiForgeryToken attribútumot általánosan alkalmazná, majd felülírná IgnoreAntiforgeryToken attribútumokkal, az AutoValidateAntiforgeryToken attribútum használható. Ez az attribútum ugyanúgy működik, mint a ValidateAntiForgeryToken attribútum, azzal a különbségkel, hogy nem igényel jogkivonatokat a következő HTTP-metódusokkal végrehajtott kérelmekhez:

  • SZEREZZ
  • FEJ
  • OPCIÓK
  • NYOM

Javasoljuk a AutoValidateAntiforgeryToken széles körű használatát nem API-szcenáriókhoz. Ez az attribútum biztosítja, hogy a POST-műveletek alapértelmezés szerint védettek legyenek. A másik lehetőség az, hogy alapértelmezés szerint figyelmen kívül hagyja az antiforgery tokeneket, kivéve, ha ValidateAntiForgeryToken az egyes műveleti módszerekre van alkalmazva. Ebben a forgatókönyvben valószínűbb, hogy egy POST-műveletmetódus véletlenül védtelen marad, így az alkalmazás sebezhető lesz a CSRF-támadásokkal szemben. Minden POST-nak el kell küldenie a hamisítás elleni tokent.

Az API-k nem rendelkeznek automatikus mechanizmusokkal a jogkivonat nemcookie részének küldéséhez. A megvalósítás valószínűleg az ügyfélkód implementálásától függ. Néhány példa alább látható:

Osztályszintű példa:

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

Globális példa:

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

Globális vagy vezérlő antiforgery attribútumok felülbírálása

Az IgnoreAntiforgeryToken szűrővel kiküszöbölhető az adott művelethez (vagy vezérlőhöz) tartozó antiforgery token szükségessége. Alkalmazásakor ez a szűrő felülbírálja a magasabb szinten (globálisan vagy vezérlőn) megadott ValidateAntiForgeryToken és AutoValidateAntiforgeryToken szűrőket.

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

Jogkivonatok frissítése a hitelesítés után

A tokeneket a felhasználó hitelesítése után frissíteni kell úgy, hogy a felhasználót átirányítja egy felületre vagy Razor Pages oldalra.

JavaScript, AJAX és SLA-k

Hagyományos HTML-alapú alkalmazásokban rejtett űrlapmezőkön keresztül továbbítják az antiforgery jogkivonatokat a kiszolgálónak. A modern JavaScript-alapú alkalmazásokban és SLA-kban számos kérés programozott módon történik. Ezek az AJAX-kérések más technikákat (például kérésfejléceket vagy cookie-kat) is használhatnak a jogkivonat elküldéséhez.

Ha a cookie-kat hitelesítési jogkivonatok tárolására és API-kérések hitelesítésére használják a kiszolgálón, a CSRF potenciális probléma. Ha a helyi tárolót a jogkivonat tárolására használják, a CSRF biztonsági rése csökkenthető, mivel a rendszer nem küldi el automatikusan a helyi tárolóból származó értékeket a kiszolgálónak minden kéréssel együtt. A helyi tároló használata az antiforgery token ügyfélen való tárolására és a token kérésfejlécben történő elküldésére ajánlott módszer.

JavaScript

JavaScript nézetek használata esetén az azonosító egy szolgáltatás segítségével hozható létre a nézeten belül. Injektálja a IAntiforgery szolgáltatást a nézetbe, és hívja meg GetAndStoreTokens:

@{
    ViewData["Title"] = "AJAX Demo";
}
@inject Microsoft.AspNetCore.Antiforgery.IAntiforgery Xsrf
@functions{
    public string GetAntiXsrfRequestToken()
    {
        return Xsrf.GetAndStoreTokens(Context).RequestToken;
    }
}

<input type="hidden" id="RequestVerificationToken" 
       name="RequestVerificationToken" value="@GetAntiXsrfRequestToken()">

<h2>@ViewData["Title"].</h2>
<h3>@ViewData["Message"]</h3>

<div class="row">
    <p><input type="button" id="antiforgery" value="Antiforgery"></p>
    <script>
        var xhttp = new XMLHttpRequest();
        xhttp.onreadystatechange = function() {
            if (xhttp.readyState == XMLHttpRequest.DONE) {
                if (xhttp.status == 200) {
                    alert(xhttp.responseText);
                } else {
                    alert('There was an error processing the AJAX request.');
                }
            }
        };

        document.addEventListener('DOMContentLoaded', function() {
            document.getElementById("antiforgery").onclick = function () {
                xhttp.open('POST', '@Url.Action("Antiforgery", "Home")', true);
                xhttp.setRequestHeader("RequestVerificationToken", 
                    document.getElementById('RequestVerificationToken').value);
                xhttp.send();
            }
        });
    </script>
</div>

Ez a megközelítés szükségtelenné teszi a cookie-k szerverről történő közvetlen beállítását vagy kliensről való közvetlen olvasását.

Az előző példa JavaScript használatával olvassa be az AJAX POST fejléc rejtett mezőértékét.

A JavaScript a cookie-k jogkivonatait is elérheti, és a cookietartalmának használatával létrehozhat egy fejlécet a jogkivonat értékével.

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

Feltételezve, hogy a szkript egy X-CSRF-TOKENnevű fejlécben kéri a jogkivonat küldését, konfigurálja úgy a hamisítás elleni szolgáltatást, hogy a X-CSRF-TOKEN fejlécre keressen.

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

Az alábbi példa JavaScript használatával készít AJAX-kérést a megfelelő fejléccel:

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

Az AngularJS egy konvenciót használ a CSRF kezelésére. Ha a kiszolgáló cookie-t küld a XSRF-TOKENnévvel, az AngularJS $http szolgáltatás hozzáadja a cookie értéket egy fejléchez, amikor kérést küld a kiszolgálónak. Ez a folyamat automatikus. Az ügyfélnek nem kell explicit módon beállítania a fejlécet. A fejléc neve X-XSRF-TOKEN. A kiszolgálónak észlelnie kell ezt a fejlécet, és ellenőriznie kell annak tartalmát.

Ahhoz, hogy ASP.NET Core API működjön ezzel a konvencióval az alkalmazás indításakor:

  • Konfigurálja az alkalmazást úgy, hogy egy cookie nevű XSRF-TOKEN-ben adjon meg egy jogkivonatot.
  • Konfigurálja az antiforgery szolgáltatást egy X-XSRF-TOKENnevű fejléc keresésére, amely az Angular alapértelmezett fejlécneve az XSRF-jogkivonat küldéséhez.
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");
}

Jegyzet

Ha az antiforgery token mind a kérelem fejlécben, mind az űrlap hasznos adataiban szerepel, csak a fejlécben lévő token kerül érvényesítésre.

Windows-hitelesítés és hamisítást gátló sütik

A Windows-hitelesítés használatakor az alkalmazásvégpontokat ugyanúgy kell védeni a CSRF-támadások ellen, mint a cookie-k esetében. A böngésző implicit módon elküldi a hitelesítési környezetet a kiszolgálónak, ezért a végpontokat védeni kell a CSRF-támadások ellen.

Antiforgery kiterjesztése

A IAntiforgeryAdditionalDataProvider típus lehetővé teszi a fejlesztők számára a CSRF-ellenes rendszer viselkedésének kiterjesztését az egyes tokenekben történő további adatcserével. A GetAdditionalData metódust minden alkalommal meghívják, amikor létrehoz egy mezőt, és a visszatérési érték a létrehozott mezőben van beágyazva. A megvalósító visszaadhat egy időbélyeget, egy egyedi azonosítót vagy bármilyen más értéket, majd meghívhatja a ValidateAdditionalData függvényt, amikor a jogkivonat érvényesítésre kerül, hogy érvényesítse ezeket az adatokat. Az ügyfél felhasználóneve már be van ágyazva a létrehozott tokenekbe, így nincs szükség ezen információk külön feltüntetésére. Ha egy token kiegészítő adatokat tartalmaz, de nincs konfigurálva IAntiForgeryAdditionalDataProvider, akkor a kiegészítő adatokat nem érvényesítik.

További erőforrások