Verhindern von Angriffen durch websiteübergreifende Anforderungsfälschung (XSRF/CSRF) in ASP.NET Core

Von Fiyaz Bin Hasan und Rick Anderson

Bei einer websiteübergreifenden Anforderungsfälschung (auch bekannt als XSRF oder CSRF) handelt es sich um einen Angriff auf im Internet gehostete Anwendungen, bei dem eine bösartige Webanwendung die Interaktion zwischen einem Client-Browser und einer Webanwendung, die diesem Browser vertraut, beeinflussen kann. Diese Angriffe sind möglich, weil Webbrowser einige Typen von Authentifizierungstoken automatisch bei jeder Anforderung an eine Website senden. Diese Form von Exploit wird auch als Ein-Klick-Angriff oder Session-Riding bezeichnet, weil für den Angriff die zuvor authentifizierte Sitzung des Benutzers verwendet wird. Websiteübergreifende Anforderungsfälschung ist auch als XSRF oder CSRF bekannt.

Ein Beispiel für einen CSRF-Angriff:

  1. Ein Benutzer meldet sich bei www.good-banking-site.example.com mit der Formularauthentifizierung an. Der Server authentifiziert den Benutzer und gibt eine Antwort aus, die ein Authentifizierungscookie enthält. Die Website ist anfällig für Angriffe, da sie jeder Anforderung vertraut, die sie mit einem gültigen Authentifizierungscookie empfängt.

  2. Der Benutzer besucht eine böswillige Website, www.bad-crook-site.example.com.

    Die böswillige Website www.bad-crook-site.example.com enthält ein HTML-Formular, das dem folgenden Beispiel ähnelt:

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

    Beachten Sie, dass die action des Formulars auf der anfälligen Website veröffentlicht, nicht auf der böswilligen Website. Dies ist der websiteübergreifende Teil von CSRF.

  3. Der Benutzer wählt die Senden-Schaltfläche aus. Der Browser führt die Anforderung aus und schließt automatisch die Authentifizierung cookie für die angeforderte Domäne www.good-banking-site.example.com ein.

  4. Die Anforderung wird auf dem www.good-banking-site.example.com-Server mit dem Authentifizierungskontext des Benutzers ausgeführt und kann jede Aktion ausführen, die ein authentifizierter Benutzer ausführen darf.

Über das Szenario hinaus, in dem der Benutzer die Schaltfläche zum Senden des Formulars auswählt, kann die böswillige Website Folgendes bewirken:

  • ein Skript ausführen, mit dem das Formular automatisch übermittelt wird.
  • die Formularübermittlung als AJAX-Anforderung senden.
  • das Formular mithilfe von CSS ausblenden.

Diese alternativen Szenarien erfordern keinerlei Aktion oder Eingabe seitens des Benutzers über den ursprünglichen Besuch der böswilligen Website hinaus.

Die Verwendung von HTTPS verhindert keinen CSRF-Angriff. Die böswillige Website kann eine https://www.good-banking-site.com/-Anforderung ebenso einfach senden wie eine unsichere Anforderung.

Einige Angriffe zielen auf Endpunkte ab, die auf GET-Anforderungen reagieren. In diesem Fall kann ein Bildtag verwendet werden, um die Aktion auszuführen. Diese Form des Angriffs ist auf Forenwebsites üblich, die Bilder zulassen, aber JavaScript blockieren. Apps, die den Status bei GET-Anforderungen ändern, bei denen Variablen oder Ressourcen geändert werden, sind anfällig für böswillige Angriffe. GET-Anforderungen, die den Status ändern, sind unsicher. Eine bewährte Methode besteht darin, niemals Statusänderungen auf eine GET-Anforderung hin vorzunehmen.

CSRF-Angriffe sind gegen Web-Apps möglich, die cookies für die Authentifizierung verwenden, weil:

  • Browser die von einer Web-App ausgegebenen cookies speichern
  • Gespeicherte cookies Sitzungscookies für authentifizierte Benutzer enthalten
  • Browser alle einer Domäne zugeordneten cookies auf jede Anforderung an die Web-App senden, unabhängig davon, wie die Anforderung an die App innerhalb des Browsers generiert wurde.

CSRF-Angriffe sind jedoch nicht auf die Ausnutzung von cookies beschränkt. Beispielsweise sind auch die Standard- und Digestauthentifizierung anfällig. Nachdem sich ein Benutzer mit der Standard- oder Digest-Authentifizierung angemeldet hat, sendet der Browser die Anmeldeinformationen automatisch, bis die Sitzung endet.

In diesem Kontext bezieht sich Sitzung auf die clientseitige Sitzung, in der der Benutzer authentifiziert wird. Dies hat nichts mit serverseitigen Sitzungen oder ASP.NET Core Sitzungs-Middleware zu tun.

Benutzer können sich vor CSRF-Sicherheitsrisiken schützen, indem sie Vorkehrungen treffen:

  • Bei Web-Apps abmelden, wenn die Nutzung abgeschlossen ist
  • Browsercookies in regelmäßigen Abständen löschen

CSRF-Sicherheitsrisiken sind jedoch grundsätzlich ein Problem der Web-App, nicht des Endbenutzers.

Grundlagen der Authentifizierung

Cookie-basierte Authentifizierung ist eine beliebte Form der Authentifizierung. Tokenbasierte Authentifizierungssysteme werden immer beliebter, insbesondere für Single Page Applications (SPAs).

Wenn sich ein Benutzer mithilfe seines Benutzernamens und Kennworts authentifiziert, wird ein Token ausgestellt, das ein Authentifizierungsticket enthält. Das Token kann für die Authentifizierung und Autorisierung verwendet werden. Das Token wird als ein cookie gespeichert, das mit jeder Anforderung des Clients gesendet wird. Die Generierung und Validierung dieses cookie erfolgt durch die Cookie Middleware zur Authentifizierung. Die Middleware serialisiert einen Benutzerprinzipal in ein verschlüsseltes cookie. Bei nachfolgenden Anforderungen überprüft die Middleware das cookie, erstellt den Prinzipal neu und weist den Prinzipal der HttpContext.User-Eigenschaft zu.

Tokenbasierte Authentifizierung

Wenn ein Benutzer authentifiziert wird, wird ein Token (kein Token zur Fälschungsverhinderung) ausgestellt. Das Token enthält Benutzerinformationen in Form von Ansprüchen oder eines Verweistokens, das die App auf den in der App verwalteten Benutzerstatus verweist. Wenn ein Benutzer versucht, auf eine Ressource zuzugreifen, die Authentifizierung erfordert, wird das Token mit einem zusätzlichen Autorisierungsheader in Form eines Bearertokens an die App gesendet. Durch diesen Ansatz wird die App zustandslos. In jeder nachfolgenden Anforderung wird das Token in der Anforderung zur serverseitigen Validierung übergeben. Dieses Token ist nicht verschlüsselt, sondern codiert. Auf dem Server wird das Token decodiert, um auf seine Informationen zuzugreifen. Zum Senden des Tokens bei nachfolgenden Anforderungen speichern Sie das Token im lokalen Speicher des Browsers. Das Platzieren eines Tokens im lokalen Speicher des Browsers und sein Abrufen und Verwenden als Bearertoken bieten Schutz vor CSRF-Angriffen. Sollte die Anwendung jedoch anfällig für die Skripteinschleusung über XSS oder eine kompromittierte externe Javascript-Datei sein, könnte ein Angreifer jeden Wert aus dem lokalen Speicher abrufen und an sich selbst senden. ASP.NET Core codiert standardmäßig alle serverseitigen Ausgaben aus Variablen, wodurch das Risiko durch XSS verringert wird. Wenn Sie dieses Verhalten außer Kraft setzen, indem Sie Html.Raw oder benutzerdefinierten Code mit nicht vertrauenswürdiger Eingabe verwenden, erhöhen Sie möglicherweise das Risiko durch XSS.

Machen Sie sich keine Sorgen über das CSRF-Sicherheitsrisiko, wenn das Token im lokalen Speicher des Browsers gespeichert wird. CSRF ist ein Problem, wenn das Token in einem cookie gespeichert wird. Weitere Informationen finden Sie im GitHub Issue SPA code sample adds two cookies (SPA-Codebeispiel fügt zwei Cookies hinzu).

Mehrere Apps, die in einer Domäne gehostet werden

Freigegebene Hostingumgebungen sind anfällig für Session Hijacking, Anmelde-CSRF und andere Angriffe.

Zwar sind example1.contoso.net und example2.contoso.net unterschiedliche Hosts, jedoch besteht eine implizite Vertrauensstellung zwischen Hosts unter der *.contoso.net-Domäne. Diese implizite Vertrauensstellung ermöglicht es potenziell nicht vertrauenswürdigen Hosts, gegenseitig Einfluss auf ihre cookies zu nehmen (die Richtlinien für gleichen Ursprung, die AJAX-Anforderungen steuern, gelten nicht zwangsläufig für HTTP-cookies.

Angriffe, die vertrauenswürdige cookies zwischen Apps ausnutzen, die in derselben Domäne gehostet werden, können verhindert werden, indem Domänen nicht freigegeben werden. Wenn jede App in ihrer eigenen Domäne gehostet wird, gibt es keine implizite cookie-Vertrauensstellung, die ausgenutzt werden kann.

Schutz vor Fälschung in ASP.NET Core

Warnung

ASP.NET Core implementiert Schutz vor Fälschung mithilfe von Datenschutz in ASP.NET Core. Der Datenschutzstapel muss für die Verwendung in einer Serverfarm konfiguriert werden. Weitere Informationen finden Sie unter Konfigurieren von Datenschutz.

Middleware zum Schutz vor Fälschung wird dem Dependency Injection-Container hinzugefügt, wenn eine der folgenden APIs in Program.cs aufgerufen wird:

Weitere Informationen finden Sie unter Schutz vor Fälschung mit Minimal APIs.

Das Formulartag-Hilfsprogramm injiziert Anti-XSRF/CSRF-Token in HTML-Formularelemente. Das folgende Markup in einer Razor-Datei generiert automatisch Token zum Schutz vor Fälschung:

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

In ähnlicher Weise generiert IHtmlHelper.BeginForm standardmäßig Token zum Schutz vor Fälschung, wenn die Methode des Formulars nicht GET lautet.

Die automatische Generierung von Token zum Schutz vor Fälschung für HTML-Formularelemente erfolgt, wenn das <form>-Tag das method="post"-Attribut enthält und eine der folgenden Bedingungen zutrifft:

  • Das Aktionsattribut ist leer (action="").
  • Das Aktionsattribut ist nicht angegeben (<form method="post">).

Die automatische Generierung von Token zum Schutz vor Fälschung für HTML-Formularelemente kann deaktiviert werden:

  • Deaktivieren Sie Token zum Schutz vor Fälschung explizit mit dem asp-antiforgery-Attribut:

    <form method="post" asp-antiforgery="false">
        <!-- ... -->
    </form>
    
  • Das Formularelement wird aus Taghilfsprogrammen mit dem Tag Helper ! opt-out-Symbol abgewählt:

    <!form method="post">
        <!-- ... -->
    </!form>
    
  • Entfernen Sie den FormTagHelper aus der Ansicht. Der FormTagHelper kann aus einer Ansicht entfernt werden, indem Sie der Razor-Ansicht die folgende Anweisung hinzufügen:

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

Hinweis

Razor Pages werden automatisch vor XSRF/CSRF geschützt. Weitere Informationen finden Sie unter XSRF/CSRF und Razor Pages.

Der häufigste Ansatz zum Schutz vor CSRF-Angriffen ist die Verwendung des Synchronizer Token Pattern (STP). STP wird verwendet, wenn der Benutzer eine Seite mit Formulardaten anfordert:

  1. Der Server sendet ein Token, das der Identität des aktuellen Benutzers zugeordnet ist, an den Client.
  2. Der Client sendet das Token zur Überprüfung an den Server zurück.
  3. Wenn der Server ein Token empfängt, das nicht mit der Identität des authentifizierten Benutzers übereinstimmt, wird die Anforderung abgelehnt.

Das Token ist eindeutig und unvorhersehbar. Das Token kann außerdem verwendet werden, um die ordnungsgemäße Sequenzierung einer Reihe von Anforderungen sicherzustellen (etwa beim Sicherstellen der Anforderungssequenz von: Seite 1 > Seite 2 > Seite 3). Alle Formulare in ASP.NET Core MVC und die Razor Pages-Vorlagen generieren Token zum Schutz vor Fälschung. Die folgenden Ansichtsbeispiele generieren Token zum Schutz vor Fälschung:

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

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

Fügen Sie einem <form>-Element explizit ein Token zum Schutz vor Fälschung hinzu, ohne Tag Helpers mit dem HTML-Hilfsprogramm @Html.AntiForgeryToken zu verwenden:

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

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

In jedem der vorstehenden Fälle fügt ASP.NET Core ein ausgeblendetes Formularfeld ähnlich dem folgenden Beispiel hinzu:

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

ASP.NET Core enthält drei Filter zum Arbeiten mit Token zum Schutz vor Fälschung:

Schutz vor Fälschung mit AddControllers

Beim Aufrufen von AddControllers werden keine Token zum Schutz vor Fälschung aktiviert. AddControllersWithViews muss aufgerufen werden, um integrierte Unterstützung von Token zum Schutz vor Fälschung zur Verfügung zu haben.

Mehrere Browserregisterkarten und das Synchronizer Token Pattern

Beim Synchronizer Token Pattern enthält nur die zuletzt geladene Seite ein gültiges Token zum Schutz vor Fälschung. Die Verwendung mehrerer Registerkarten kann problematisch sein. Beispielsweise, wenn ein Benutzer mehrere Registerkarten öffnet:

  • Nur die zuletzt geladene Registerkarte enthält ein gültiges Token zum Schutz vor Fälschung.
  • Anforderungen, die von zuvor geladenen Registerkarten gesendet werden, schlagen mit einem Fehler fehl: Antiforgery token validation failed. The antiforgery cookie token and request token do not match

Ziehen Sie alternative CSRF-Schutzmuster in Betracht, wenn dies ein Problem darstellt.

Konfigurieren des Schutzes vor Fälschung mit AntiforgeryOptions

Passen Sie AntiforgeryOptions in Program.cs an:

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

Legen Sie die Cookie-Eigenschaften für den Schutz vor Fälschung mithilfe der Eigenschaften der CookieBuilder-Klasse fest, wie in der folgenden Tabelle gezeigt.

Option Beschreibung
Cookie Bestimmt die Einstellungen, die zum Erstellen der cookies zum Schutz vor Fälschung verwendet werden.
FormFieldName Der Name des ausgeblendeten Formularfelds, das vom System zum Schutz vor Fälschungen zum Rendern von Token zum Schutz vor Fälschung in Ansichten verwendet wird.
HeaderName Der Name des Headers, der vom System zum Schutz vor Fälschung verwendet wird. Bei null berücksichtigt das System nur Formulardaten.
SuppressXFrameOptionsHeader Gibt an, ob die Generierung des Headers X-Frame-Options unterdrückt werden soll. Standardmäßig wird der Header mit dem Wert „SAMEORIGIN“ generiert. Wird standardmäßig auf false festgelegt.

Weitere Informationen finden Sie unter CookieAuthenticationOptions.

Generieren von Token zum Schutz vor Fälschung mit IAntiforgery

IAntiforgery stellt die API zum Konfigurieren von Features zum Schutz vor Fälschung zur Verfügung. IAntiforgery kann in Program.cs mit WebApplication.Services angefordert werden. Im folgenden Beispiel wird Middleware von der Startseite der App verwendet, um ein Token zum Schutz vor Fälschung zu generieren und es in der Antwort als cookie zu senden:

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

Im vorstehenden Beispiel wird ein cookie mit dem Namen XSRF-TOKEN festgelegt. Der Client kann dieses cookie lesen und seinen Wert als Header angeben, der an AJAX-Anforderungen angefügt ist. Beispielsweise enthält Angular integrierten XSRF-Schutz, der standardmäßig ein cookie mit dem Namen XSRF-TOKEN liest.

Vorschreiben der Überprüfung des Schutzes vor Fälschungen

Der Aktionsfilter ValidateAntiForgeryToken kann auf eine einzelne Aktion, einen Controller oder global angewendet werden. Anforderungen an Aktionen, für die dieser Filter angewendet wird, werden blockiert, es sei denn, die Anforderung enthält ein gültiges Token zum Schutz vor Fälschung:

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

    return RedirectToAction();
}

Das ValidateAntiForgeryToken-Attribut erfordert ein Token für Anforderungen an die Aktionsmethoden, die es markiert, einschließlich HTTP GET-Anforderungen. Wenn das ValidateAntiForgeryToken-Attribut auf die Controller der App angewendet wird, kann es mit dem IgnoreAntiforgeryToken-Attribut außer Kraft gesetzt werden.

Automatische Überprüfung von Token zum Schutz vor Fälschung nur für unsichere HTTP-Methoden

Anstatt das ValidateAntiForgeryToken-Attribut in großem Umfang anzuwenden und es dann mit IgnoreAntiforgeryToken-Attributen außer Kraft zu setzen, kann das Attribut AutoValidateAntiforgeryToken verwendet werden. Dieses Attribut funktioniert identisch mit dem ValidateAntiForgeryToken-Attribut, mit dem Unterschied, dass es keine Token für Anforderungen erfordert, die mit den folgenden HTTP-Methoden vorgenommen werden:

  • GET
  • HEAD
  • OPTIONEN
  • TRACE

Es empfiehlt sich, für Szenarien ohne API AutoValidateAntiforgeryToken in großem Umfang zu verwenden. Dieses Attribut stellt sicher, dass POST-Aktionen standardmäßig geschützt sind. Alternativ können Sie Token zum Schutz vor Fälschung standardmäßig ignorieren, es sei denn, ValidateAntiForgeryToken wird auf einzelne Aktionsmethoden angewendet. In diesem Szenario ist es wahrscheinlicher, dass eine POST-Aktionsmethode versehentlich nicht geschützt wird, sodass die App für CSRF-Angriffe anfällig bleibt. Alle POSTs sollten das Token zum Schutz vor Fälschung senden.

APIs verfügen nicht über einen automatischen Mechanismus zum Senden des Nicht-cookie-Teils des Tokens. Die Implementierung hängt wahrscheinlich von der Clientcodeimplementierung ab. Nachfolgend werden einige Beispiele veranschaulicht:

Beispiel auf Klassenebene:

[AutoValidateAntiforgeryToken]
public class HomeController : Controller

Globales Beispiel:

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

Außerkraftsetzung von globalen oder Controller-Attributen zum Schutz vor Fälschung

Der Filter IgnoreAntiforgeryToken wird verwendet, um die Notwendigkeit eines Tokens zum Schutz vor Fälschung für eine bestimmte Aktion (oder einen Controller) zu beseitigen. Bei Anwendung setzt dieser Filter die Filter ValidateAntiForgeryToken und AutoValidateAntiforgeryToken außer Kraft, die auf einer höheren Ebene (global oder auf einem Controller) angegeben sind.

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

    return RedirectToAction();
}

Aktualisieren von Token nach der Authentifizierung

Token sollten nach der Authentifizierung des Benutzers aktualisiert werden, indem der Benutzer zu einer Ansicht oder Razor Pages-Seite umgeleitet wird.

JavaScript, AJAX und SPAs

In herkömmlichen HTML-basierten Apps werden Token zum Schutz vor Fälschung mithilfe ausgeblendeter Formularfelder an den Server übergeben. In modernen JavaScript-basierten Apps und SPAs erfolgen viele Anforderungen programmgesteuert. Diese AJAX-Anforderungen können andere Techniken wie beispielsweise Anforderungsheader oder cookie zum Senden des Tokens verwenden.

Wenn cookies verwendet wird, um Authentifizierungstoken zu speichern und API-Anforderungen auf dem Server zu authentifizieren, ist CSRF ein potenzielles Problem. Wenn der lokale Speicher zum Speichern des Tokens verwendet wird, kann das CSRF-Sicherheitsrisiko gemildert werden, da Werte aus dem lokalen Speicher nicht bei jeder Anforderung automatisch an den Server gesendet werden. Die Verwendung des lokalen Speichers zum Speichern des Tokens zum Schutz vor Fälschung auf dem Client und das Senden des Tokens als Anforderungsheader stellt einen empfohlenen Ansatz dar.

Blazor

Weitere Informationen hierzu finden Sie unter Authentifizierung und Autorisierung in ASP.NET Core Blazor.

JavaScript

Mithilfe von JavaScript in Verbindung mit Ansichten kann das Token mithilfe eines Diensts innerhalb der Ansicht erstellt werden. Schleusen Sie den IAntiforgery-Dienst in die Ansicht ein, und rufen Sie GetAndStoreTokens auf:

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

Im vorstehenden Beispiel wird JavaScript verwendet, um den Wert des ausgeblendeten Felds für den AJAX POST-Header zu lesen.

Durch diesen Ansatz entfällt die Notwendigkeit, sich direkt mit dem Festlegen von cookies durch den Server oder dem Lesen durch den Client zu befassen. Wenn das Einschleusen des IAntiforgery-Diensts jedoch nicht möglich ist, verwenden Sie JavaScript, um auf Token in cookies zuzugreifen:

  • Greifen Sie auf Token in einer zusätzlichen Anforderung an den Server zu, in der Regel same-origin.
  • Verwenden Sie den Inhalt des cookies, um einen Header mit dem Wert des Tokens zu erstellen.

Wenn das Skript das Token in einem Anforderungsheader namens X-XSRF-TOKENsendet, konfigurieren Sie den Dienst zum Schutz vor Fälschung, um nach dem Header X-XSRF-TOKEN zu suchen:

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

Im folgenden Beispiel wird ein geschützter Endpunkt hinzugefügt, der das Anforderungstoken in ein durch JavaScript lesbares cookie schreibt:

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

Im folgenden Beispiel wird JavaScript verwendet, um eine AJAX-Anforderung zu erstellen, um das Token abzurufen und eine weitere Anforderung mit dem entsprechenden Header zu erstellen:

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

Hinweis

Wenn das Token zum Schutz vor Fälschung sowohl im Anforderungsheader als auch in den Formularnutzdaten bereitgestellt wird, wird nur das Token im Header überprüft.

Schutz vor Fälschung mit Minimal APIs

Rufen Sie AddAntiforgeryUseAntiforgery(IApplicationBuilder) auf, um Dienste zum Schutz vor Fälschung in DI zu registrieren. Token zum Schutz vor Fälschung werden verwendet, um websiteübergreifende Anforderungsfälschungsangriffe zu entschärfen.

var builder = WebApplication.CreateBuilder();

builder.Services.AddAntiforgery();

var app = builder.Build();

app.UseAntiforgery();

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

app.Run();

Für die Middleware zum Schutz vor Fälschung gilt Folgendes:

Das Token zum Schutz vor Fälschung wird nur in folgenden Fällen überprüft:

  • Der Endpunkt enthält Metadaten, die IAntiforgeryMetadata mit RequiresValidation=true implementieren.
  • Die dem Endpunkt zugeordnete HTTP-Methode ist eine relevante HTTP-Methode. Die relevanten Methoden sind alle HTTP-Methoden außer TRACE, OPTIONS, HEAD und GET.
  • Die Anforderung ist einem gültigen Endpunkt zugeordnet.

Hinweis: Bei manueller Aktivierung muss die Middleware zum Schutz vor Fälschung nach der Authentifizierungs- und Autorisierungs-Middleware ausgeführt werden, um zu verhindern, dass Formulardaten von nicht authentifizierten Benutzer*innen gelesen werden.

Standardmäßig erfordern minimale APIs, die Formulardaten akzeptieren, eine Überprüfung der Token zum Schutz vor Fälschung.

Sehen Sie sich die folgende GenerateForm-Methode an:

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

Der vorangehende Code weist drei Argumente auf: die Aktion, das Token zum Schutz vor Fälschung und einen bool-Wert, der angibt, ob das Token verwendet werden soll.

Betrachten Sie das folgende Beispiel:

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

Im vorangehenden Code gilt für POST-Einträge Folgendes:

  • Für POST-Einträge an /todo ist ein gültiges Token zum Schutz vor Fälschung erforderlich.
  • Für POST-Einträge an /todo2 ist kein gültiges Token zum Schutz vor Fälschung erforderlich, weil DisableAntiforgery aufgerufen wird.
app.MapPost("/todo", ([FromForm] Todo todo) => Results.Ok(todo));

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

Für POST-Einträge gilt:

  • Ein POST an /todo aus dem vom /-Endpunkt generierten Formular ist erfolgreich, weil das Token zum Schutz vor Fälschung gültig ist.
  • Ein POST an /todo aus dem Formular, das über /SkipToken generiert wird, schlägt fehl, weil kein Schutz vor Fälschung enthalten ist.
  • Ein POST an /todo2 aus dem vom /DisableAntiforgery-Endpunkt generierten Formular ist erfolgreich, weil kein Schutz vor Fälschung erforderlich ist.
app.MapPost("/todo", ([FromForm] Todo todo) => Results.Ok(todo));

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

Wenn ein Formular ohne gültiges Token zum Schutz vor Fälschung übermittelt wird, geschieht Folgendes:

  • In der Entwicklungsumgebung wird eine Ausnahme ausgelöst.
  • In der Produktionsumgebung wird eine Meldung protokolliert.

Windows-Authentifizierung und cookies zum Schutz vor Fälschung

Bei Verwendung der Windows-Authentifizierung müssen Anwendungsendpunkte auf die gleiche Weise wie cookies vor CSRF-Angriffen geschützt werden. Der Browser sendet implizit den Authentifizierungskontext an den Server, und Endpunkte müssen vor CSRF-Angriffen geschützt werden.

Erweitern des Schutzes vor Fälschung

Der IAntiforgeryAdditionalDataProvider-Typ ermöglicht es Entwicklern, das Verhalten des Anti-CSRF-Systems mithilfe von Round-Trips zusätzlicher Daten in jedem Token zu erweitern. Die GetAdditionalData-Methode wird jedes Mal aufgerufen, wenn ein Feldtoken generiert wird, und der Rückgabewert wird in das generierte Token eingebettet. Ein Implementierer kann einen Zeitstempel, eine Nonce oder einen anderen Wert zurückgeben und dann ValidateAdditionalData aufrufen, um diese Daten zu überprüfen, wenn das Token überprüft wird. Der Benutzername des Clients ist bereits in die generierten Token eingebettet, sodass diese Informationen nicht eingeschlossen werden müssen. Wenn ein Token zusätzliche Daten enthält, aber kein IAntiForgeryAdditionalDataProvider konfiguriert ist, werden die zusätzlichen Daten nicht überprüft.

Zusätzliche Ressourcen

Bei einer websiteübergreifenden Anforderungsfälschung (auch bekannt als XSRF oder CSRF) handelt es sich um einen Angriff auf im Web gehostete Apps, durch den eine schädliche Web-App die Interaktion zwischen einem Clientbrowser und einer Web-App beeinflussen kann, die diesem Browser vertraut. Diese Angriffe sind möglich, weil Webbrowser einige Typen von Authentifizierungstoken automatisch bei jeder Anforderung an eine Website senden. Diese Form von Exploit wird auch als Ein-Klick-Angriff oder Session-Riding bezeichnet, weil für den Angriff die zuvor authentifizierte Sitzung des Benutzers verwendet wird.

Ein Beispiel für einen CSRF-Angriff:

  1. Ein Benutzer meldet sich bei www.good-banking-site.example.com mit der Formularauthentifizierung an. Der Server authentifiziert den Benutzer und gibt eine Antwort aus, die ein Authentifizierungscookie enthält. Die Website ist anfällig für Angriffe, da sie jeder Anforderung vertraut, die sie mit einem gültigen Authentifizierungscookie empfängt.

  2. Der Benutzer besucht eine böswillige Website, www.bad-crook-site.example.com.

    Die böswillige Website www.bad-crook-site.example.com enthält ein HTML-Formular, das dem folgenden Beispiel ähnelt:

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

    Beachten Sie, dass die action des Formulars auf der anfälligen Website veröffentlicht, nicht auf der böswilligen Website. Dies ist der websiteübergreifende Teil von CSRF.

  3. Der Benutzer wählt die Senden-Schaltfläche aus. Der Browser führt die Anforderung aus und schließt automatisch die Authentifizierung cookie für die angeforderte Domäne www.good-banking-site.example.com ein.

  4. Die Anforderung wird auf dem www.good-banking-site.example.com-Server mit dem Authentifizierungskontext des Benutzers ausgeführt und kann jede Aktion ausführen, die ein authentifizierter Benutzer ausführen darf.

Über das Szenario hinaus, in dem der Benutzer die Schaltfläche zum Senden des Formulars auswählt, kann die böswillige Website Folgendes bewirken:

  • ein Skript ausführen, mit dem das Formular automatisch übermittelt wird.
  • die Formularübermittlung als AJAX-Anforderung senden.
  • das Formular mithilfe von CSS ausblenden.

Diese alternativen Szenarien erfordern keinerlei Aktion oder Eingabe seitens des Benutzers über den ursprünglichen Besuch der böswilligen Website hinaus.

Die Verwendung von HTTPS verhindert keinen CSRF-Angriff. Die böswillige Website kann eine https://www.good-banking-site.com/-Anforderung ebenso einfach senden wie eine unsichere Anforderung.

Einige Angriffe zielen auf Endpunkte ab, die auf GET-Anforderungen reagieren. In diesem Fall kann ein Bildtag verwendet werden, um die Aktion auszuführen. Diese Form des Angriffs ist auf Forenwebsites üblich, die Bilder zulassen, aber JavaScript blockieren. Apps, die den Status bei GET-Anforderungen ändern, bei denen Variablen oder Ressourcen geändert werden, sind anfällig für böswillige Angriffe. GET-Anforderungen, die den Status ändern, sind unsicher. Eine bewährte Methode besteht darin, niemals Statusänderungen auf eine GET-Anforderung hin vorzunehmen.

CSRF-Angriffe sind gegen Web-Apps möglich, die cookies für die Authentifizierung verwenden, weil:

  • Browser die von einer Web-App ausgegebenen cookies speichern
  • Gespeicherte cookies Sitzungscookies für authentifizierte Benutzer enthalten
  • Browser alle einer Domäne zugeordneten cookies auf jede Anforderung an die Web-App senden, unabhängig davon, wie die Anforderung an die App innerhalb des Browsers generiert wurde.

CSRF-Angriffe sind jedoch nicht auf die Ausnutzung von cookies beschränkt. Beispielsweise sind auch die Standard- und Digestauthentifizierung anfällig. Nachdem sich ein Benutzer mit der Standard- oder Digest-Authentifizierung angemeldet hat, sendet der Browser die Anmeldeinformationen automatisch, bis die Sitzung endet.

In diesem Kontext bezieht sich Sitzung auf die clientseitige Sitzung, in der der Benutzer authentifiziert wird. Dies hat nichts mit serverseitigen Sitzungen oder ASP.NET Core Sitzungs-Middleware zu tun.

Benutzer können sich vor CSRF-Sicherheitsrisiken schützen, indem sie Vorkehrungen treffen:

  • Bei Web-Apps abmelden, wenn die Nutzung abgeschlossen ist
  • Browsercookies in regelmäßigen Abständen löschen

CSRF-Sicherheitsrisiken sind jedoch grundsätzlich ein Problem der Web-App, nicht des Endbenutzers.

Grundlagen der Authentifizierung

Cookie-basierte Authentifizierung ist eine beliebte Form der Authentifizierung. Tokenbasierte Authentifizierungssysteme werden immer beliebter, insbesondere für Single Page Applications (SPAs).

Wenn sich ein Benutzer mithilfe seines Benutzernamens und Kennworts authentifiziert, wird ein Token ausgestellt, das ein Authentifizierungsticket enthält, das für die Authentifizierung und Autorisierung verwendet werden kann. Das Token wird als ein cookie gespeichert, das mit jeder Anforderung des Clients gesendet wird. Die Generierung und Überprüfung dieses cookies erfolgt durch die Middleware zur Cookieauthentifizierung. Die Middleware serialisiert einen Benutzerprinzipal in ein verschlüsseltes cookie. Bei nachfolgenden Anforderungen überprüft die Middleware das cookie, erstellt den Prinzipal neu und weist den Prinzipal der HttpContext.User-Eigenschaft zu.

Tokenbasierte Authentifizierung

Wenn ein Benutzer authentifiziert wird, wird ein Token (kein Token zur Fälschungsverhinderung) ausgestellt. Das Token enthält Benutzerinformationen in Form von Ansprüchen oder eines Verweistokens, das die App auf den in der App verwalteten Benutzerstatus verweist. Wenn ein Benutzer versucht, auf eine Ressource zuzugreifen, die Authentifizierung erfordert, wird das Token mit einem zusätzlichen Autorisierungsheader in Form eines Bearertokens an die App gesendet. Durch diesen Ansatz wird die App zustandslos. In jeder nachfolgenden Anforderung wird das Token in der Anforderung zur serverseitigen Validierung übergeben. Dieses Token ist nicht verschlüsselt, sondern codiert. Auf dem Server wird das Token decodiert, um auf seine Informationen zuzugreifen. Zum Senden des Tokens bei nachfolgenden Anforderungen speichern Sie das Token im lokalen Speicher des Browsers. Das Platzieren eines Tokens im lokalen Speicher des Browsers und sein Abrufen und Verwenden als Bearertoken bieten Schutz vor CSRF-Angriffen. Sollte die App jedoch anfällig für die Skripteinschleusung über XSS oder eine kompromittierte externe Javascript-Datei sein, könnte ein Angreifer jeden Wert aus dem lokalen Speicher abrufen und an sich selbst senden. ASP.NET Core codiert standardmäßig alle serverseitigen Ausgaben aus Variablen, wodurch das Risiko durch XSS verringert wird. Wenn Sie dieses Verhalten außer Kraft setzen, indem Sie Html.Raw oder benutzerdefinierten Code mit nicht vertrauenswürdiger Eingabe verwenden, erhöhen Sie möglicherweise das Risiko durch XSS.

Machen Sie sich keine Sorgen über das CSRF-Sicherheitsrisiko, wenn das Token im lokalen Speicher des Browsers gespeichert wird. CSRF ist ein Problem, wenn das Token in einem cookie gespeichert wird. Weitere Informationen finden Sie im GitHub Issue SPA code sample adds two cookies (SPA-Codebeispiel fügt zwei Cookies hinzu).

Mehrere Apps, die in einer Domäne gehostet werden

Freigegebene Hostingumgebungen sind anfällig für Session Hijacking, Anmelde-CSRF und andere Angriffe.

Zwar sind example1.contoso.net und example2.contoso.net unterschiedliche Hosts, jedoch besteht eine implizite Vertrauensstellung zwischen Hosts unter der *.contoso.net-Domäne. Diese implizite Vertrauensstellung ermöglicht es potenziell nicht vertrauenswürdigen Hosts, gegenseitig Einfluss auf ihre cookies zu nehmen (die Richtlinien für gleichen Ursprung, die AJAX-Anforderungen steuern, gelten nicht zwangsläufig für HTTP-cookies.

Angriffe, die vertrauenswürdige cookies zwischen Apps ausnutzen, die in derselben Domäne gehostet werden, können verhindert werden, indem Domänen nicht freigegeben werden. Wenn jede App in ihrer eigenen Domäne gehostet wird, gibt es keine implizite cookie-Vertrauensstellung, die ausgenutzt werden kann.

Schutz vor Fälschung in ASP.NET Core

Warnung

ASP.NET Core implementiert Schutz vor Fälschung mithilfe von Datenschutz in ASP.NET Core. Der Datenschutzstapel muss für die Verwendung in einer Serverfarm konfiguriert werden. Weitere Informationen finden Sie unter Konfigurieren von Datenschutz.

Middleware zum Schutz vor Fälschung wird dem Dependency Injection-Container hinzugefügt, wenn eine der folgenden APIs in Program.cs aufgerufen wird:

Das Formulartag-Hilfsprogramm injiziert Anti-XSRF/CSRF-Token in HTML-Formularelemente. Das folgende Markup in einer Razor-Datei generiert automatisch Token zum Schutz vor Fälschung:

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

In ähnlicher Weise generiert IHtmlHelper.BeginForm standardmäßig Token zum Schutz vor Fälschung, wenn die Methode des Formulars nicht GET lautet.

Die automatische Generierung von Token zum Schutz vor Fälschung für HTML-Formularelemente erfolgt, wenn das <form>-Tag das method="post"-Attribut enthält und eine der folgenden Bedingungen zutrifft:

  • Das Aktionsattribut ist leer (action="").
  • Das Aktionsattribut ist nicht angegeben (<form method="post">).

Die automatische Generierung von Token zum Schutz vor Fälschung für HTML-Formularelemente kann deaktiviert werden:

  • Deaktivieren Sie Token zum Schutz vor Fälschung explizit mit dem asp-antiforgery-Attribut:

    <form method="post" asp-antiforgery="false">
        <!-- ... -->
    </form>
    
  • Das Formularelement wird aus Taghilfsprogrammen mit dem Tag Helper ! opt-out-Symbol abgewählt:

    <!form method="post">
        <!-- ... -->
    </!form>
    
  • Entfernen Sie den FormTagHelper aus der Ansicht. Der FormTagHelper kann aus einer Ansicht entfernt werden, indem Sie der Razor-Ansicht die folgende Anweisung hinzufügen:

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

Hinweis

Razor Pages werden automatisch vor XSRF/CSRF geschützt. Weitere Informationen finden Sie unter XSRF/CSRF und Razor Pages.

Der häufigste Ansatz zum Schutz vor CSRF-Angriffen ist die Verwendung des Synchronizer Token Pattern (STP). STP wird verwendet, wenn der Benutzer eine Seite mit Formulardaten anfordert:

  1. Der Server sendet ein Token, das der Identität des aktuellen Benutzers zugeordnet ist, an den Client.
  2. Der Client sendet das Token zur Überprüfung an den Server zurück.
  3. Wenn der Server ein Token empfängt, das nicht mit der Identität des authentifizierten Benutzers übereinstimmt, wird die Anforderung abgelehnt.

Das Token ist eindeutig und unvorhersehbar. Das Token kann außerdem verwendet werden, um die ordnungsgemäße Sequenzierung einer Reihe von Anforderungen sicherzustellen (etwa beim Sicherstellen der Anforderungssequenz von: Seite 1 > Seite 2 > Seite 3). Alle Formulare in ASP.NET Core MVC und die Razor Pages-Vorlagen generieren Token zum Schutz vor Fälschung. Die folgenden Ansichtsbeispiele generieren Token zum Schutz vor Fälschung:

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

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

Fügen Sie einem <form>-Element explizit ein Token zum Schutz vor Fälschung hinzu, ohne Tag Helpers mit dem HTML-Hilfsprogramm @Html.AntiForgeryToken zu verwenden:

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

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

In jedem der vorstehenden Fälle fügt ASP.NET Core ein ausgeblendetes Formularfeld ähnlich dem folgenden Beispiel hinzu:

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

ASP.NET Core enthält drei Filter zum Arbeiten mit Token zum Schutz vor Fälschung:

Schutz vor Fälschung mit AddControllers

Beim Aufrufen von AddControllers werden keine Token zum Schutz vor Fälschung aktiviert. AddControllersWithViews muss aufgerufen werden, um integrierte Unterstützung von Token zum Schutz vor Fälschung zur Verfügung zu haben.

Mehrere Browserregisterkarten und das Synchronizer Token Pattern

Beim Synchronizer Token Pattern enthält nur die zuletzt geladene Seite ein gültiges Token zum Schutz vor Fälschung. Die Verwendung mehrerer Registerkarten kann problematisch sein. Beispielsweise, wenn ein Benutzer mehrere Registerkarten öffnet:

  • Nur die zuletzt geladene Registerkarte enthält ein gültiges Token zum Schutz vor Fälschung.
  • Anforderungen, die von zuvor geladenen Registerkarten gesendet werden, schlagen mit einem Fehler fehl: Antiforgery token validation failed. The antiforgery cookie token and request token do not match

Ziehen Sie alternative CSRF-Schutzmuster in Betracht, wenn dies ein Problem darstellt.

Konfigurieren des Schutzes vor Fälschung mit AntiforgeryOptions

Passen Sie AntiforgeryOptions in Program.cs an:

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

Legen Sie die Cookie-Eigenschaften für den Schutz vor Fälschung mithilfe der Eigenschaften der CookieBuilder-Klasse fest, wie in der folgenden Tabelle gezeigt.

Option Beschreibung
Cookie Bestimmt die Einstellungen, die zum Erstellen der cookies zum Schutz vor Fälschung verwendet werden.
FormFieldName Der Name des ausgeblendeten Formularfelds, das vom System zum Schutz vor Fälschungen zum Rendern von Token zum Schutz vor Fälschung in Ansichten verwendet wird.
HeaderName Der Name des Headers, der vom System zum Schutz vor Fälschung verwendet wird. Bei null berücksichtigt das System nur Formulardaten.
SuppressXFrameOptionsHeader Gibt an, ob die Generierung des Headers X-Frame-Options unterdrückt werden soll. Standardmäßig wird der Header mit dem Wert „SAMEORIGIN“ generiert. Wird standardmäßig auf false festgelegt.

Weitere Informationen finden Sie unter CookieAuthenticationOptions.

Generieren von Token zum Schutz vor Fälschung mit IAntiforgery

IAntiforgery stellt die API zum Konfigurieren von Features zum Schutz vor Fälschung zur Verfügung. IAntiforgery kann in Program.cs mit WebApplication.Services angefordert werden. Im folgenden Beispiel wird Middleware von der Startseite der App verwendet, um ein Token zum Schutz vor Fälschung zu generieren und es in der Antwort als cookie zu senden:

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

Im vorstehenden Beispiel wird ein cookie mit dem Namen XSRF-TOKEN festgelegt. Der Client kann dieses cookie lesen und seinen Wert als Header angeben, der an AJAX-Anforderungen angefügt ist. Beispielsweise enthält Angular integrierten XSRF-Schutz, der standardmäßig ein cookie mit dem Namen XSRF-TOKEN liest.

Vorschreiben der Überprüfung des Schutzes vor Fälschungen

Der Aktionsfilter ValidateAntiForgeryToken kann auf eine einzelne Aktion, einen Controller oder global angewendet werden. Anforderungen an Aktionen, für die dieser Filter angewendet wird, werden blockiert, es sei denn, die Anforderung enthält ein gültiges Token zum Schutz vor Fälschung:

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

    return RedirectToAction();
}

Das ValidateAntiForgeryToken-Attribut erfordert ein Token für Anforderungen an die Aktionsmethoden, die es markiert, einschließlich HTTP GET-Anforderungen. Wenn das ValidateAntiForgeryToken-Attribut auf die Controller der App angewendet wird, kann es mit dem IgnoreAntiforgeryToken-Attribut außer Kraft gesetzt werden.

Automatische Überprüfung von Token zum Schutz vor Fälschung nur für unsichere HTTP-Methoden

Anstatt das ValidateAntiForgeryToken-Attribut in großem Umfang anzuwenden und es dann mit IgnoreAntiforgeryToken-Attributen außer Kraft zu setzen, kann das Attribut AutoValidateAntiforgeryToken verwendet werden. Dieses Attribut funktioniert identisch mit dem ValidateAntiForgeryToken-Attribut, mit dem Unterschied, dass es keine Token für Anforderungen erfordert, die mit den folgenden HTTP-Methoden vorgenommen werden:

  • GET
  • HEAD
  • OPTIONEN
  • TRACE

Es empfiehlt sich, für Szenarien ohne API AutoValidateAntiforgeryToken in großem Umfang zu verwenden. Dieses Attribut stellt sicher, dass POST-Aktionen standardmäßig geschützt sind. Alternativ können Sie Token zum Schutz vor Fälschung standardmäßig ignorieren, es sei denn, ValidateAntiForgeryToken wird auf einzelne Aktionsmethoden angewendet. In diesem Szenario ist es wahrscheinlicher, dass eine POST-Aktionsmethode versehentlich nicht geschützt wird, sodass die App für CSRF-Angriffe anfällig bleibt. Alle POSTs sollten das Token zum Schutz vor Fälschung senden.

APIs verfügen nicht über einen automatischen Mechanismus zum Senden des Nicht-cookie-Teils des Tokens. Die Implementierung hängt wahrscheinlich von der Clientcodeimplementierung ab. Nachfolgend werden einige Beispiele veranschaulicht:

Beispiel auf Klassenebene:

[AutoValidateAntiforgeryToken]
public class HomeController : Controller

Globales Beispiel:

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

Außerkraftsetzung von globalen oder Controller-Attributen zum Schutz vor Fälschung

Der Filter IgnoreAntiforgeryToken wird verwendet, um die Notwendigkeit eines Tokens zum Schutz vor Fälschung für eine bestimmte Aktion (oder einen Controller) zu beseitigen. Bei Anwendung setzt dieser Filter die Filter ValidateAntiForgeryToken und AutoValidateAntiforgeryToken außer Kraft, die auf einer höheren Ebene (global oder auf einem Controller) angegeben sind.

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

    return RedirectToAction();
}

Aktualisieren von Token nach der Authentifizierung

Token sollten nach der Authentifizierung des Benutzers aktualisiert werden, indem der Benutzer zu einer Ansicht oder Razor Pages-Seite umgeleitet wird.

JavaScript, AJAX und SPAs

In herkömmlichen HTML-basierten Apps werden Token zum Schutz vor Fälschung mithilfe ausgeblendeter Formularfelder an den Server übergeben. In modernen JavaScript-basierten Apps und SPAs erfolgen viele Anforderungen programmgesteuert. Diese AJAX-Anforderungen können andere Techniken (z. B. Anforderungsheader oder cookies) zum Senden des Tokens verwenden.

Wenn cookies verwendet wird, um Authentifizierungstoken zu speichern und API-Anforderungen auf dem Server zu authentifizieren, ist CSRF ein potenzielles Problem. Wenn der lokale Speicher zum Speichern des Tokens verwendet wird, kann das CSRF-Sicherheitsrisiko gemildert werden, da Werte aus dem lokalen Speicher nicht bei jeder Anforderung automatisch an den Server gesendet werden. Die Verwendung des lokalen Speichers zum Speichern des Tokens zum Schutz vor Fälschung auf dem Client und das Senden des Tokens als Anforderungsheader stellt einen empfohlenen Ansatz dar.

JavaScript

Mithilfe von JavaScript in Verbindung mit Ansichten kann das Token mithilfe eines Diensts innerhalb der Ansicht erstellt werden. Schleusen Sie den IAntiforgery-Dienst in die Ansicht ein, und rufen Sie GetAndStoreTokens auf:

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

Im vorstehenden Beispiel wird JavaScript verwendet, um den Wert des ausgeblendeten Felds für den AJAX POST-Header zu lesen.

Durch diesen Ansatz entfällt die Notwendigkeit, sich direkt mit dem Festlegen von cookies durch den Server oder dem Lesen durch den Client zu befassen. Wenn das Einschleusen des IAntiforgery-Diensts jedoch nicht möglich ist, verwenden Sie JavaScript, um auf Token in cookies zuzugreifen:

  • Greifen Sie auf Token in einer zusätzlichen Anforderung an den Server zu, in der Regel same-origin.
  • Verwenden Sie den Inhalt des cookies, um einen Header mit dem Wert des Tokens zu erstellen.

Wenn das Skript das Token in einem Anforderungsheader namens X-XSRF-TOKENsendet, konfigurieren Sie den Dienst zum Schutz vor Fälschung, um nach dem Header X-XSRF-TOKEN zu suchen:

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

Im folgenden Beispiel wird ein geschützter Endpunkt hinzugefügt, der das Anforderungstoken in ein durch JavaScript lesbares cookie schreibt:

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

Im folgenden Beispiel wird JavaScript verwendet, um eine AJAX-Anforderung zu erstellen, um das Token abzurufen und eine weitere Anforderung mit dem entsprechenden Header zu erstellen:

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

Hinweis

Wenn das Token zum Schutz vor Fälschung sowohl im Anforderungsheader als auch in den Formularnutzdaten bereitgestellt wird, wird nur das Token im Header überprüft.

Schutz vor Fälschung mit Minimal APIs

Minimal APIs unterstützt die Verwendung der enthaltenen Filter (ValidateAntiForgeryToken, AutoValidateAntiforgeryToken, IgnoreAntiforgeryToken) nicht, jedoch bietet IAntiforgery die erforderlichen APIs, um eine Anforderung zu überprüfen.

Im folgenden Beispiel wird ein Filter erstellt, der das Token zum Schutz vor Fälschung überprüft:

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

        });
    }
}

Der Filter kann dann auf einen Endpunkt angewendet werden:

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

Windows-Authentifizierung und cookies zum Schutz vor Fälschung

Bei Verwendung der Windows-Authentifizierung müssen Anwendungsendpunkte auf die gleiche Weise wie cookies vor CSRF-Angriffen geschützt werden. Der Browser sendet implizit den Authentifizierungskontext an den Server, und Endpunkte müssen vor CSRF-Angriffen geschützt werden.

Erweitern des Schutzes vor Fälschung

Der IAntiforgeryAdditionalDataProvider-Typ ermöglicht es Entwicklern, das Verhalten des Anti-CSRF-Systems mithilfe von Round-Trips zusätzlicher Daten in jedem Token zu erweitern. Die GetAdditionalData-Methode wird jedes Mal aufgerufen, wenn ein Feldtoken generiert wird, und der Rückgabewert wird in das generierte Token eingebettet. Ein Implementierer kann einen Zeitstempel, eine Nonce oder einen anderen Wert zurückgeben und dann ValidateAdditionalData aufrufen, um diese Daten zu überprüfen, wenn das Token überprüft wird. Der Benutzername des Clients ist bereits in die generierten Token eingebettet, sodass diese Informationen nicht eingeschlossen werden müssen. Wenn ein Token zusätzliche Daten enthält, aber kein IAntiForgeryAdditionalDataProvider konfiguriert ist, werden die zusätzlichen Daten nicht überprüft.

Zusätzliche Ressourcen

Bei einer websiteübergreifenden Anforderungsfälschung (auch bekannt als XSRF oder CSRF) handelt es sich um einen Angriff auf im Web gehostete Apps, durch den eine schädliche Web-App die Interaktion zwischen einem Clientbrowser und einer Web-App beeinflussen kann, die diesem Browser vertraut. Diese Angriffe sind möglich, weil Webbrowser einige Typen von Authentifizierungstoken automatisch bei jeder Anforderung an eine Website senden. Diese Form von Exploit wird auch als Ein-Klick-Angriff oder Session-Riding bezeichnet, weil für den Angriff die zuvor authentifizierte Sitzung des Benutzers verwendet wird.

Ein Beispiel für einen CSRF-Angriff:

  1. Ein Benutzer meldet sich bei www.good-banking-site.example.com mit der Formularauthentifizierung an. Der Server authentifiziert den Benutzer und gibt eine Antwort aus, die ein Authentifizierungscookie enthält. Die Website ist anfällig für Angriffe, da sie jeder Anforderung vertraut, die sie mit einem gültigen Authentifizierungscookie empfängt.

  2. Der Benutzer besucht eine böswillige Website, www.bad-crook-site.example.com.

    Die böswillige Website www.bad-crook-site.example.com enthält ein HTML-Formular, das dem folgenden Beispiel ähnelt:

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

    Beachten Sie, dass die action des Formulars auf der anfälligen Website veröffentlicht, nicht auf der böswilligen Website. Dies ist der websiteübergreifende Teil von CSRF.

  3. Der Benutzer wählt die Senden-Schaltfläche aus. Der Browser führt die Anforderung aus und schließt automatisch die Authentifizierung cookie für die angeforderte Domäne www.good-banking-site.example.com ein.

  4. Die Anforderung wird auf dem www.good-banking-site.example.com-Server mit dem Authentifizierungskontext des Benutzers ausgeführt und kann jede Aktion ausführen, die ein authentifizierter Benutzer ausführen darf.

Über das Szenario hinaus, in dem der Benutzer die Schaltfläche zum Senden des Formulars auswählt, kann die böswillige Website Folgendes bewirken:

  • ein Skript ausführen, mit dem das Formular automatisch übermittelt wird.
  • die Formularübermittlung als AJAX-Anforderung senden.
  • das Formular mithilfe von CSS ausblenden.

Diese alternativen Szenarien erfordern keinerlei Aktion oder Eingabe seitens des Benutzers über den ursprünglichen Besuch der böswilligen Website hinaus.

Die Verwendung von HTTPS verhindert keinen CSRF-Angriff. Die böswillige Website kann eine https://www.good-banking-site.com/-Anforderung ebenso einfach senden wie eine unsichere Anforderung.

Einige Angriffe zielen auf Endpunkte ab, die auf GET-Anforderungen reagieren. In diesem Fall kann ein Bildtag verwendet werden, um die Aktion auszuführen. Diese Form des Angriffs ist auf Forenwebsites üblich, die Bilder zulassen, aber JavaScript blockieren. Apps, die den Status bei GET-Anforderungen ändern, bei denen Variablen oder Ressourcen geändert werden, sind anfällig für böswillige Angriffe. GET-Anforderungen, die den Status ändern, sind unsicher. Eine bewährte Methode besteht darin, niemals Statusänderungen auf eine GET-Anforderung hin vorzunehmen.

CSRF-Angriffe sind gegen Web-Apps möglich, die cookies für die Authentifizierung verwenden, weil:

  • Browser die von einer Web-App ausgegebenen cookies speichern
  • Gespeicherte cookies Sitzungscookies für authentifizierte Benutzer enthalten
  • Browser alle einer Domäne zugeordneten cookies auf jede Anforderung an die Web-App senden, unabhängig davon, wie die Anforderung an die App innerhalb des Browsers generiert wurde.

CSRF-Angriffe sind jedoch nicht auf die Ausnutzung von cookies beschränkt. Beispielsweise sind auch die Standard- und Digestauthentifizierung anfällig. Nachdem sich ein Benutzer mit der Standard- oder Digest-Authentifizierung angemeldet hat, sendet der Browser die Anmeldeinformationen automatisch, bis die Sitzung endet.

In diesem Kontext bezieht sich Sitzung auf die clientseitige Sitzung, in der der Benutzer authentifiziert wird. Dies hat nichts mit serverseitigen Sitzungen oder ASP.NET Core Sitzungs-Middleware zu tun.

Benutzer können sich vor CSRF-Sicherheitsrisiken schützen, indem sie Vorkehrungen treffen:

  • Bei Web-Apps abmelden, wenn die Nutzung abgeschlossen ist
  • Browsercookies in regelmäßigen Abständen löschen

CSRF-Sicherheitsrisiken sind jedoch grundsätzlich ein Problem der Web-App, nicht des Endbenutzers.

Grundlagen der Authentifizierung

Cookie-basierte Authentifizierung ist eine beliebte Form der Authentifizierung. Tokenbasierte Authentifizierungssysteme werden immer beliebter, insbesondere für Single Page Applications (SPAs).

Wenn sich ein Benutzer mithilfe seines Benutzernamens und Kennworts authentifiziert, wird ein Token ausgestellt, das ein Authentifizierungsticket enthält, das für die Authentifizierung und Autorisierung verwendet werden kann. Das Token wird als ein cookie gespeichert, das mit jeder Anforderung des Clients gesendet wird. Die Generierung und Überprüfung dieses cookies erfolgt durch die Middleware zur Cookieauthentifizierung. Die Middleware serialisiert einen Benutzerprinzipal in ein verschlüsseltes cookie. Bei nachfolgenden Anforderungen überprüft die Middleware das cookie, erstellt den Prinzipal neu und weist den Prinzipal der HttpContext.User-Eigenschaft zu.

Tokenbasierte Authentifizierung

Wenn ein Benutzer authentifiziert wird, wird ein Token (kein Token zur Fälschungsverhinderung) ausgestellt. Das Token enthält Benutzerinformationen in Form von Ansprüchen oder eines Verweistokens, das die App auf den in der App verwalteten Benutzerstatus verweist. Wenn ein Benutzer versucht, auf eine Ressource zuzugreifen, die Authentifizierung erfordert, wird das Token mit einem zusätzlichen Autorisierungsheader in Form eines Bearertokens an die App gesendet. Durch diesen Ansatz wird die App zustandslos. In jeder nachfolgenden Anforderung wird das Token in der Anforderung zur serverseitigen Validierung übergeben. Dieses Token ist nicht verschlüsselt, sondern codiert. Auf dem Server wird das Token decodiert, um auf seine Informationen zuzugreifen. Zum Senden des Tokens bei nachfolgenden Anforderungen speichern Sie das Token im lokalen Speicher des Browsers. Machen Sie sich keine Sorgen über das CSRF-Sicherheitsrisiko, wenn das Token im lokalen Speicher des Browsers gespeichert wird. CSRF ist ein Problem, wenn das Token in einem cookie gespeichert wird. Weitere Informationen finden Sie im GitHub Issue SPA code sample adds two cookies (SPA-Codebeispiel fügt zwei Cookies hinzu).

Mehrere Apps, die in einer Domäne gehostet werden

Freigegebene Hostingumgebungen sind anfällig für Session Hijacking, Anmelde-CSRF und andere Angriffe.

Zwar sind example1.contoso.net und example2.contoso.net unterschiedliche Hosts, jedoch besteht eine implizite Vertrauensstellung zwischen Hosts unter der *.contoso.net-Domäne. Diese implizite Vertrauensstellung ermöglicht es potenziell nicht vertrauenswürdigen Hosts, gegenseitig Einfluss auf ihre cookies zu nehmen (die Richtlinien für gleichen Ursprung, die AJAX-Anforderungen steuern, gelten nicht zwangsläufig für HTTP-cookies.

Angriffe, die vertrauenswürdige cookies zwischen Apps ausnutzen, die in derselben Domäne gehostet werden, können verhindert werden, indem Domänen nicht freigegeben werden. Wenn jede App in ihrer eigenen Domäne gehostet wird, gibt es keine implizite cookie-Vertrauensstellung, die ausgenutzt werden kann.

Schutz vor Fälschung in ASP.NET Core

Warnung

ASP.NET Core implementiert Schutz vor Fälschung mithilfe von Datenschutz in ASP.NET Core. Der Datenschutzstapel muss für die Verwendung in einer Serverfarm konfiguriert werden. Weitere Informationen finden Sie unter Konfigurieren von Datenschutz.

Middleware zum Schutz vor Fälschung wird dem Dependency Injection-Container hinzugefügt, wenn eine der folgenden APIs in Program.cs aufgerufen wird:

Das Formulartag-Hilfsprogramm injiziert Anti-XSRF/CSRF-Token in HTML-Formularelemente. Das folgende Markup in einer Razor-Datei generiert automatisch Token zum Schutz vor Fälschung:

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

In ähnlicher Weise generiert IHtmlHelper.BeginForm standardmäßig Token zum Schutz vor Fälschung, wenn die Methode des Formulars nicht GET lautet.

Die automatische Generierung von Token zum Schutz vor Fälschung für HTML-Formularelemente erfolgt, wenn das <form>-Tag das method="post"-Attribut enthält und eine der folgenden Bedingungen zutrifft:

  • Das Aktionsattribut ist leer (action="").
  • Das Aktionsattribut ist nicht angegeben (<form method="post">).

Die automatische Generierung von Token zum Schutz vor Fälschung für HTML-Formularelemente kann deaktiviert werden:

  • Deaktivieren Sie Token zum Schutz vor Fälschung explizit mit dem asp-antiforgery-Attribut:

    <form method="post" asp-antiforgery="false">
        <!-- ... -->
    </form>
    
  • Das Formularelement wird aus Taghilfsprogrammen mit dem Tag Helper ! opt-out-Symbol abgewählt:

    <!form method="post">
        <!-- ... -->
    </!form>
    
  • Entfernen Sie den FormTagHelper aus der Ansicht. Der FormTagHelper kann aus einer Ansicht entfernt werden, indem Sie der Razor-Ansicht die folgende Anweisung hinzufügen:

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

Hinweis

Razor Pages werden automatisch vor XSRF/CSRF geschützt. Weitere Informationen finden Sie unter XSRF/CSRF und Razor Pages.

Der häufigste Ansatz zum Schutz vor CSRF-Angriffen ist die Verwendung des Synchronizer Token Pattern (STP). STP wird verwendet, wenn der Benutzer eine Seite mit Formulardaten anfordert:

  1. Der Server sendet ein Token, das der Identität des aktuellen Benutzers zugeordnet ist, an den Client.
  2. Der Client sendet das Token zur Überprüfung an den Server zurück.
  3. Wenn der Server ein Token empfängt, das nicht mit der Identität des authentifizierten Benutzers übereinstimmt, wird die Anforderung abgelehnt.

Das Token ist eindeutig und unvorhersehbar. Das Token kann außerdem verwendet werden, um die ordnungsgemäße Sequenzierung einer Reihe von Anforderungen sicherzustellen (etwa beim Sicherstellen der Anforderungssequenz von: Seite 1 > Seite 2 > Seite 3). Alle Formulare in ASP.NET Core MVC und die Razor Pages-Vorlagen generieren Token zum Schutz vor Fälschung. Die folgenden Ansichtsbeispiele generieren Token zum Schutz vor Fälschung:

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

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

Fügen Sie einem <form>-Element explizit ein Token zum Schutz vor Fälschung hinzu, ohne Tag Helpers mit dem HTML-Hilfsprogramm @Html.AntiForgeryToken zu verwenden:

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

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

In jedem der vorstehenden Fälle fügt ASP.NET Core ein ausgeblendetes Formularfeld ähnlich dem folgenden Beispiel hinzu:

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

ASP.NET Core enthält drei Filter zum Arbeiten mit Token zum Schutz vor Fälschung:

Schutz vor Fälschung mit AddControllers

Beim Aufrufen von AddControllers werden keine Token zum Schutz vor Fälschung aktiviert. AddControllersWithViews muss aufgerufen werden, um integrierte Unterstützung von Token zum Schutz vor Fälschung zur Verfügung zu haben.

Mehrere Browserregisterkarten und das Synchronizer Token Pattern

Beim Synchronizer Token Pattern enthält nur die zuletzt geladene Seite ein gültiges Token zum Schutz vor Fälschung. Die Verwendung mehrerer Registerkarten kann problematisch sein. Beispielsweise, wenn ein Benutzer mehrere Registerkarten öffnet:

  • Nur die zuletzt geladene Registerkarte enthält ein gültiges Token zum Schutz vor Fälschung.
  • Anforderungen, die von zuvor geladenen Registerkarten gesendet werden, schlagen mit einem Fehler fehl: Antiforgery token validation failed. The antiforgery cookie token and request token do not match

Ziehen Sie alternative CSRF-Schutzmuster in Betracht, wenn dies ein Problem darstellt.

Konfigurieren des Schutzes vor Fälschung mit AntiforgeryOptions

Passen Sie AntiforgeryOptions in Program.cs an:

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

Legen Sie die Cookie-Eigenschaften für den Schutz vor Fälschung mithilfe der Eigenschaften der CookieBuilder-Klasse fest, wie in der folgenden Tabelle gezeigt.

Option Beschreibung
Cookie Bestimmt die Einstellungen, die zum Erstellen der cookies zum Schutz vor Fälschung verwendet werden.
FormFieldName Der Name des ausgeblendeten Formularfelds, das vom System zum Schutz vor Fälschungen zum Rendern von Token zum Schutz vor Fälschung in Ansichten verwendet wird.
HeaderName Der Name des Headers, der vom System zum Schutz vor Fälschung verwendet wird. Bei null berücksichtigt das System nur Formulardaten.
SuppressXFrameOptionsHeader Gibt an, ob die Generierung des Headers X-Frame-Options unterdrückt werden soll. Standardmäßig wird der Header mit dem Wert „SAMEORIGIN“ generiert. Wird standardmäßig auf false festgelegt.

Weitere Informationen finden Sie unter CookieAuthenticationOptions.

Generieren von Token zum Schutz vor Fälschung mit IAntiforgery

IAntiforgery stellt die API zum Konfigurieren von Features zum Schutz vor Fälschung zur Verfügung. IAntiforgery kann in Program.cs mit WebApplication.Services angefordert werden. Im folgenden Beispiel wird Middleware von der Startseite der App verwendet, um ein Token zum Schutz vor Fälschung zu generieren und es in der Antwort als cookie zu senden:

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

Im vorstehenden Beispiel wird ein cookie mit dem Namen XSRF-TOKEN festgelegt. Der Client kann dieses cookie lesen und seinen Wert als Header angeben, der an AJAX-Anforderungen angefügt ist. Beispielsweise enthält Angular integrierten XSRF-Schutz, der standardmäßig ein cookie mit dem Namen XSRF-TOKEN liest.

Vorschreiben der Überprüfung des Schutzes vor Fälschungen

Der Aktionsfilter ValidateAntiForgeryToken kann auf eine einzelne Aktion, einen Controller oder global angewendet werden. Anforderungen an Aktionen, für die dieser Filter angewendet wird, werden blockiert, es sei denn, die Anforderung enthält ein gültiges Token zum Schutz vor Fälschung:

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

    return RedirectToAction();
}

Das ValidateAntiForgeryToken-Attribut erfordert ein Token für Anforderungen an die Aktionsmethoden, die es markiert, einschließlich HTTP GET-Anforderungen. Wenn das ValidateAntiForgeryToken-Attribut auf die Controller der App angewendet wird, kann es mit dem IgnoreAntiforgeryToken-Attribut außer Kraft gesetzt werden.

Automatische Überprüfung von Token zum Schutz vor Fälschung nur für unsichere HTTP-Methoden

Anstatt das ValidateAntiForgeryToken-Attribut in großem Umfang anzuwenden und es dann mit IgnoreAntiforgeryToken-Attributen außer Kraft zu setzen, kann das Attribut AutoValidateAntiforgeryToken verwendet werden. Dieses Attribut funktioniert identisch mit dem ValidateAntiForgeryToken-Attribut, mit dem Unterschied, dass es keine Token für Anforderungen erfordert, die mit den folgenden HTTP-Methoden vorgenommen werden:

  • GET
  • HEAD
  • OPTIONEN
  • TRACE

Es empfiehlt sich, für Szenarien ohne API AutoValidateAntiforgeryToken in großem Umfang zu verwenden. Dieses Attribut stellt sicher, dass POST-Aktionen standardmäßig geschützt sind. Alternativ können Sie Token zum Schutz vor Fälschung standardmäßig ignorieren, es sei denn, ValidateAntiForgeryToken wird auf einzelne Aktionsmethoden angewendet. In diesem Szenario ist es wahrscheinlicher, dass eine POST-Aktionsmethode versehentlich nicht geschützt wird, sodass die App für CSRF-Angriffe anfällig bleibt. Alle POSTs sollten das Token zum Schutz vor Fälschung senden.

APIs verfügen nicht über einen automatischen Mechanismus zum Senden des Nicht-cookie-Teils des Tokens. Die Implementierung hängt wahrscheinlich von der Clientcodeimplementierung ab. Nachfolgend werden einige Beispiele veranschaulicht:

Beispiel auf Klassenebene:

[AutoValidateAntiforgeryToken]
public class HomeController : Controller

Globales Beispiel:

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

Außerkraftsetzung von globalen oder Controller-Attributen zum Schutz vor Fälschung

Der Filter IgnoreAntiforgeryToken wird verwendet, um die Notwendigkeit eines Tokens zum Schutz vor Fälschung für eine bestimmte Aktion (oder einen Controller) zu beseitigen. Bei Anwendung setzt dieser Filter die Filter ValidateAntiForgeryToken und AutoValidateAntiforgeryToken außer Kraft, die auf einer höheren Ebene (global oder auf einem Controller) angegeben sind.

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

    return RedirectToAction();
}

Aktualisieren von Token nach der Authentifizierung

Token sollten nach der Authentifizierung des Benutzers aktualisiert werden, indem der Benutzer zu einer Ansicht oder Razor Pages-Seite umgeleitet wird.

JavaScript, AJAX und SPAs

In herkömmlichen HTML-basierten Apps werden Token zum Schutz vor Fälschung mithilfe ausgeblendeter Formularfelder an den Server übergeben. In modernen JavaScript-basierten Apps und SPAs erfolgen viele Anforderungen programmgesteuert. Diese AJAX-Anforderungen können andere Techniken (z. B. Anforderungsheader oder cookies) zum Senden des Tokens verwenden.

Wenn cookies verwendet wird, um Authentifizierungstoken zu speichern und API-Anforderungen auf dem Server zu authentifizieren, ist CSRF ein potenzielles Problem. Wenn der lokale Speicher zum Speichern des Tokens verwendet wird, kann das CSRF-Sicherheitsrisiko gemildert werden, da Werte aus dem lokalen Speicher nicht bei jeder Anforderung automatisch an den Server gesendet werden. Die Verwendung des lokalen Speichers zum Speichern des Tokens zum Schutz vor Fälschung auf dem Client und das Senden des Tokens als Anforderungsheader stellt einen empfohlenen Ansatz dar.

JavaScript

Mithilfe von JavaScript in Verbindung mit Ansichten kann das Token mithilfe eines Diensts innerhalb der Ansicht erstellt werden. Schleusen Sie den IAntiforgery-Dienst in die Ansicht ein, und rufen Sie GetAndStoreTokens auf:

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

Im vorstehenden Beispiel wird JavaScript verwendet, um den Wert des ausgeblendeten Felds für den AJAX POST-Header zu lesen.

Durch diesen Ansatz entfällt die Notwendigkeit, sich direkt mit dem Festlegen von cookies durch den Server oder dem Lesen durch den Client zu befassen. Wenn das Einschleusen des IAntiforgery-Diensts jedoch nicht möglich ist, kann JavaScript auch auf das Token in cookies zugreifen, die durch eine zusätzliche Anforderung an den Server abgerufen werden (in der Regel same-origin), und den Inhalt des cookies verwenden, um einen Header mit dem Wert des Tokens zu erstellen.

Wenn das Skript das Token in einem Anforderungsheader namens X-XSRF-TOKENsendet, konfigurieren Sie den Dienst zum Schutz vor Fälschung, um nach dem Header X-XSRF-TOKEN zu suchen:

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

Im folgenden Beispiel wird ein geschützter Endpunkt hinzugefügt, der das Anforderungstoken in ein durch JavaScript lesbares cookie schreibt:

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

Im folgenden Beispiel wird JavaScript verwendet, um eine AJAX-Anforderung zu erstellen, um das Token abzurufen und eine weitere Anforderung mit dem entsprechenden Header zu erstellen:

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-Authentifizierung und cookies zum Schutz vor Fälschung

Bei Verwendung der Windows-Authentifizierung müssen Anwendungsendpunkte auf die gleiche Weise wie cookies vor CSRF-Angriffen geschützt werden. Der Browser sendet implizit den Authentifizierungskontext an den Server, daher müssen Endpunkte vor CSRF-Angriffen geschützt werden.

Erweitern des Schutzes vor Fälschung

Der IAntiforgeryAdditionalDataProvider-Typ ermöglicht es Entwicklern, das Verhalten des Anti-CSRF-Systems mithilfe von Round-Trips zusätzlicher Daten in jedem Token zu erweitern. Die GetAdditionalData-Methode wird jedes Mal aufgerufen, wenn ein Feldtoken generiert wird, und der Rückgabewert wird in das generierte Token eingebettet. Ein Implementierer kann einen Zeitstempel, eine Nonce oder einen anderen Wert zurückgeben und dann ValidateAdditionalData aufrufen, um diese Daten zu überprüfen, wenn das Token überprüft wird. Der Benutzername des Clients ist bereits in die generierten Token eingebettet, sodass diese Informationen nicht eingeschlossen werden müssen. Wenn ein Token zusätzliche Daten enthält, aber kein IAntiForgeryAdditionalDataProvider konfiguriert ist, werden die zusätzlichen Daten nicht überprüft.

Zusätzliche Ressourcen

Bei einer websiteübergreifenden Anforderungsfälschung (auch bekannt als XSRF oder CSRF) handelt es sich um einen Angriff auf im Web gehostete Apps, durch den eine schädliche Web-App die Interaktion zwischen einem Clientbrowser und einer Web-App beeinflussen kann, die diesem Browser vertraut. Diese Angriffe sind möglich, weil Webbrowser einige Typen von Authentifizierungstoken automatisch bei jeder Anforderung an eine Website senden. Diese Form von Exploit wird auch als Ein-Klick-Angriff oder Session-Riding bezeichnet, weil für den Angriff die zuvor authentifizierte Sitzung des Benutzers verwendet wird.

Ein Beispiel für einen CSRF-Angriff:

  1. Ein Benutzer meldet sich bei www.good-banking-site.example.com mit der Formularauthentifizierung an. Der Server authentifiziert den Benutzer und gibt eine Antwort aus, die ein Authentifizierungscookie enthält. Die Website ist anfällig für Angriffe, da sie jeder Anforderung vertraut, die sie mit einem gültigen Authentifizierungscookie empfängt.

  2. Der Benutzer besucht eine böswillige Website, www.bad-crook-site.example.com.

    Die böswillige Website www.bad-crook-site.example.com enthält ein HTML-Formular, das dem folgenden Beispiel ähnelt:

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

    Beachten Sie, dass die action des Formulars auf der anfälligen Website veröffentlicht, nicht auf der böswilligen Website. Dies ist der websiteübergreifende Teil von CSRF.

  3. Der Benutzer wählt die Senden-Schaltfläche aus. Der Browser führt die Anforderung aus und schließt automatisch die Authentifizierung cookie für die angeforderte Domäne www.good-banking-site.example.com ein.

  4. Die Anforderung wird auf dem www.good-banking-site.example.com-Server mit dem Authentifizierungskontext des Benutzers ausgeführt und kann jede Aktion ausführen, die ein authentifizierter Benutzer ausführen darf.

Über das Szenario hinaus, in dem der Benutzer die Schaltfläche zum Senden des Formulars auswählt, kann die böswillige Website Folgendes bewirken:

  • ein Skript ausführen, mit dem das Formular automatisch übermittelt wird.
  • die Formularübermittlung als AJAX-Anforderung senden.
  • das Formular mithilfe von CSS ausblenden.

Diese alternativen Szenarien erfordern keinerlei Aktion oder Eingabe seitens des Benutzers über den ursprünglichen Besuch der böswilligen Website hinaus.

Die Verwendung von HTTPS verhindert keinen CSRF-Angriff. Die böswillige Website kann eine https://www.good-banking-site.com/-Anforderung ebenso einfach senden wie eine unsichere Anforderung.

Einige Angriffe zielen auf Endpunkte ab, die auf GET-Anforderungen reagieren. In diesem Fall kann ein Bildtag verwendet werden, um die Aktion auszuführen. Diese Form des Angriffs ist auf Forenwebsites üblich, die Bilder zulassen, aber JavaScript blockieren. Apps, die den Status bei GET-Anforderungen ändern, bei denen Variablen oder Ressourcen geändert werden, sind anfällig für böswillige Angriffe. GET-Anforderungen, die den Status ändern, sind unsicher. Eine bewährte Methode besteht darin, niemals Statusänderungen auf eine GET-Anforderung hin vorzunehmen.

CSRF-Angriffe sind gegen Web-Apps möglich, die cookies für die Authentifizierung verwenden, weil:

  • Browser die von einer Web-App ausgegebenen cookies speichern
  • Gespeicherte cookies Sitzungscookies für authentifizierte Benutzer enthalten
  • Browser alle einer Domäne zugeordneten cookies auf jede Anforderung an die Web-App senden, unabhängig davon, wie die Anforderung an die App innerhalb des Browsers generiert wurde.

CSRF-Angriffe sind jedoch nicht auf die Ausnutzung von cookies beschränkt. Beispielsweise sind auch die Standard- und Digestauthentifizierung anfällig. Nachdem sich ein Benutzer mit der Standard- oder Digest-Authentifizierung angemeldet hat, sendet der Browser die Anmeldeinformationen automatisch, bis die Sitzung endet.

In diesem Kontext bezieht sich Sitzung auf die clientseitige Sitzung, in der der Benutzer authentifiziert wird. Dies hat nichts mit serverseitigen Sitzungen oder ASP.NET Core Sitzungs-Middleware zu tun.

Benutzer können sich vor CSRF-Sicherheitsrisiken schützen, indem sie Vorkehrungen treffen:

  • Bei Web-Apps abmelden, wenn die Nutzung abgeschlossen ist
  • Browsercookies in regelmäßigen Abständen löschen

CSRF-Sicherheitsrisiken sind jedoch grundsätzlich ein Problem der Web-App, nicht des Endbenutzers.

Grundlagen der Authentifizierung

Cookie-basierte Authentifizierung ist eine beliebte Form der Authentifizierung. Tokenbasierte Authentifizierungssysteme werden immer beliebter, insbesondere für Single Page Applications (SPAs).

Wenn sich ein Benutzer mithilfe seines Benutzernamens und Kennworts authentifiziert, wird ein Token ausgestellt, das ein Authentifizierungsticket enthält, das für die Authentifizierung und Autorisierung verwendet werden kann. Das Token wird als ein cookie gespeichert, das mit jeder Anforderung des Clients gesendet wird. Die Generierung und Überprüfung dieses cookies erfolgt durch die Middleware zur Cookieauthentifizierung. Die Middleware serialisiert einen Benutzerprinzipal in ein verschlüsseltes cookie. Bei nachfolgenden Anforderungen überprüft die Middleware das cookie, erstellt den Prinzipal neu und weist den Prinzipal der HttpContext.User-Eigenschaft zu.

Tokenbasierte Authentifizierung

Wenn ein Benutzer authentifiziert wird, wird ein Token (kein Token zur Fälschungsverhinderung) ausgestellt. Das Token enthält Benutzerinformationen in Form von Ansprüchen oder eines Verweistokens, das die App auf den in der App verwalteten Benutzerstatus verweist. Wenn ein Benutzer versucht, auf eine Ressource zuzugreifen, die Authentifizierung erfordert, wird das Token mit einem zusätzlichen Autorisierungsheader in Form eines Bearertokens an die App gesendet. Durch diesen Ansatz wird die App zustandslos. In jeder nachfolgenden Anforderung wird das Token in der Anforderung zur serverseitigen Validierung übergeben. Dieses Token ist nicht verschlüsselt, sondern codiert. Auf dem Server wird das Token decodiert, um auf seine Informationen zuzugreifen. Zum Senden des Tokens bei nachfolgenden Anforderungen speichern Sie das Token im lokalen Speicher des Browsers. Machen Sie sich keine Sorgen über das CSRF-Sicherheitsrisiko, wenn das Token im lokalen Speicher des Browsers gespeichert wird. CSRF ist ein Problem, wenn das Token in einem cookie gespeichert wird. Weitere Informationen finden Sie im GitHub Issue SPA code sample adds two cookies (SPA-Codebeispiel fügt zwei Cookies hinzu).

Mehrere Apps, die in einer Domäne gehostet werden

Freigegebene Hostingumgebungen sind anfällig für Session Hijacking, Anmelde-CSRF und andere Angriffe.

Zwar sind example1.contoso.net und example2.contoso.net unterschiedliche Hosts, jedoch besteht eine implizite Vertrauensstellung zwischen Hosts unter der *.contoso.net-Domäne. Diese implizite Vertrauensstellung ermöglicht es potenziell nicht vertrauenswürdigen Hosts, gegenseitig Einfluss auf ihre cookies zu nehmen (die Richtlinien für gleichen Ursprung, die AJAX-Anforderungen steuern, gelten nicht zwangsläufig für HTTP-cookies.

Angriffe, die vertrauenswürdige cookies zwischen Apps ausnutzen, die in derselben Domäne gehostet werden, können verhindert werden, indem Domänen nicht freigegeben werden. Wenn jede App in ihrer eigenen Domäne gehostet wird, gibt es keine implizite cookie-Vertrauensstellung, die ausgenutzt werden kann.

ASP.NET Core-Konfiguration zum Schutz vor Fälschung

Warnung

ASP.NET Core implementiert Schutz vor Fälschung mithilfe von Datenschutz in ASP.NET Core. Der Datenschutzstapel muss für die Verwendung in einer Serverfarm konfiguriert werden. Weitere Informationen finden Sie unter Konfigurieren von Datenschutz.

Middleware zum Schutz vor Fälschung wird dem Dependency Injection-Container hinzugefügt, wenn eine der folgenden APIs in Startup.ConfigureServices aufgerufen wird:

In ASP.NET Core 2.0 oder höher injiziert der FormTagHelper Token zum Schutz vor Fälschung in HTML-Formularelemente. Das folgende Markup in einer Razor-Datei generiert automatisch Token zum Schutz vor Fälschung:

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

In ähnlicher Weise generiert IHtmlHelper.BeginForm standardmäßig Token zum Schutz vor Fälschung, wenn die Methode des Formulars nicht GET lautet.

Die automatische Generierung von Token zum Schutz vor Fälschung für HTML-Formularelemente erfolgt, wenn das <form>-Tag das method="post"-Attribut enthält und eine der folgenden Bedingungen zutrifft:

  • Das Aktionsattribut ist leer (action="").
  • Das Aktionsattribut ist nicht angegeben (<form method="post">).

Die automatische Generierung von Token zum Schutz vor Fälschung für HTML-Formularelemente kann deaktiviert werden:

  • Deaktivieren Sie Token zum Schutz vor Fälschung explizit mit dem asp-antiforgery-Attribut:

    <form method="post" asp-antiforgery="false">
        ...
    </form>
    
  • Das Formularelement wird aus Taghilfsprogrammen mit dem Tag Helper ! opt-out-Symbol abgewählt:

    <!form method="post">
        ...
    </!form>
    
  • Entfernen Sie den FormTagHelper aus der Ansicht. Der FormTagHelper kann aus einer Ansicht entfernt werden, indem Sie der Razor-Ansicht die folgende Anweisung hinzufügen:

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

Hinweis

Razor Pages werden automatisch vor XSRF/CSRF geschützt. Weitere Informationen finden Sie unter XSRF/CSRF und Razor Pages.

Der häufigste Ansatz zum Schutz vor CSRF-Angriffen ist die Verwendung des Synchronizer Token Pattern (STP). STP wird verwendet, wenn der Benutzer eine Seite mit Formulardaten anfordert:

  1. Der Server sendet ein Token, das der Identität des aktuellen Benutzers zugeordnet ist, an den Client.
  2. Der Client sendet das Token zur Überprüfung an den Server zurück.
  3. Wenn der Server ein Token empfängt, das nicht mit der Identität des authentifizierten Benutzers übereinstimmt, wird die Anforderung abgelehnt.

Das Token ist eindeutig und unvorhersehbar. Das Token kann außerdem verwendet werden, um die ordnungsgemäße Sequenzierung einer Reihe von Anforderungen sicherzustellen (etwa beim Sicherstellen der Anforderungssequenz von: Seite 1 > Seite 2 > Seite 3). Alle Formulare in ASP.NET Core MVC und die Razor Pages-Vorlagen generieren Token zum Schutz vor Fälschung. Die folgenden Ansichtsbeispiele generieren Token zum Schutz vor Fälschung:

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

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

Fügen Sie einem <form>-Element explizit ein Token zum Schutz vor Fälschung hinzu, ohne Tag Helpers mit dem HTML-Hilfsprogramm @Html.AntiForgeryToken zu verwenden:

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

In jedem der vorstehenden Fälle fügt ASP.NET Core ein ausgeblendetes Formularfeld ähnlich dem folgenden Beispiel hinzu:

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

ASP.NET Core enthält drei Filter zum Arbeiten mit Token zum Schutz vor Fälschung:

Optionen zum Schutz vor Fälschung

Passen Sie AntiforgeryOptions in Startup.ConfigureServices an:

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

Legen Sie die Cookie-Eigenschaften für den Schutz vor Fälschung mithilfe der Eigenschaften der CookieBuilder-Klasse fest, wie in der folgenden Tabelle gezeigt.

Option Beschreibung
Cookie Bestimmt die Einstellungen, die zum Erstellen der cookies zum Schutz vor Fälschung verwendet werden.
FormFieldName Der Name des ausgeblendeten Formularfelds, das vom System zum Schutz vor Fälschungen zum Rendern von Token zum Schutz vor Fälschung in Ansichten verwendet wird.
HeaderName Der Name des Headers, der vom System zum Schutz vor Fälschung verwendet wird. Bei null berücksichtigt das System nur Formulardaten.
SuppressXFrameOptionsHeader Gibt an, ob die Generierung des Headers X-Frame-Options unterdrückt werden soll. Standardmäßig wird der Header mit dem Wert „SAMEORIGIN“ generiert. Wird standardmäßig auf false festgelegt.

Weitere Informationen finden Sie unter CookieAuthenticationOptions.

Konfigurieren von Features zum Schutz vor Fälschung mit IAntiforgery

IAntiforgery stellt die API zum Konfigurieren von Features zum Schutz vor Fälschung zur Verfügung. IAntiforgery kann in der Configure-Methode der Startup-Klasse angefordert werden.

Im folgenden Beispiel:

  • Middleware von der Startseite der App wird verwendet, um ein Token zum Schutz vor Fälschung zu generieren und es in der Antwort als cookie zu senden.
  • Das Anforderungstoken wird als JavaScript-lesbares cookie mit der im Abschnitt AngularJS beschriebenen Angular-Standardbenennungskonvention gesendet.
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);
    });
}

Vorschreiben der Überprüfung des Schutzes vor Fälschungen

ValidateAntiForgeryToken ist ein Aktionsfilter, der auf eine einzelne Aktion, einen Controller oder global angewendet werden kann. Anforderungen an Aktionen, für die dieser Filter angewendet wird, werden blockiert, es sei denn, die Anforderung enthält ein gültiges Token zum Schutz vor Fälschung.

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

Das ValidateAntiForgeryToken-Attribut erfordert ein Token für Anforderungen an die Aktionsmethoden, die es markiert, einschließlich HTTP GET-Anforderungen. Wenn das ValidateAntiForgeryToken-Attribut auf die Controller der App angewendet wird, kann es mit dem IgnoreAntiforgeryToken-Attribut außer Kraft gesetzt werden.

Hinweis

ASP.NET Core unterstützt das automatische Hinzufügen von Token zum Schutz vor Fälschung zu GET-Anforderungen nicht.

Automatische Überprüfung von Token zum Schutz vor Fälschung nur für unsichere HTTP-Methoden

ASP.NET Core-Apps generieren keine Token zum Schutz vor Fälschung für sichere HTTP-Methoden (GET, HEAD, OPTIONS und TRACE). Anstatt das ValidateAntiForgeryToken-Attribut in großem Umfang anzuwenden und es dann mit IgnoreAntiforgeryToken-Attributen außer Kraft zu setzen, kann das Attribut AutoValidateAntiforgeryToken verwendet werden. Dieses Attribut funktioniert identisch mit dem ValidateAntiForgeryToken-Attribut, mit dem Unterschied, dass es keine Token für Anforderungen erfordert, die mit den folgenden HTTP-Methoden vorgenommen werden:

  • GET
  • HEAD
  • OPTIONEN
  • TRACE

Es empfiehlt sich, für Szenarien ohne API AutoValidateAntiforgeryToken in großem Umfang zu verwenden. Dieses Attribut stellt sicher, dass POST-Aktionen standardmäßig geschützt sind. Alternativ können Sie Token zum Schutz vor Fälschung standardmäßig ignorieren, es sei denn, ValidateAntiForgeryToken wird auf einzelne Aktionsmethoden angewendet. In diesem Szenario ist es wahrscheinlicher, dass eine POST-Aktionsmethode versehentlich nicht geschützt wird, sodass die App für CSRF-Angriffe anfällig bleibt. Alle POSTs sollten das Token zum Schutz vor Fälschung senden.

APIs verfügen nicht über einen automatischen Mechanismus zum Senden des Nicht-cookie-Teils des Tokens. Die Implementierung hängt wahrscheinlich von der Clientcodeimplementierung ab. Nachfolgend werden einige Beispiele veranschaulicht:

Beispiel auf Klassenebene:

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

Globales Beispiel:

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

Außerkraftsetzung von globalen oder Controller-Attributen zum Schutz vor Fälschung

Der Filter IgnoreAntiforgeryToken wird verwendet, um die Notwendigkeit eines Tokens zum Schutz vor Fälschung für eine bestimmte Aktion (oder einen Controller) zu beseitigen. Bei Anwendung setzt dieser Filter die Filter ValidateAntiForgeryToken und AutoValidateAntiforgeryToken außer Kraft, die auf einer höheren Ebene (global oder auf einem Controller) angegeben sind.

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

Aktualisieren von Token nach der Authentifizierung

Token sollten nach der Authentifizierung des Benutzers aktualisiert werden, indem der Benutzer zu einer Ansicht oder Razor Pages-Seite umgeleitet wird.

JavaScript, AJAX und SPAs

In herkömmlichen HTML-basierten Apps werden Token zum Schutz vor Fälschung mithilfe ausgeblendeter Formularfelder an den Server übergeben. In modernen JavaScript-basierten Apps und SPAs erfolgen viele Anforderungen programmgesteuert. Diese AJAX-Anforderungen können andere Techniken (z. B. Anforderungsheader oder cookies) zum Senden des Tokens verwenden.

Wenn cookies verwendet wird, um Authentifizierungstoken zu speichern und API-Anforderungen auf dem Server zu authentifizieren, ist CSRF ein potenzielles Problem. Wenn der lokale Speicher zum Speichern des Tokens verwendet wird, kann das CSRF-Sicherheitsrisiko gemildert werden, da Werte aus dem lokalen Speicher nicht bei jeder Anforderung automatisch an den Server gesendet werden. Die Verwendung des lokalen Speichers zum Speichern des Tokens zum Schutz vor Fälschung auf dem Client und das Senden des Tokens als Anforderungsheader stellt einen empfohlenen Ansatz dar.

JavaScript

Mithilfe von JavaScript in Verbindung mit Ansichten kann das Token mithilfe eines Diensts innerhalb der Ansicht erstellt werden. Schleusen Sie den IAntiforgery-Dienst in die Ansicht ein, und rufen Sie GetAndStoreTokens auf:

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

Durch diesen Ansatz entfällt die Notwendigkeit, sich direkt mit dem Festlegen von cookies durch den Server oder dem Lesen durch den Client zu befassen.

Im vorstehenden Beispiel wird JavaScript verwendet, um den Wert des ausgeblendeten Felds für den AJAX POST-Header zu lesen.

JavaScript kann auch auf Token in cookies zugreifen und den Inhalt des cookies verwenden, um einen Header mit dem Wert des Tokens zu erstellen.

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

Wenn das Skript das Senden des Tokens in einem Header namens X-CSRF-TOKEN anfordert, konfigurieren Sie den Dienst zum Schutz vor Fälschung, um nach dem Header X-CSRF-TOKEN zu suchen:

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

Im folgenden Beispiel wird JavaScript verwendet, um eine AJAX-Anforderung mit dem entsprechenden Header auszuführen:

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

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

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

AngularJS

AngularJS verwendet eine Konvention zur Behandlung von CSRF. Wenn der Server ein cookie mit dem Namen XSRF-TOKEN sendet, fügt der AngularJS$http-Dienst den cookie-Wert einem Header hinzu, wenn er eine Anforderung an den Server sendet. Dieser Prozess ist automatisiert. Der Client braucht den Header nicht explizit festzulegen. Der Name des Headers lautet X-XSRF-TOKEN. Der Server sollte diesen Header erkennen und dessen Inhalt überprüfen.

Damit ASP.NET Core-API beim Anwendungsstart mit dieser Konvention funktioniert:

  • Konfigurieren Sie Ihre App so, dass ein Token in einem cookie namens XSRF-TOKEN bereitgestellt wird.
  • Konfigurieren Sie den Dienst zum Schutz vor Fälschung für die Suche nach einem Header mit dem Namen X-XSRF-TOKEN. Dies ist der Standardheadername von Angular zum Senden des XSRF-Tokens.
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");
}

Hinweis

Wenn das Token zum Schutz vor Fälschung sowohl im Anforderungsheader als auch in den Formularnutzdaten bereitgestellt wird, wird nur das Token im Header überprüft.

Windows-Authentifizierung und cookies zum Schutz vor Fälschung

Bei Verwendung der Windows-Authentifizierung müssen Anwendungsendpunkte auf die gleiche Weise wie cookies vor CSRF-Angriffen geschützt werden. Der Browser sendet implizit den Authentifizierungskontext an den Server, daher müssen Endpunkte vor CSRF-Angriffen geschützt werden.

Erweitern des Schutzes vor Fälschung

Der IAntiforgeryAdditionalDataProvider-Typ ermöglicht es Entwicklern, das Verhalten des Anti-CSRF-Systems mithilfe von Round-Trips zusätzlicher Daten in jedem Token zu erweitern. Die GetAdditionalData-Methode wird jedes Mal aufgerufen, wenn ein Feldtoken generiert wird, und der Rückgabewert wird in das generierte Token eingebettet. Ein Implementierer kann einen Zeitstempel, eine Nonce oder einen anderen Wert zurückgeben und dann ValidateAdditionalData aufrufen, um diese Daten zu überprüfen, wenn das Token überprüft wird. Der Benutzername des Clients ist bereits in die generierten Token eingebettet, sodass diese Informationen nicht eingeschlossen werden müssen. Wenn ein Token zusätzliche Daten enthält, aber kein IAntiForgeryAdditionalDataProvider konfiguriert ist, werden die zusätzlichen Daten nicht überprüft.

Zusätzliche Ressourcen