Mencegah serangan Pemalsuan Permintaan Lintas Situs (XSRF/CSRF) di ASP.NET Core

Oleh Fiyaz Hasan dan Rick Anderson

Pemalsuan permintaan lintas situs adalah serangan terhadap aplikasi yang dihosting web di mana aplikasi web berbahaya dapat memengaruhi interaksi antara browser klien dan aplikasi web yang mempercayai browser tersebut. Serangan ini dimungkinkan karena browser web mengirim beberapa jenis token autentikasi secara otomatis dengan setiap permintaan ke situs web. Bentuk eksploitasi ini juga dikenal sebagai serangan satu klik atau naik sesi karena serangan memanfaatkan sesi yang diautentikasi pengguna sebelumnya. Pemalsuan permintaan lintas situs juga dikenal sebagai XSRF atau CSRF.

Contoh serangan CSRF:

  1. Pengguna masuk www.good-banking-site.example.com menggunakan autentikasi formulir. Server mengautentikasi pengguna dan mengeluarkan respons yang menyertakan autentikasi cookie. Situs ini rentan terhadap serangan karena mempercayai permintaan apa pun yang diterimanya dengan autentikasi cookieyang valid.

  2. Pengguna mengunjungi situs berbahaya, www.bad-crook-site.example.com.

    Situs berbahaya, www.bad-crook-site.example.com, berisi formulir HTML yang mirip dengan contoh berikut:

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

    Perhatikan bahwa posting formulir action ke situs yang rentan, bukan ke situs berbahaya. Ini adalah bagian "lintas situs" dari CSRF.

  3. Pengguna memilih tombol kirim. Browser membuat permintaan dan secara otomatis menyertakan autentikasi cookie untuk domain yang diminta, www.good-banking-site.example.com.

  4. Permintaan berjalan di www.good-banking-site.example.com server dengan konteks autentikasi pengguna dan dapat melakukan tindakan apa pun yang diizinkan untuk dilakukan oleh pengguna terautentikasi.

Selain skenario di mana pengguna memilih tombol untuk mengirimkan formulir, situs berbahaya dapat:

  • Jalankan skrip yang secara otomatis mengirimkan formulir.
  • Kirim pengiriman formulir sebagai permintaan AJAX.
  • Sembunyikan formulir menggunakan CSS.

Skenario alternatif ini tidak memerlukan tindakan atau input apa pun dari pengguna selain awalnya mengunjungi situs berbahaya.

Menggunakan HTTPS tidak mencegah serangan CSRF. Situs berbahaya dapat mengirim https://www.good-banking-site.com/ permintaan semudah dapat mengirim permintaan yang tidak aman.

Beberapa serangan menargetkan titik akhir yang merespons permintaan GET, dalam hal ini tag gambar dapat digunakan untuk melakukan tindakan. Bentuk serangan ini umum terjadi di situs forum yang mengizinkan gambar tetapi memblokir JavaScript. Aplikasi yang mengubah status pada permintaan GET, di mana variabel atau sumber daya diubah, rentan terhadap serangan berbahaya. Permintaan GET yang mengubah status tidak aman. Praktik terbaik adalah tidak pernah mengubah status pada permintaan GET.

Serangan CSRF dimungkinkan terhadap aplikasi web yang menggunakan cookies untuk autentikasi karena:

  • Browser menyimpan cookieyang dikeluarkan oleh aplikasi web.
  • cookieMenyimpan termasuk sesi cookieuntuk pengguna yang diautentikasi.
  • Browser mengirim semua cookieyang terkait dengan domain ke aplikasi web setiap permintaan terlepas dari bagaimana permintaan ke aplikasi dihasilkan dalam browser.

Namun, serangan CSRF tidak terbatas pada eksploitasi cookie. Misalnya, autentikasi Dasar dan Hash juga rentan. Setelah pengguna masuk dengan autentikasi Dasar atau Hash, browser secara otomatis mengirim kredensial hingga sesi berakhir.

Dalam konteks ini, sesi mengacu pada sesi sisi klien tempat pengguna diautentikasi. Ini tidak terkait dengan sesi sisi server atau ASP.NET Middleware Sesi Inti.

Pengguna dapat melindungi dari kerentanan CSRF dengan mengambil tindakan pencegahan:

  • Keluar dari aplikasi web setelah selesai menggunakannya.
  • Hapus browser cookiesecara berkala.

Namun, kerentanan CSRF pada dasarnya merupakan masalah dengan aplikasi web, bukan pengguna akhir.

Dasar-dasar autentikasi

CookieAutentikasi berbasis -adalah bentuk autentikasi yang populer. Sistem autentikasi berbasis token semakin populer, terutama untuk Aplikasi Halaman Tunggal (SPAs).

Saat pengguna mengautentikasi menggunakan nama pengguna dan kata sandi mereka, mereka mengeluarkan token yang berisi tiket autentikasi. Token dapat digunakan untuk autentikasi dan otorisasi. Token disimpan sebagai cookie yang dikirim dengan setiap permintaan yang dilakukan klien. Menghasilkan dan memvalidasi ini cookie dilakukan dengan Cookie Middleware Autentikasi. Middleware menserialisasikan prinsipal pengguna ke dalam terenkripsi cookie. Pada permintaan berikutnya, middleware memvalidasi cookie, membuat ulang prinsipal, dan menetapkan utama ke HttpContext.User properti .

Autentikasi berbasis token

Saat pengguna diautentikasi, mereka mengeluarkan token (bukan token antiforgery). Token berisi informasi pengguna dalam bentuk klaim atau token referensi yang menunjuk aplikasi ke status pengguna yang dipertahankan di aplikasi. Saat pengguna mencoba mengakses sumber daya yang memerlukan autentikasi, token dikirim ke aplikasi dengan header otorisasi tambahan dalam bentuk token Pembawa. Pendekatan ini membuat aplikasi tanpa status. Dalam setiap permintaan berikutnya, token diteruskan dalam permintaan validasi sisi server. Token ini tidak dienkripsi; dikodekan. Di server, token didekodekan untuk mengakses informasinya. Untuk mengirim token pada permintaan berikutnya, simpan token di penyimpanan lokal browser. Menempatkan token di penyimpanan lokal browser dan mengambilnya dan menggunakannya sebagai token pembawa memberikan perlindungan terhadap serangan CSRF. Namun, jika aplikasi rentan terhadap injeksi skrip melalui XSS atau file JavaScript eksternal yang disusupi, penyerang dapat mengambil nilai apa pun dari penyimpanan lokal dan mengirimkannya ke diri mereka sendiri. ASP.NET Core mengodekan semua output sisi server dari variabel secara default, mengurangi risiko XSS. Jika Anda mengambil alih perilaku ini dengan menggunakan Html.Raw atau kode kustom dengan input yang tidak tepercaya, Maka Anda dapat meningkatkan risiko XSS.

Jangan khawatir tentang kerentanan CSRF jika token disimpan di penyimpanan lokal browser. CSRF menjadi perhatian ketika token disimpan dalam cookie. Untuk informasi selengkapnya, lihat sampel kode SPA masalah GitHub menambahkan dua cookies.

Beberapa aplikasi yang dihosting di satu domain

Lingkungan hosting bersama rentan terhadap pembajakan sesi, CSRF masuk, dan serangan lainnya.

Meskipun example1.contoso.net dan example2.contoso.net merupakan host yang berbeda, ada hubungan kepercayaan implisit antara host di *.contoso.net bawah domain. Hubungan kepercayaan implisit ini memungkinkan host yang berpotensi tidak tepercaya untuk memengaruhi satu sama lain cookie(kebijakan asal yang sama yang mengatur permintaan AJAX tidak selalu berlaku untuk HTTP cookie.

Serangan yang mengeksploitasi tepercaya cookieantara aplikasi yang dihosting di domain yang sama dapat dicegah dengan tidak berbagi domain. Saat setiap aplikasi dihosting di domainnya sendiri, tidak ada hubungan kepercayaan implisit cookie untuk dieksploitasi.

Antiforgery dalam ASP.NET Core

Peringatan

ASP.NET Core mengimplementasikan antiforgery menggunakan ASP.NET Core Data Protection. Tumpukan perlindungan data harus dikonfigurasi untuk bekerja di farm server. Untuk informasi selengkapnya, lihat Mengonfigurasi perlindungan data.

Middleware antiforgery ditambahkan ke kontainer injeksi Dependensi ketika salah satu API berikut dipanggil dalam Program.cs:

Untuk informasi selengkapnya, lihat Antiforgery dengan API Minimal.

FormTagHelper menyuntikkan token anti-pemalsuan ke dalam elemen formulir HTML. Markup berikut dalam Razor file secara otomatis menghasilkan token antiforgery:

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

Demikian pula, IHtmlHelper.BeginForm menghasilkan token antiforgery secara default jika metode formulir bukan GET.

Pembuatan otomatis token antiforgery untuk elemen formulir HTML terjadi ketika <form> tag berisi method="post" atribut dan salah satu dari yang berikut ini benar:

  • Atribut tindakan kosong (action="").
  • Atribut tindakan tidak disediakan (<form method="post">).

Pembuatan token antiforgeri otomatis untuk elemen formulir HTML dapat dinonaktifkan:

  • Nonaktifkan token antiforgery secara eksplisit dengan asp-antiforgery atribut :

    <form method="post" asp-antiforgery="false">
        <!-- ... -->
    </form>
    
  • Elemen formulir ditolak dari Pembantu Tag dengan menggunakan simbol penolakan Pembantu Tag ! :

    <!form method="post">
        <!-- ... -->
    </!form>
    
  • FormTagHelper Hapus dari tampilan. FormTagHelper dapat dihapus dari tampilan dengan menambahkan direktif berikut ke Razor tampilan:

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

Catatan

Razor Halaman secara otomatis dilindungi dari XSRF/CSRF. Untuk informasi selengkapnya, lihat XSRF/CSRF dan Razor Pages.

Pendekatan paling umum untuk bertahan dari serangan CSRF adalah menggunakan Pola Token Penyinkron (STP). STP digunakan saat pengguna meminta halaman dengan data formulir:

  1. Server mengirim token yang terkait dengan identitas pengguna saat ini ke klien.
  2. Klien mengirim kembali token ke server untuk verifikasi.
  3. Jika server menerima token yang tidak cocok dengan identitas pengguna yang diautentikasi, permintaan akan ditolak.

Token unik dan tidak dapat diprediksi. Token juga dapat digunakan untuk memastikan urutan yang tepat dari serangkaian permintaan (misalnya, memastikan urutan permintaan: halaman 1 > halaman 2 > halaman 3). Semua formulir dalam templat ASP.NET Core MVC dan Razor Pages menghasilkan token antiforgery. Sepasang contoh tampilan berikut menghasilkan token antiforgery:

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

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

Secara eksplisit menambahkan token antiforgery ke <form> elemen tanpa menggunakan Pembantu Tag dengan pembantu @Html.AntiForgeryTokenHTML :

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

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

Dalam setiap kasus sebelumnya, ASP.NET Core menambahkan bidang formulir tersembunyi yang mirip dengan contoh berikut:

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

ASP.NET Core mencakup tiga filter untuk bekerja dengan token antiforgery:

Antiforgery dengan AddControllers

AddControllers Panggilan tidak mengaktifkan token antiforgery. AddControllersWithViews harus dipanggil untuk memiliki dukungan token antiforgery bawaan.

Beberapa tab browser dan Pola Token Penyinkron

Dengan Pola Token Penyinkron, hanya halaman yang terakhir dimuat yang berisi token antiforgery yang valid. Menggunakan beberapa tab bisa bermasalah. Misalnya, jika pengguna membuka beberapa tab:

  • Hanya tab yang terakhir dimuat yang berisi token antiforgery yang valid.
  • Permintaan yang dibuat dari tab yang dimuat sebelumnya gagal dengan kesalahan: Antiforgery token validation failed. The antiforgery cookie token and request token do not match

Pertimbangkan pola perlindungan CSRF alternatif jika ini menimbulkan masalah.

Mengonfigurasi antiforgery dengan AntiforgeryOptions

Sesuaikan AntiforgeryOptions dalam Program.cs:

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

Atur properti antiforgery Cookie menggunakan properti kelas , seperti yang CookieBuilder ditunjukkan dalam tabel berikut.

Opsi Deskripsi
Cookie Menentukan pengaturan yang digunakan untuk membuat antiforgery cookie.
FormFieldName Nama bidang formulir tersembunyi yang digunakan oleh sistem antiforgery untuk merender token antiforgery dalam tampilan.
HeaderName Nama header yang digunakan oleh sistem antiforgery. Jika null, sistem hanya mempertimbangkan data formulir.
SuppressXFrameOptionsHeader Menentukan apakah akan menekan pembuatan X-Frame-Options header. Secara default, header dihasilkan dengan nilai "SAMEORIGIN". Default ke false.

Untuk informasi selengkapnya, lihat CookieAuthenticationOptions .

Hasilkan token antiforgery dengan IAntiforgery

IAntiforgery menyediakan API untuk mengonfigurasi fitur antiforgery. IAntiforgery dapat diminta dalam Program.cs menggunakan WebApplication.Services. Contoh berikut menggunakan middleware dari halaman beranda aplikasi untuk menghasilkan token antiforgery dan mengirimkannya dalam respons sebagai cookie:

app.UseRouting();

app.UseAuthorization();

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

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

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

    return next(context);
});

Contoh sebelumnya menetapkan bernama cookieXSRF-TOKEN. Klien dapat membaca ini cookie dan memberikan nilainya sebagai header yang dilampirkan ke permintaan AJAX. Misalnya, Angular menyertakan perlindungan XSRF bawaan yang membaca nama cookie secara XSRF-TOKEN default.

Memerlukan validasi antiforgery

Filter tindakan ValidateAntiForgeryToken dapat diterapkan ke tindakan individual, pengontrol, atau secara global. Permintaan yang dibuat untuk tindakan yang menerapkan filter ini diblokir kecuali permintaan menyertakan token antiforgery yang valid:

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

    return RedirectToAction();
}

Atribut ValidateAntiForgeryToken memerlukan token untuk permintaan ke metode tindakan yang ditandainya, termasuk permintaan HTTP GET. ValidateAntiForgeryToken Jika atribut diterapkan di seluruh pengontrol aplikasi, atribut dapat ditimpa dengan IgnoreAntiforgeryToken atribut .

Memvalidasi token antiforgery secara otomatis hanya untuk metode HTTP yang tidak aman

Alih-alih menerapkan ValidateAntiForgeryToken atribut secara luas dan kemudian menimpanya dengan IgnoreAntiforgeryToken atribut, atribut AutoValidateAntiforgeryToken dapat digunakan. Atribut ini berfungsi secara identik dengan ValidateAntiForgeryToken atribut , kecuali bahwa atribut ini tidak memerlukan token untuk permintaan yang dibuat menggunakan metode HTTP berikut:

  • GET
  • HEAD
  • OPSI
  • TRACE

Sebaiknya gunakan AutoValidateAntiforgeryToken secara luas untuk skenario non-API. Atribut ini memastikan tindakan POST dilindungi secara default. Alternatifnya adalah mengabaikan token antiforgery secara default, kecuali ValidateAntiForgeryToken diterapkan ke metode tindakan individual. Lebih mungkin dalam skenario ini untuk metode tindakan POST dibiarkan tidak terlindungi secara tidak sengaja, membuat aplikasi rentan terhadap serangan CSRF. Semua POS harus mengirim token antiforgery.

API tidak memiliki mekanisme otomatis untuk mengirim non-bagiancookie token. Implementasi mungkin tergantung pada implementasi kode klien. Beberapa contoh ditunjukkan di bawah ini:

Contoh tingkat kelas:

[AutoValidateAntiforgeryToken]
public class HomeController : Controller

Contoh global:

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

Mengambil alih atribut antiforgery global atau pengontrol

Filter IgnoreAntiforgeryToken digunakan untuk menghilangkan kebutuhan token antiforgery untuk tindakan tertentu (atau pengontrol). Saat diterapkan, filter ini mengambil alih ValidateAntiForgeryToken dan AutoValidateAntiforgeryToken filter yang ditentukan pada tingkat yang lebih tinggi (secara global atau pada pengontrol).

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

    return RedirectToAction();
}

Refresh token setelah autentikasi

Token harus di-refresh setelah pengguna diautentikasi dengan mengalihkan pengguna ke halaman tampilan atau Razor Halaman.

JavaScript, AJAX, dan SPAs

Dalam aplikasi tradisional berbasis HTML, token antiforgery diteruskan ke server menggunakan bidang formulir tersembunyi. Di aplikasi dan SPAs berbasis JavaScript modern, banyak permintaan dibuat secara terprogram. Permintaan AJAX ini dapat menggunakan teknik lain, seperti header permintaan atau cookies, untuk mengirim token.

Jika cookies digunakan untuk menyimpan token autentikasi dan untuk mengautentikasi permintaan API di server, CSRF adalah masalah potensial. Jika penyimpanan lokal digunakan untuk menyimpan token, kerentanan CSRF mungkin dimitigasi karena nilai dari penyimpanan lokal tidak dikirim secara otomatis ke server dengan setiap permintaan. Menggunakan penyimpanan lokal untuk menyimpan token antiforgery pada klien dan mengirim token sebagai header permintaan adalah pendekatan yang direkomendasikan.

Blazor

Untuk informasi selengkapnya, lihat autentikasi dan otorisasi ASP.NET CoreBlazor.

JavaScript

Menggunakan JavaScript dengan tampilan, token dapat dibuat menggunakan layanan dari dalam tampilan. IAntiforgery Masukkan layanan ke dalam tampilan dan panggil GetAndStoreTokens:

@inject Microsoft.AspNetCore.Antiforgery.IAntiforgery Antiforgery

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

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

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

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

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

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

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

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

Contoh sebelumnya menggunakan JavaScript untuk membaca nilai bidang tersembunyi untuk header AJAX POST.

Pendekatan ini menghilangkan kebutuhan untuk berurusan langsung dengan pengaturan cookiedari server atau membacanya dari klien. Namun, saat menyuntikkan layanan tidak dimungkinkan IAntiforgery , gunakan JavaScript untuk mengakses token dalam cookie:

  • Akses token dalam permintaan tambahan ke server, biasanya .same-origin
  • cookieGunakan konten 's untuk membuat header dengan nilai token.

Dengan asumsi skrip mengirim token di header permintaan yang disebut X-XSRF-TOKEN, konfigurasikan layanan antiforgery untuk X-XSRF-TOKEN mencari header:

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

Contoh berikut menambahkan titik akhir terproteksi yang menulis token permintaan ke JavaScript yang dapat cookiedibaca :

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

Contoh berikut menggunakan JavaScript untuk membuat permintaan AJAX untuk mendapatkan token dan membuat permintaan lain dengan header yang sesuai:

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

Catatan

Ketika token antiforgery disediakan di header permintaan dan dalam payload formulir, hanya token di header yang divalidasi.

Antiforgery dengan API Minimal

Hubungi AddAntiforgery dan UseAntiforgery(IApplicationBuilder) untuk mendaftarkan layanan antiforgery di DI. Token antiforgery digunakan untuk mengurangi serangan pemalsuan permintaan lintas situs.

var builder = WebApplication.CreateBuilder();

builder.Services.AddAntiforgery();

var app = builder.Build();

app.UseAntiforgery();

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

app.Run();

Middleware antiforgery:

Token antiforgery hanya divalidasi jika:

  • Titik akhir berisi metadata yang mengimplementasikan IAntiforgeryMetadata di mana RequiresValidation=true.
  • Metode HTTP yang terkait dengan titik akhir adalah metode HTTP yang relevan. Metode yang relevan adalah semua metode HTTP kecuali untuk TRACE, OPTIONS, HEAD, dan GET.
  • Permintaan dikaitkan dengan titik akhir yang valid.

Catatan: Saat diaktifkan secara manual, middleware antiforgery harus berjalan setelah middleware autentikasi dan otorisasi untuk mencegah membaca data formulir saat pengguna tidak diautentikasi.

Secara default, API minimal yang menerima data formulir memerlukan validasi token antiforgery.

Pertimbangkan metode berikut GenerateForm :

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

Kode sebelumnya memiliki tiga argumen, tindakan, token anti-pemalsuan, dan yang bool menunjukkan apakah token harus digunakan.

Pertimbangkan sampel berikut:

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

Dalam kode sebelumnya, posting ke:

  • /todo memerlukan token antiforgery yang valid.
  • /todo2tidak memerlukan token antiforgery yang valid karena DisableAntiforgery dipanggil.
app.MapPost("/todo", ([FromForm] Todo todo) => Results.Ok(todo));

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

POST untuk:

  • /todo dari formulir yang dihasilkan oleh / titik akhir berhasil karena token antiforgery valid.
  • /todo dari formulir yang dihasilkan oleh /SkipToken kegagalan karena antiforgery tidak disertakan.
  • /todo2 dari formulir yang dihasilkan oleh /DisableAntiforgery titik akhir berhasil karena antiforgery tidak diperlukan.
app.MapPost("/todo", ([FromForm] Todo todo) => Results.Ok(todo));

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

Ketika formulir dikirimkan tanpa token antiforgery yang valid:

  • Di lingkungan pengembangan, pengecualian dilemparkan.
  • Di lingkungan produksi, pesan dicatat.

Autentikasi Windows dan antiforgery cookies

Saat menggunakan Autentikasi Windows, titik akhir aplikasi harus dilindungi dari serangan CSRF dengan cara yang sama seperti yang dilakukan untuk cookies. Browser secara implisit mengirim konteks autentikasi ke server dan titik akhir perlu dilindungi dari serangan CSRF.

Perluas antiforgery

Jenis ini IAntiforgeryAdditionalDataProvider memungkinkan pengembang untuk memperluas perilaku sistem anti-CSRF dengan melakukan round-tripping data tambahan di setiap token. Metode GetAdditionalData ini dipanggil setiap kali token bidang dihasilkan, dan nilai pengembalian disematkan dalam token yang dihasilkan. Pelaksana dapat mengembalikan tanda waktu, nonce, atau nilai lain lalu memanggil ValidateAdditionalData untuk memvalidasi data ini saat token divalidasi. Nama pengguna klien sudah disematkan dalam token yang dihasilkan, sehingga tidak perlu menyertakan informasi ini. Jika token menyertakan data tambahan tetapi tidak IAntiForgeryAdditionalDataProvider dikonfigurasi, data tambahan tidak divalidasi.

Sumber Daya Tambahan:

Pemalsuan permintaan lintas situs (juga dikenal sebagai XSRF atau CSRF) adalah serangan terhadap aplikasi yang dihosting web di mana aplikasi web berbahaya dapat memengaruhi interaksi antara browser klien dan aplikasi web yang mempercayai browser tersebut. Serangan ini dimungkinkan karena browser web mengirim beberapa jenis token autentikasi secara otomatis dengan setiap permintaan ke situs web. Bentuk eksploitasi ini juga dikenal sebagai serangan satu klik atau naik sesi karena serangan memanfaatkan sesi yang diautentikasi pengguna sebelumnya.

Contoh serangan CSRF:

  1. Pengguna masuk www.good-banking-site.example.com menggunakan autentikasi formulir. Server mengautentikasi pengguna dan mengeluarkan respons yang menyertakan autentikasi cookie. Situs ini rentan terhadap serangan karena mempercayai permintaan apa pun yang diterimanya dengan autentikasi cookieyang valid.

  2. Pengguna mengunjungi situs berbahaya, www.bad-crook-site.example.com.

    Situs berbahaya, www.bad-crook-site.example.com, berisi formulir HTML yang mirip dengan contoh berikut:

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

    Perhatikan bahwa posting formulir action ke situs yang rentan, bukan ke situs berbahaya. Ini adalah bagian "lintas situs" dari CSRF.

  3. Pengguna memilih tombol kirim. Browser membuat permintaan dan secara otomatis menyertakan autentikasi cookie untuk domain yang diminta, www.good-banking-site.example.com.

  4. Permintaan berjalan di www.good-banking-site.example.com server dengan konteks autentikasi pengguna dan dapat melakukan tindakan apa pun yang diizinkan untuk dilakukan oleh pengguna terautentikasi.

Selain skenario di mana pengguna memilih tombol untuk mengirimkan formulir, situs berbahaya dapat:

  • Jalankan skrip yang secara otomatis mengirimkan formulir.
  • Kirim pengiriman formulir sebagai permintaan AJAX.
  • Sembunyikan formulir menggunakan CSS.

Skenario alternatif ini tidak memerlukan tindakan atau input apa pun dari pengguna selain awalnya mengunjungi situs berbahaya.

Menggunakan HTTPS tidak mencegah serangan CSRF. Situs berbahaya dapat mengirim https://www.good-banking-site.com/ permintaan semudah dapat mengirim permintaan yang tidak aman.

Beberapa serangan menargetkan titik akhir yang merespons permintaan GET, dalam hal ini tag gambar dapat digunakan untuk melakukan tindakan. Bentuk serangan ini umum terjadi di situs forum yang mengizinkan gambar tetapi memblokir JavaScript. Aplikasi yang mengubah status pada permintaan GET, di mana variabel atau sumber daya diubah, rentan terhadap serangan berbahaya. Permintaan GET yang mengubah status tidak aman. Praktik terbaik adalah tidak pernah mengubah status pada permintaan GET.

Serangan CSRF dimungkinkan terhadap aplikasi web yang menggunakan cookies untuk autentikasi karena:

  • Browser menyimpan cookieyang dikeluarkan oleh aplikasi web.
  • cookieMenyimpan termasuk sesi cookieuntuk pengguna yang diautentikasi.
  • Browser mengirim semua cookieyang terkait dengan domain ke aplikasi web setiap permintaan terlepas dari bagaimana permintaan ke aplikasi dihasilkan dalam browser.

Namun, serangan CSRF tidak terbatas pada eksploitasi cookie. Misalnya, autentikasi Dasar dan Hash juga rentan. Setelah pengguna masuk dengan autentikasi Dasar atau Hash, browser secara otomatis mengirim kredensial hingga sesi berakhir.

Dalam konteks ini, sesi mengacu pada sesi sisi klien tempat pengguna diautentikasi. Ini tidak terkait dengan sesi sisi server atau ASP.NET Middleware Sesi Inti.

Pengguna dapat melindungi dari kerentanan CSRF dengan mengambil tindakan pencegahan:

  • Keluar dari aplikasi web setelah selesai menggunakannya.
  • Hapus browser cookiesecara berkala.

Namun, kerentanan CSRF pada dasarnya merupakan masalah dengan aplikasi web, bukan pengguna akhir.

Dasar-dasar autentikasi

CookieAutentikasi berbasis -adalah bentuk autentikasi yang populer. Sistem autentikasi berbasis token semakin populer, terutama untuk Aplikasi Halaman Tunggal (SPAs).

Saat pengguna mengautentikasi menggunakan nama pengguna dan kata sandi mereka, mereka mengeluarkan token, yang berisi tiket autentikasi yang dapat digunakan untuk autentikasi dan otorisasi. Token disimpan sebagai cookie yang dikirim dengan setiap permintaan yang dilakukan klien. Menghasilkan dan memvalidasi ini cookie dilakukan oleh Cookie Middleware Autentikasi. Middleware menserialisasikan prinsipal pengguna ke dalam terenkripsi cookie. Pada permintaan berikutnya, middleware memvalidasi cookie, membuat ulang prinsipal, dan menetapkan utama ke HttpContext.User properti .

Autentikasi berbasis token

Saat pengguna diautentikasi, mereka mengeluarkan token (bukan token antiforgery). Token berisi informasi pengguna dalam bentuk klaim atau token referensi yang menunjuk aplikasi ke status pengguna yang dipertahankan di aplikasi. Saat pengguna mencoba mengakses sumber daya yang memerlukan autentikasi, token dikirim ke aplikasi dengan header otorisasi tambahan dalam bentuk token Pembawa. Pendekatan ini membuat aplikasi tanpa status. Dalam setiap permintaan berikutnya, token diteruskan dalam permintaan validasi sisi server. Token ini tidak dienkripsi; dikodekan. Di server, token didekodekan untuk mengakses informasinya. Untuk mengirim token pada permintaan berikutnya, simpan token di penyimpanan lokal browser. Menempatkan token di penyimpanan lokal browser dan mengambilnya dan menggunakannya sebagai token pembawa memberikan perlindungan terhadap serangan CSRF. Namun, jika aplikasi rentan terhadap injeksi skrip melalui XSS atau file javascript eksternal yang disusupi, penyerang dapat mengambil nilai apa pun dari penyimpanan lokal dan mengirimkannya ke diri mereka sendiri. ASP.NET Core mengodekan semua output sisi server dari variabel secara default, mengurangi risiko XSS. Jika Anda mengambil alih perilaku ini dengan menggunakan Html.Raw atau kode kustom dengan input yang tidak tepercaya, Maka Anda dapat meningkatkan risiko XSS.

Jangan khawatir tentang kerentanan CSRF jika token disimpan di penyimpanan lokal browser. CSRF menjadi perhatian ketika token disimpan dalam cookie. Untuk informasi selengkapnya, lihat sampel kode SPA masalah GitHub menambahkan dua cookies.

Beberapa aplikasi yang dihosting di satu domain

Lingkungan hosting bersama rentan terhadap pembajakan sesi, CSRF masuk, dan serangan lainnya.

Meskipun example1.contoso.net dan example2.contoso.net merupakan host yang berbeda, ada hubungan kepercayaan implisit antara host di *.contoso.net bawah domain. Hubungan kepercayaan implisit ini memungkinkan host yang berpotensi tidak tepercaya untuk memengaruhi satu sama lain cookie(kebijakan asal yang sama yang mengatur permintaan AJAX tidak selalu berlaku untuk HTTP cookie.

Serangan yang mengeksploitasi tepercaya cookieantara aplikasi yang dihosting di domain yang sama dapat dicegah dengan tidak berbagi domain. Saat setiap aplikasi dihosting di domainnya sendiri, tidak ada hubungan kepercayaan implisit cookie untuk dieksploitasi.

Antiforgery dalam ASP.NET Core

Peringatan

ASP.NET Core mengimplementasikan antiforgery menggunakan ASP.NET Core Data Protection. Tumpukan perlindungan data harus dikonfigurasi untuk bekerja di farm server. Untuk informasi selengkapnya, lihat Mengonfigurasi perlindungan data.

Middleware antiforgery ditambahkan ke kontainer injeksi Dependensi ketika salah satu API berikut dipanggil dalam Program.cs:

FormTagHelper menyuntikkan token anti-pemalsuan ke dalam elemen formulir HTML. Markup berikut dalam Razor file secara otomatis menghasilkan token antiforgery:

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

Demikian pula, IHtmlHelper.BeginForm menghasilkan token antiforgery secara default jika metode formulir bukan GET.

Pembuatan otomatis token antiforgery untuk elemen formulir HTML terjadi ketika <form> tag berisi method="post" atribut dan salah satu dari yang berikut ini benar:

  • Atribut tindakan kosong (action="").
  • Atribut tindakan tidak disediakan (<form method="post">).

Pembuatan token antiforgeri otomatis untuk elemen formulir HTML dapat dinonaktifkan:

  • Nonaktifkan token antiforgery secara eksplisit dengan asp-antiforgery atribut :

    <form method="post" asp-antiforgery="false">
        <!-- ... -->
    </form>
    
  • Elemen formulir ditolak dari Pembantu Tag dengan menggunakan simbol penolakan Pembantu Tag ! :

    <!form method="post">
        <!-- ... -->
    </!form>
    
  • FormTagHelper Hapus dari tampilan. FormTagHelper dapat dihapus dari tampilan dengan menambahkan direktif berikut ke Razor tampilan:

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

Catatan

Razor Halaman secara otomatis dilindungi dari XSRF/CSRF. Untuk informasi selengkapnya, lihat XSRF/CSRF dan Razor Pages.

Pendekatan paling umum untuk bertahan dari serangan CSRF adalah menggunakan Pola Token Penyinkron (STP). STP digunakan saat pengguna meminta halaman dengan data formulir:

  1. Server mengirim token yang terkait dengan identitas pengguna saat ini ke klien.
  2. Klien mengirim kembali token ke server untuk verifikasi.
  3. Jika server menerima token yang tidak cocok dengan identitas pengguna yang diautentikasi, permintaan akan ditolak.

Token unik dan tidak dapat diprediksi. Token juga dapat digunakan untuk memastikan urutan yang tepat dari serangkaian permintaan (misalnya, memastikan urutan permintaan: halaman 1 > halaman 2 > halaman 3). Semua formulir dalam templat ASP.NET Core MVC dan Razor Pages menghasilkan token antiforgery. Sepasang contoh tampilan berikut menghasilkan token antiforgery:

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

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

Secara eksplisit menambahkan token antiforgery ke <form> elemen tanpa menggunakan Pembantu Tag dengan pembantu @Html.AntiForgeryTokenHTML :

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

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

Dalam setiap kasus sebelumnya, ASP.NET Core menambahkan bidang formulir tersembunyi yang mirip dengan contoh berikut:

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

ASP.NET Core mencakup tiga filter untuk bekerja dengan token antiforgery:

Antiforgery dengan AddControllers

AddControllers Panggilan tidak mengaktifkan token antiforgery. AddControllersWithViews harus dipanggil untuk memiliki dukungan token antiforgery bawaan.

Beberapa tab browser dan Pola Token Penyinkron

Dengan Pola Token Penyinkron, hanya halaman yang terakhir dimuat yang berisi token antiforgery yang valid. Menggunakan beberapa tab bisa bermasalah. Misalnya, jika pengguna membuka beberapa tab:

  • Hanya tab yang terakhir dimuat yang berisi token antiforgery yang valid.
  • Permintaan yang dibuat dari tab yang dimuat sebelumnya gagal dengan kesalahan: Antiforgery token validation failed. The antiforgery cookie token and request token do not match

Pertimbangkan pola perlindungan CSRF alternatif jika ini menimbulkan masalah.

Mengonfigurasi antiforgery dengan AntiforgeryOptions

Sesuaikan AntiforgeryOptions dalam Program.cs:

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

Atur properti antiforgery Cookie menggunakan properti kelas , seperti yang CookieBuilder ditunjukkan dalam tabel berikut.

Opsi Deskripsi
Cookie Menentukan pengaturan yang digunakan untuk membuat antiforgery cookie.
FormFieldName Nama bidang formulir tersembunyi yang digunakan oleh sistem antiforgery untuk merender token antiforgery dalam tampilan.
HeaderName Nama header yang digunakan oleh sistem antiforgery. Jika null, sistem hanya mempertimbangkan data formulir.
SuppressXFrameOptionsHeader Menentukan apakah akan menekan pembuatan X-Frame-Options header. Secara default, header dihasilkan dengan nilai "SAMEORIGIN". Default ke false.

Untuk informasi selengkapnya, lihat CookieAuthenticationOptions .

Hasilkan token antiforgery dengan IAntiforgery

IAntiforgery menyediakan API untuk mengonfigurasi fitur antiforgery. IAntiforgery dapat diminta dalam Program.cs menggunakan WebApplication.Services. Contoh berikut menggunakan middleware dari halaman beranda aplikasi untuk menghasilkan token antiforgery dan mengirimkannya dalam respons sebagai cookie:

app.UseRouting();

app.UseAuthorization();

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

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

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

    return next(context);
});

Contoh sebelumnya menetapkan bernama cookieXSRF-TOKEN. Klien dapat membaca ini cookie dan memberikan nilainya sebagai header yang dilampirkan ke permintaan AJAX. Misalnya, Angular menyertakan perlindungan XSRF bawaan yang membaca nama cookie secara XSRF-TOKEN default.

Memerlukan validasi antiforgery

Filter tindakan ValidateAntiForgeryToken dapat diterapkan ke tindakan individual, pengontrol, atau secara global. Permintaan yang dibuat untuk tindakan yang menerapkan filter ini diblokir kecuali permintaan menyertakan token antiforgery yang valid:

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

    return RedirectToAction();
}

Atribut ValidateAntiForgeryToken memerlukan token untuk permintaan ke metode tindakan yang ditandainya, termasuk permintaan HTTP GET. ValidateAntiForgeryToken Jika atribut diterapkan di seluruh pengontrol aplikasi, atribut dapat ditimpa dengan IgnoreAntiforgeryToken atribut .

Memvalidasi token antiforgery secara otomatis hanya untuk metode HTTP yang tidak aman

Alih-alih menerapkan ValidateAntiForgeryToken atribut secara luas dan kemudian menimpanya dengan IgnoreAntiforgeryToken atribut, atribut AutoValidateAntiforgeryToken dapat digunakan. Atribut ini berfungsi secara identik dengan ValidateAntiForgeryToken atribut , kecuali bahwa atribut ini tidak memerlukan token untuk permintaan yang dibuat menggunakan metode HTTP berikut:

  • GET
  • HEAD
  • OPSI
  • TRACE

Sebaiknya gunakan AutoValidateAntiforgeryToken secara luas untuk skenario non-API. Atribut ini memastikan tindakan POST dilindungi secara default. Alternatifnya adalah mengabaikan token antiforgery secara default, kecuali ValidateAntiForgeryToken diterapkan ke metode tindakan individual. Lebih mungkin dalam skenario ini untuk metode tindakan POST dibiarkan tidak terlindungi secara tidak sengaja, membuat aplikasi rentan terhadap serangan CSRF. Semua POS harus mengirim token antiforgery.

API tidak memiliki mekanisme otomatis untuk mengirim non-bagiancookie token. Implementasi mungkin tergantung pada implementasi kode klien. Beberapa contoh ditunjukkan di bawah ini:

Contoh tingkat kelas:

[AutoValidateAntiforgeryToken]
public class HomeController : Controller

Contoh global:

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

Mengambil alih atribut antiforgery global atau pengontrol

Filter IgnoreAntiforgeryToken digunakan untuk menghilangkan kebutuhan token antiforgery untuk tindakan tertentu (atau pengontrol). Saat diterapkan, filter ini mengambil alih ValidateAntiForgeryToken dan AutoValidateAntiforgeryToken filter yang ditentukan pada tingkat yang lebih tinggi (secara global atau pada pengontrol).

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

    return RedirectToAction();
}

Refresh token setelah autentikasi

Token harus di-refresh setelah pengguna diautentikasi dengan mengalihkan pengguna ke halaman tampilan atau Razor Halaman.

JavaScript, AJAX, dan SPAs

Dalam aplikasi tradisional berbasis HTML, token antiforgery diteruskan ke server menggunakan bidang formulir tersembunyi. Di aplikasi dan SPAs berbasis JavaScript modern, banyak permintaan dibuat secara terprogram. Permintaan AJAX ini dapat menggunakan teknik lain (seperti header permintaan atau cookies) untuk mengirim token.

Jika cookies digunakan untuk menyimpan token autentikasi dan untuk mengautentikasi permintaan API di server, CSRF adalah masalah potensial. Jika penyimpanan lokal digunakan untuk menyimpan token, kerentanan CSRF mungkin dimitigasi karena nilai dari penyimpanan lokal tidak dikirim secara otomatis ke server dengan setiap permintaan. Menggunakan penyimpanan lokal untuk menyimpan token antiforgery pada klien dan mengirim token sebagai header permintaan adalah pendekatan yang direkomendasikan.

JavaScript

Menggunakan JavaScript dengan tampilan, token dapat dibuat menggunakan layanan dari dalam tampilan. IAntiforgery Masukkan layanan ke dalam tampilan dan panggil GetAndStoreTokens:

@inject Microsoft.AspNetCore.Antiforgery.IAntiforgery Antiforgery

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

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

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

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

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

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

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

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

Contoh sebelumnya menggunakan JavaScript untuk membaca nilai bidang tersembunyi untuk header AJAX POST.

Pendekatan ini menghilangkan kebutuhan untuk berurusan langsung dengan pengaturan cookiedari server atau membacanya dari klien. Namun, saat menyuntikkan layanan tidak dimungkinkan IAntiforgery , gunakan JavaScript untuk mengakses token dalam cookie:

  • Akses token dalam permintaan tambahan ke server, biasanya .same-origin
  • cookieGunakan konten 's untuk membuat header dengan nilai token.

Dengan asumsi skrip mengirim token di header permintaan yang disebut X-XSRF-TOKEN, konfigurasikan layanan antiforgery untuk X-XSRF-TOKEN mencari header:

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

Contoh berikut menambahkan titik akhir terproteksi yang menulis token permintaan ke JavaScript yang dapat cookiedibaca :

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

Contoh berikut menggunakan JavaScript untuk membuat permintaan AJAX untuk mendapatkan token dan membuat permintaan lain dengan header yang sesuai:

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

Catatan

Ketika token antiforgery disediakan di header permintaan dan dalam payload formulir, hanya token di header yang divalidasi.

Antiforgery dengan API Minimal

Minimal APIstidak mendukung penggunaan filter yang disertakan (ValidateAntiForgeryToken, , AutoValidateAntiforgeryTokenIgnoreAntiforgeryToken), namun, IAntiforgery menyediakan API yang diperlukan untuk memvalidasi permintaan.

Contoh berikut membuat filter yang memvalidasi token antiforgery:

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

            return await next(context);

        });
    }
}

Filter kemudian dapat diterapkan ke titik akhir:

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

Autentikasi Windows dan antiforgery cookies

Saat menggunakan Autentikasi Windows, titik akhir aplikasi harus dilindungi dari serangan CSRF dengan cara yang sama seperti yang dilakukan untuk cookies. Browser secara implisit mengirim konteks autentikasi ke server dan titik akhir perlu dilindungi dari serangan CSRF.

Perluas antiforgery

Jenis ini IAntiforgeryAdditionalDataProvider memungkinkan pengembang untuk memperluas perilaku sistem anti-CSRF dengan melakukan round-tripping data tambahan di setiap token. Metode GetAdditionalData ini dipanggil setiap kali token bidang dihasilkan, dan nilai pengembalian disematkan dalam token yang dihasilkan. Pelaksana dapat mengembalikan tanda waktu, nonce, atau nilai lain lalu memanggil ValidateAdditionalData untuk memvalidasi data ini saat token divalidasi. Nama pengguna klien sudah disematkan dalam token yang dihasilkan, sehingga tidak perlu menyertakan informasi ini. Jika token menyertakan data tambahan tetapi tidak IAntiForgeryAdditionalDataProvider dikonfigurasi, data tambahan tidak divalidasi.

Sumber Daya Tambahan:

Pemalsuan permintaan lintas situs (juga dikenal sebagai XSRF atau CSRF) adalah serangan terhadap aplikasi yang dihosting web di mana aplikasi web berbahaya dapat memengaruhi interaksi antara browser klien dan aplikasi web yang mempercayai browser tersebut. Serangan ini dimungkinkan karena browser web mengirim beberapa jenis token autentikasi secara otomatis dengan setiap permintaan ke situs web. Bentuk eksploitasi ini juga dikenal sebagai serangan satu klik atau naik sesi karena serangan memanfaatkan sesi yang diautentikasi pengguna sebelumnya.

Contoh serangan CSRF:

  1. Pengguna masuk www.good-banking-site.example.com menggunakan autentikasi formulir. Server mengautentikasi pengguna dan mengeluarkan respons yang menyertakan autentikasi cookie. Situs ini rentan terhadap serangan karena mempercayai permintaan apa pun yang diterimanya dengan autentikasi cookieyang valid.

  2. Pengguna mengunjungi situs berbahaya, www.bad-crook-site.example.com.

    Situs berbahaya, www.bad-crook-site.example.com, berisi formulir HTML yang mirip dengan contoh berikut:

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

    Perhatikan bahwa posting formulir action ke situs yang rentan, bukan ke situs berbahaya. Ini adalah bagian "lintas situs" dari CSRF.

  3. Pengguna memilih tombol kirim. Browser membuat permintaan dan secara otomatis menyertakan autentikasi cookie untuk domain yang diminta, www.good-banking-site.example.com.

  4. Permintaan berjalan di www.good-banking-site.example.com server dengan konteks autentikasi pengguna dan dapat melakukan tindakan apa pun yang diizinkan untuk dilakukan oleh pengguna terautentikasi.

Selain skenario di mana pengguna memilih tombol untuk mengirimkan formulir, situs berbahaya dapat:

  • Jalankan skrip yang secara otomatis mengirimkan formulir.
  • Kirim pengiriman formulir sebagai permintaan AJAX.
  • Sembunyikan formulir menggunakan CSS.

Skenario alternatif ini tidak memerlukan tindakan atau input apa pun dari pengguna selain awalnya mengunjungi situs berbahaya.

Menggunakan HTTPS tidak mencegah serangan CSRF. Situs berbahaya dapat mengirim https://www.good-banking-site.com/ permintaan semudah dapat mengirim permintaan yang tidak aman.

Beberapa serangan menargetkan titik akhir yang merespons permintaan GET, dalam hal ini tag gambar dapat digunakan untuk melakukan tindakan. Bentuk serangan ini umum terjadi di situs forum yang mengizinkan gambar tetapi memblokir JavaScript. Aplikasi yang mengubah status pada permintaan GET, di mana variabel atau sumber daya diubah, rentan terhadap serangan berbahaya. Permintaan GET yang mengubah status tidak aman. Praktik terbaik adalah tidak pernah mengubah status pada permintaan GET.

Serangan CSRF dimungkinkan terhadap aplikasi web yang menggunakan cookies untuk autentikasi karena:

  • Browser menyimpan cookieyang dikeluarkan oleh aplikasi web.
  • cookieMenyimpan termasuk sesi cookieuntuk pengguna yang diautentikasi.
  • Browser mengirim semua cookieyang terkait dengan domain ke aplikasi web setiap permintaan terlepas dari bagaimana permintaan ke aplikasi dihasilkan dalam browser.

Namun, serangan CSRF tidak terbatas pada eksploitasi cookie. Misalnya, autentikasi Dasar dan Hash juga rentan. Setelah pengguna masuk dengan autentikasi Dasar atau Hash, browser secara otomatis mengirim kredensial hingga sesi berakhir.

Dalam konteks ini, sesi mengacu pada sesi sisi klien tempat pengguna diautentikasi. Ini tidak terkait dengan sesi sisi server atau ASP.NET Middleware Sesi Inti.

Pengguna dapat melindungi dari kerentanan CSRF dengan mengambil tindakan pencegahan:

  • Keluar dari aplikasi web setelah selesai menggunakannya.
  • Hapus browser cookiesecara berkala.

Namun, kerentanan CSRF pada dasarnya merupakan masalah dengan aplikasi web, bukan pengguna akhir.

Dasar-dasar autentikasi

CookieAutentikasi berbasis -adalah bentuk autentikasi yang populer. Sistem autentikasi berbasis token semakin populer, terutama untuk Aplikasi Halaman Tunggal (SPAs).

Saat pengguna mengautentikasi menggunakan nama pengguna dan kata sandi mereka, mereka mengeluarkan token, yang berisi tiket autentikasi yang dapat digunakan untuk autentikasi dan otorisasi. Token disimpan sebagai cookie yang dikirim dengan setiap permintaan yang dilakukan klien. Menghasilkan dan memvalidasi ini cookie dilakukan oleh Cookie Middleware Autentikasi. Middleware menserialisasikan prinsipal pengguna ke dalam terenkripsi cookie. Pada permintaan berikutnya, middleware memvalidasi cookie, membuat ulang prinsipal, dan menetapkan utama ke HttpContext.User properti .

Autentikasi berbasis token

Saat pengguna diautentikasi, mereka mengeluarkan token (bukan token antiforgery). Token berisi informasi pengguna dalam bentuk klaim atau token referensi yang menunjuk aplikasi ke status pengguna yang dipertahankan di aplikasi. Saat pengguna mencoba mengakses sumber daya yang memerlukan autentikasi, token dikirim ke aplikasi dengan header otorisasi tambahan dalam bentuk token Pembawa. Pendekatan ini membuat aplikasi tanpa status. Dalam setiap permintaan berikutnya, token diteruskan dalam permintaan validasi sisi server. Token ini tidak dienkripsi; dikodekan. Di server, token didekodekan untuk mengakses informasinya. Untuk mengirim token pada permintaan berikutnya, simpan token di penyimpanan lokal browser. Jangan khawatir tentang kerentanan CSRF jika token disimpan di penyimpanan lokal browser. CSRF menjadi perhatian ketika token disimpan dalam cookie. Untuk informasi selengkapnya, lihat sampel kode SPA masalah GitHub menambahkan dua cookies.

Beberapa aplikasi yang dihosting di satu domain

Lingkungan hosting bersama rentan terhadap pembajakan sesi, CSRF masuk, dan serangan lainnya.

Meskipun example1.contoso.net dan example2.contoso.net merupakan host yang berbeda, ada hubungan kepercayaan implisit antara host di *.contoso.net bawah domain. Hubungan kepercayaan implisit ini memungkinkan host yang berpotensi tidak tepercaya untuk memengaruhi satu sama lain cookie(kebijakan asal yang sama yang mengatur permintaan AJAX tidak selalu berlaku untuk HTTP cookie.

Serangan yang mengeksploitasi tepercaya cookieantara aplikasi yang dihosting di domain yang sama dapat dicegah dengan tidak berbagi domain. Saat setiap aplikasi dihosting di domainnya sendiri, tidak ada hubungan kepercayaan implisit cookie untuk dieksploitasi.

Antiforgery dalam ASP.NET Core

Peringatan

ASP.NET Core mengimplementasikan antiforgery menggunakan ASP.NET Core Data Protection. Tumpukan perlindungan data harus dikonfigurasi untuk bekerja di farm server. Untuk informasi selengkapnya, lihat Mengonfigurasi perlindungan data.

Middleware antiforgery ditambahkan ke kontainer injeksi Dependensi ketika salah satu API berikut dipanggil dalam Program.cs:

FormTagHelper menyuntikkan token anti-pemalsuan ke dalam elemen formulir HTML. Markup berikut dalam Razor file secara otomatis menghasilkan token antiforgery:

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

Demikian pula, IHtmlHelper.BeginForm menghasilkan token antiforgery secara default jika metode formulir bukan GET.

Pembuatan otomatis token antiforgery untuk elemen formulir HTML terjadi ketika <form> tag berisi method="post" atribut dan salah satu dari yang berikut ini benar:

  • Atribut tindakan kosong (action="").
  • Atribut tindakan tidak disediakan (<form method="post">).

Pembuatan token antiforgeri otomatis untuk elemen formulir HTML dapat dinonaktifkan:

  • Nonaktifkan token antiforgery secara eksplisit dengan asp-antiforgery atribut :

    <form method="post" asp-antiforgery="false">
        <!-- ... -->
    </form>
    
  • Elemen formulir ditolak dari Pembantu Tag dengan menggunakan simbol penolakan Pembantu Tag ! :

    <!form method="post">
        <!-- ... -->
    </!form>
    
  • FormTagHelper Hapus dari tampilan. FormTagHelper dapat dihapus dari tampilan dengan menambahkan direktif berikut ke Razor tampilan:

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

Catatan

Razor Halaman secara otomatis dilindungi dari XSRF/CSRF. Untuk informasi selengkapnya, lihat XSRF/CSRF dan Razor Pages.

Pendekatan paling umum untuk bertahan dari serangan CSRF adalah menggunakan Pola Token Penyinkron (STP). STP digunakan saat pengguna meminta halaman dengan data formulir:

  1. Server mengirim token yang terkait dengan identitas pengguna saat ini ke klien.
  2. Klien mengirim kembali token ke server untuk verifikasi.
  3. Jika server menerima token yang tidak cocok dengan identitas pengguna yang diautentikasi, permintaan akan ditolak.

Token unik dan tidak dapat diprediksi. Token juga dapat digunakan untuk memastikan urutan yang tepat dari serangkaian permintaan (misalnya, memastikan urutan permintaan: halaman 1 > halaman 2 > halaman 3). Semua formulir dalam templat ASP.NET Core MVC dan Razor Pages menghasilkan token antiforgery. Sepasang contoh tampilan berikut menghasilkan token antiforgery:

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

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

Secara eksplisit menambahkan token antiforgery ke <form> elemen tanpa menggunakan Pembantu Tag dengan pembantu @Html.AntiForgeryTokenHTML :

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

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

Dalam setiap kasus sebelumnya, ASP.NET Core menambahkan bidang formulir tersembunyi yang mirip dengan contoh berikut:

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

ASP.NET Core mencakup tiga filter untuk bekerja dengan token antiforgery:

Antiforgery dengan AddControllers

AddControllers Panggilan tidak mengaktifkan token antiforgery. AddControllersWithViews harus dipanggil untuk memiliki dukungan token antiforgery bawaan.

Beberapa tab browser dan Pola Token Penyinkron

Dengan Pola Token Penyinkron, hanya halaman yang terakhir dimuat yang berisi token antiforgery yang valid. Menggunakan beberapa tab bisa bermasalah. Misalnya, jika pengguna membuka beberapa tab:

  • Hanya tab yang terakhir dimuat yang berisi token antiforgery yang valid.
  • Permintaan yang dibuat dari tab yang dimuat sebelumnya gagal dengan kesalahan: Antiforgery token validation failed. The antiforgery cookie token and request token do not match

Pertimbangkan pola perlindungan CSRF alternatif jika ini menimbulkan masalah.

Mengonfigurasi antiforgery dengan AntiforgeryOptions

Sesuaikan AntiforgeryOptions dalam Program.cs:

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

Atur properti antiforgery Cookie menggunakan properti kelas , seperti yang CookieBuilder ditunjukkan dalam tabel berikut.

Opsi Deskripsi
Cookie Menentukan pengaturan yang digunakan untuk membuat antiforgery cookie.
FormFieldName Nama bidang formulir tersembunyi yang digunakan oleh sistem antiforgery untuk merender token antiforgery dalam tampilan.
HeaderName Nama header yang digunakan oleh sistem antiforgery. Jika null, sistem hanya mempertimbangkan data formulir.
SuppressXFrameOptionsHeader Menentukan apakah akan menekan pembuatan X-Frame-Options header. Secara default, header dihasilkan dengan nilai "SAMEORIGIN". Default ke false.

Untuk informasi selengkapnya, lihat CookieAuthenticationOptions .

Hasilkan token antiforgery dengan IAntiforgery

IAntiforgery menyediakan API untuk mengonfigurasi fitur antiforgery. IAntiforgery dapat diminta dalam Program.cs menggunakan WebApplication.Services. Contoh berikut menggunakan middleware dari halaman beranda aplikasi untuk menghasilkan token antiforgery dan mengirimkannya dalam respons sebagai cookie:

app.UseRouting();

app.UseAuthorization();

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

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

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

    return next(context);
});

Contoh sebelumnya menetapkan bernama cookieXSRF-TOKEN. Klien dapat membaca ini cookie dan memberikan nilainya sebagai header yang dilampirkan ke permintaan AJAX. Misalnya, Angular menyertakan perlindungan XSRF bawaan yang membaca nama cookie secara XSRF-TOKEN default.

Memerlukan validasi antiforgery

Filter tindakan ValidateAntiForgeryToken dapat diterapkan ke tindakan individual, pengontrol, atau secara global. Permintaan yang dibuat untuk tindakan yang menerapkan filter ini diblokir kecuali permintaan menyertakan token antiforgery yang valid:

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

    return RedirectToAction();
}

Atribut ValidateAntiForgeryToken memerlukan token untuk permintaan ke metode tindakan yang ditandainya, termasuk permintaan HTTP GET. ValidateAntiForgeryToken Jika atribut diterapkan di seluruh pengontrol aplikasi, atribut dapat ditimpa dengan IgnoreAntiforgeryToken atribut .

Memvalidasi token antiforgery secara otomatis hanya untuk metode HTTP yang tidak aman

Alih-alih menerapkan ValidateAntiForgeryToken atribut secara luas dan kemudian menimpanya dengan IgnoreAntiforgeryToken atribut, atribut AutoValidateAntiforgeryToken dapat digunakan. Atribut ini berfungsi secara identik dengan ValidateAntiForgeryToken atribut , kecuali bahwa atribut ini tidak memerlukan token untuk permintaan yang dibuat menggunakan metode HTTP berikut:

  • GET
  • HEAD
  • OPSI
  • TRACE

Sebaiknya gunakan AutoValidateAntiforgeryToken secara luas untuk skenario non-API. Atribut ini memastikan tindakan POST dilindungi secara default. Alternatifnya adalah mengabaikan token antiforgery secara default, kecuali ValidateAntiForgeryToken diterapkan ke metode tindakan individual. Lebih mungkin dalam skenario ini untuk metode tindakan POST dibiarkan tidak terlindungi secara tidak sengaja, membuat aplikasi rentan terhadap serangan CSRF. Semua POS harus mengirim token antiforgery.

API tidak memiliki mekanisme otomatis untuk mengirim non-bagiancookie token. Implementasi mungkin tergantung pada implementasi kode klien. Beberapa contoh ditunjukkan di bawah ini:

Contoh tingkat kelas:

[AutoValidateAntiforgeryToken]
public class HomeController : Controller

Contoh global:

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

Mengambil alih atribut antiforgery global atau pengontrol

Filter IgnoreAntiforgeryToken digunakan untuk menghilangkan kebutuhan token antiforgery untuk tindakan tertentu (atau pengontrol). Saat diterapkan, filter ini mengambil alih ValidateAntiForgeryToken dan AutoValidateAntiforgeryToken filter yang ditentukan pada tingkat yang lebih tinggi (secara global atau pada pengontrol).

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

    return RedirectToAction();
}

Refresh token setelah autentikasi

Token harus di-refresh setelah pengguna diautentikasi dengan mengalihkan pengguna ke halaman tampilan atau Razor Halaman.

JavaScript, AJAX, dan SPAs

Dalam aplikasi tradisional berbasis HTML, token antiforgery diteruskan ke server menggunakan bidang formulir tersembunyi. Di aplikasi dan SPAs berbasis JavaScript modern, banyak permintaan dibuat secara terprogram. Permintaan AJAX ini dapat menggunakan teknik lain (seperti header permintaan atau cookies) untuk mengirim token.

Jika cookies digunakan untuk menyimpan token autentikasi dan untuk mengautentikasi permintaan API di server, CSRF adalah masalah potensial. Jika penyimpanan lokal digunakan untuk menyimpan token, kerentanan CSRF mungkin dimitigasi karena nilai dari penyimpanan lokal tidak dikirim secara otomatis ke server dengan setiap permintaan. Menggunakan penyimpanan lokal untuk menyimpan token antiforgery pada klien dan mengirim token sebagai header permintaan adalah pendekatan yang direkomendasikan.

JavaScript

Menggunakan JavaScript dengan tampilan, token dapat dibuat menggunakan layanan dari dalam tampilan. IAntiforgery Masukkan layanan ke dalam tampilan dan panggil GetAndStoreTokens:

@inject Microsoft.AspNetCore.Antiforgery.IAntiforgery Antiforgery

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

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

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

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

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

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

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

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

Contoh sebelumnya menggunakan JavaScript untuk membaca nilai bidang tersembunyi untuk header AJAX POST.

Pendekatan ini menghilangkan kebutuhan untuk berurusan langsung dengan pengaturan cookiedari server atau membacanya dari klien. Namun, ketika menyuntikkan layanan tidak dimungkinkan IAntiforgery , JavaScript juga dapat mengakses token dalam cookies, yang diperoleh dari permintaan tambahan ke server (biasanya same-origin), dan menggunakan cookiekonten 's untuk membuat header dengan nilai token.

Dengan asumsi skrip mengirim token di header permintaan yang disebut X-XSRF-TOKEN, konfigurasikan layanan antiforgery untuk X-XSRF-TOKEN mencari header:

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

Contoh berikut menambahkan titik akhir terproteksi yang akan menulis token permintaan ke JavaScript yang dapat cookiedibaca :

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

Contoh berikut menggunakan JavaScript untuk membuat permintaan AJAX untuk mendapatkan token dan membuat permintaan lain dengan header yang sesuai:

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

Autentikasi Windows dan antiforgery cookies

Saat menggunakan Autentikasi Windows, titik akhir aplikasi harus dilindungi dari serangan CSRF dengan cara yang sama seperti yang dilakukan untuk cookies. Browser secara implisit mengirim konteks autentikasi ke server sehingga titik akhir perlu dilindungi dari serangan CSRF.

Perluas antiforgery

Jenis ini IAntiforgeryAdditionalDataProvider memungkinkan pengembang untuk memperluas perilaku sistem anti-CSRF dengan melakukan round-tripping data tambahan di setiap token. Metode GetAdditionalData ini dipanggil setiap kali token bidang dihasilkan, dan nilai pengembalian disematkan dalam token yang dihasilkan. Pelaksana dapat mengembalikan tanda waktu, nonce, atau nilai lain lalu memanggil ValidateAdditionalData untuk memvalidasi data ini saat token divalidasi. Nama pengguna klien sudah disematkan dalam token yang dihasilkan, sehingga tidak perlu menyertakan informasi ini. Jika token menyertakan data tambahan tetapi tidak IAntiForgeryAdditionalDataProvider dikonfigurasi, data tambahan tidak divalidasi.

Sumber Daya Tambahan:

Pemalsuan permintaan lintas situs (juga dikenal sebagai XSRF atau CSRF) adalah serangan terhadap aplikasi yang dihosting web di mana aplikasi web berbahaya dapat memengaruhi interaksi antara browser klien dan aplikasi web yang mempercayai browser tersebut. Serangan ini dimungkinkan karena browser web mengirim beberapa jenis token autentikasi secara otomatis dengan setiap permintaan ke situs web. Bentuk eksploitasi ini juga dikenal sebagai serangan satu klik atau naik sesi karena serangan memanfaatkan sesi yang diautentikasi pengguna sebelumnya.

Contoh serangan CSRF:

  1. Pengguna masuk www.good-banking-site.example.com menggunakan autentikasi formulir. Server mengautentikasi pengguna dan mengeluarkan respons yang menyertakan autentikasi cookie. Situs ini rentan terhadap serangan karena mempercayai permintaan apa pun yang diterimanya dengan autentikasi cookieyang valid.

  2. Pengguna mengunjungi situs berbahaya, www.bad-crook-site.example.com.

    Situs berbahaya, www.bad-crook-site.example.com, berisi formulir HTML yang mirip dengan contoh berikut:

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

    Perhatikan bahwa posting formulir action ke situs yang rentan, bukan ke situs berbahaya. Ini adalah bagian "lintas situs" dari CSRF.

  3. Pengguna memilih tombol kirim. Browser membuat permintaan dan secara otomatis menyertakan autentikasi cookie untuk domain yang diminta, www.good-banking-site.example.com.

  4. Permintaan berjalan di www.good-banking-site.example.com server dengan konteks autentikasi pengguna dan dapat melakukan tindakan apa pun yang diizinkan untuk dilakukan oleh pengguna terautentikasi.

Selain skenario di mana pengguna memilih tombol untuk mengirimkan formulir, situs berbahaya dapat:

  • Jalankan skrip yang secara otomatis mengirimkan formulir.
  • Kirim pengiriman formulir sebagai permintaan AJAX.
  • Sembunyikan formulir menggunakan CSS.

Skenario alternatif ini tidak memerlukan tindakan atau input apa pun dari pengguna selain awalnya mengunjungi situs berbahaya.

Menggunakan HTTPS tidak mencegah serangan CSRF. Situs berbahaya dapat mengirim https://www.good-banking-site.com/ permintaan semudah dapat mengirim permintaan yang tidak aman.

Beberapa serangan menargetkan titik akhir yang merespons permintaan GET, dalam hal ini tag gambar dapat digunakan untuk melakukan tindakan. Bentuk serangan ini umum terjadi di situs forum yang mengizinkan gambar tetapi memblokir JavaScript. Aplikasi yang mengubah status pada permintaan GET, di mana variabel atau sumber daya diubah, rentan terhadap serangan berbahaya. Permintaan GET yang mengubah status tidak aman. Praktik terbaik adalah tidak pernah mengubah status pada permintaan GET.

Serangan CSRF dimungkinkan terhadap aplikasi web yang menggunakan cookies untuk autentikasi karena:

  • Browser menyimpan cookieyang dikeluarkan oleh aplikasi web.
  • cookieMenyimpan termasuk sesi cookieuntuk pengguna yang diautentikasi.
  • Browser mengirim semua cookieyang terkait dengan domain ke aplikasi web setiap permintaan terlepas dari bagaimana permintaan ke aplikasi dihasilkan dalam browser.

Namun, serangan CSRF tidak terbatas pada eksploitasi cookie. Misalnya, autentikasi Dasar dan Hash juga rentan. Setelah pengguna masuk dengan autentikasi Dasar atau Hash, browser secara otomatis mengirim kredensial hingga sesi berakhir.

Dalam konteks ini, sesi mengacu pada sesi sisi klien tempat pengguna diautentikasi. Ini tidak terkait dengan sesi sisi server atau ASP.NET Middleware Sesi Inti.

Pengguna dapat melindungi dari kerentanan CSRF dengan mengambil tindakan pencegahan:

  • Keluar dari aplikasi web setelah selesai menggunakannya.
  • Hapus browser cookiesecara berkala.

Namun, kerentanan CSRF pada dasarnya merupakan masalah dengan aplikasi web, bukan pengguna akhir.

Dasar-dasar autentikasi

CookieAutentikasi berbasis -adalah bentuk autentikasi yang populer. Sistem autentikasi berbasis token semakin populer, terutama untuk Aplikasi Halaman Tunggal (SPAs).

Saat pengguna mengautentikasi menggunakan nama pengguna dan kata sandi mereka, mereka mengeluarkan token, yang berisi tiket autentikasi yang dapat digunakan untuk autentikasi dan otorisasi. Token disimpan sebagai cookie yang dikirim dengan setiap permintaan yang dilakukan klien. Menghasilkan dan memvalidasi ini cookie dilakukan oleh Cookie Middleware Autentikasi. Middleware menserialisasikan prinsipal pengguna ke dalam terenkripsi cookie. Pada permintaan berikutnya, middleware memvalidasi cookie, membuat ulang prinsipal, dan menetapkan utama ke HttpContext.User properti .

Autentikasi berbasis token

Saat pengguna diautentikasi, mereka mengeluarkan token (bukan token antiforgery). Token berisi informasi pengguna dalam bentuk klaim atau token referensi yang menunjuk aplikasi ke status pengguna yang dipertahankan di aplikasi. Saat pengguna mencoba mengakses sumber daya yang memerlukan autentikasi, token dikirim ke aplikasi dengan header otorisasi tambahan dalam bentuk token Pembawa. Pendekatan ini membuat aplikasi tanpa status. Dalam setiap permintaan berikutnya, token diteruskan dalam permintaan validasi sisi server. Token ini tidak dienkripsi; dikodekan. Di server, token didekodekan untuk mengakses informasinya. Untuk mengirim token pada permintaan berikutnya, simpan token di penyimpanan lokal browser. Jangan khawatir tentang kerentanan CSRF jika token disimpan di penyimpanan lokal browser. CSRF menjadi perhatian ketika token disimpan dalam cookie. Untuk informasi selengkapnya, lihat sampel kode SPA masalah GitHub menambahkan dua cookies.

Beberapa aplikasi yang dihosting di satu domain

Lingkungan hosting bersama rentan terhadap pembajakan sesi, CSRF masuk, dan serangan lainnya.

Meskipun example1.contoso.net dan example2.contoso.net merupakan host yang berbeda, ada hubungan kepercayaan implisit antara host di *.contoso.net bawah domain. Hubungan kepercayaan implisit ini memungkinkan host yang berpotensi tidak tepercaya untuk memengaruhi satu sama lain cookie(kebijakan asal yang sama yang mengatur permintaan AJAX tidak selalu berlaku untuk HTTP cookie.

Serangan yang mengeksploitasi tepercaya cookieantara aplikasi yang dihosting di domain yang sama dapat dicegah dengan tidak berbagi domain. Saat setiap aplikasi dihosting di domainnya sendiri, tidak ada hubungan kepercayaan implisit cookie untuk dieksploitasi.

konfigurasi antiforgery ASP.NET Core

Peringatan

ASP.NET Core mengimplementasikan antiforgery menggunakan ASP.NET Core Data Protection. Tumpukan perlindungan data harus dikonfigurasi untuk bekerja di farm server. Untuk informasi selengkapnya, lihat Mengonfigurasi perlindungan data.

Middleware antiforgery ditambahkan ke kontainer injeksi Dependensi ketika salah satu API berikut dipanggil dalam Startup.ConfigureServices:

Dalam ASP.NET Core 2.0 atau yang lebih baru, FormTagHelper menyuntikkan token antiforgery ke dalam elemen bentuk HTML. Markup berikut dalam Razor file secara otomatis menghasilkan token antiforgery:

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

Demikian pula, IHtmlHelper.BeginForm menghasilkan token antiforgery secara default jika metode formulir bukan GET.

Pembuatan otomatis token antiforgery untuk elemen formulir HTML terjadi ketika <form> tag berisi method="post" atribut dan salah satu dari yang berikut ini benar:

  • Atribut tindakan kosong (action="").
  • Atribut tindakan tidak disediakan (<form method="post">).

Pembuatan token antiforgeri otomatis untuk elemen formulir HTML dapat dinonaktifkan:

  • Nonaktifkan token antiforgery secara eksplisit dengan asp-antiforgery atribut :

    <form method="post" asp-antiforgery="false">
        ...
    </form>
    
  • Elemen formulir ditolak dari Pembantu Tag dengan menggunakan simbol penolakan Pembantu Tag ! :

    <!form method="post">
        ...
    </!form>
    
  • FormTagHelper Hapus dari tampilan. FormTagHelper dapat dihapus dari tampilan dengan menambahkan direktif berikut ke Razor tampilan:

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

Catatan

Razor Halaman secara otomatis dilindungi dari XSRF/CSRF. Untuk informasi selengkapnya, lihat XSRF/CSRF dan Razor Pages.

Pendekatan paling umum untuk bertahan dari serangan CSRF adalah menggunakan Pola Token Penyinkron (STP). STP digunakan saat pengguna meminta halaman dengan data formulir:

  1. Server mengirim token yang terkait dengan identitas pengguna saat ini ke klien.
  2. Klien mengirim kembali token ke server untuk verifikasi.
  3. Jika server menerima token yang tidak cocok dengan identitas pengguna yang diautentikasi, permintaan akan ditolak.

Token unik dan tidak dapat diprediksi. Token juga dapat digunakan untuk memastikan urutan yang tepat dari serangkaian permintaan (misalnya, memastikan urutan permintaan: halaman 1 > halaman 2 > halaman 3). Semua formulir dalam templat ASP.NET Core MVC dan Razor Pages menghasilkan token antiforgery. Sepasang contoh tampilan berikut menghasilkan token antiforgery:

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

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

Secara eksplisit menambahkan token antiforgery ke <form> elemen tanpa menggunakan Pembantu Tag dengan pembantu @Html.AntiForgeryTokenHTML :

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

Dalam setiap kasus sebelumnya, ASP.NET Core menambahkan bidang formulir tersembunyi yang mirip dengan contoh berikut:

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

ASP.NET Core mencakup tiga filter untuk bekerja dengan token antiforgery:

Opsi antiforgery

Sesuaikan AntiforgeryOptions dalam Startup.ConfigureServices:

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

Atur properti antiforgery Cookie menggunakan properti kelas , seperti yang CookieBuilder ditunjukkan dalam tabel berikut.

Opsi Deskripsi
Cookie Menentukan pengaturan yang digunakan untuk membuat antiforgery cookie.
FormFieldName Nama bidang formulir tersembunyi yang digunakan oleh sistem antiforgery untuk merender token antiforgery dalam tampilan.
HeaderName Nama header yang digunakan oleh sistem antiforgery. Jika null, sistem hanya mempertimbangkan data formulir.
SuppressXFrameOptionsHeader Menentukan apakah akan menekan pembuatan X-Frame-Options header. Secara default, header dihasilkan dengan nilai "SAMEORIGIN". Default ke false.

Untuk informasi selengkapnya, lihat CookieAuthenticationOptions .

Mengonfigurasi fitur antiforgery dengan IAntiforgery

IAntiforgery menyediakan API untuk mengonfigurasi fitur antiforgery. IAntiforgery dapat diminta dalam Configure metode Startup kelas .

Dalam contoh berikut:

  • Middleware dari halaman beranda aplikasi digunakan untuk menghasilkan token antiforgery dan mengirimkannya dalam respons sebagai cookie.
  • Token permintaan dikirim sebagai JavaScript yang dapat cookie dibaca dengan konvensi penamaan Angular default yang dijelaskan di bagian AngularJS .
public void Configure(IApplicationBuilder app, IAntiforgery antiforgery)
{
    app.Use(next => context =>
    {
        string path = context.Request.Path.Value;

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

        return next(context);
    });
}

Memerlukan validasi antiforgery

ValidateAntiForgeryToken adalah filter tindakan yang dapat diterapkan ke tindakan individual, pengontrol, atau secara global. Permintaan yang dibuat untuk tindakan yang menerapkan filter ini diblokir kecuali permintaan menyertakan token antiforgery yang valid.

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> RemoveLogin(RemoveLoginViewModel account)
{
    ManageMessageId? message = ManageMessageId.Error;
    var user = await GetCurrentUserAsync();

    if (user != null)
    {
        var result = 
            await _userManager.RemoveLoginAsync(
                user, account.LoginProvider, account.ProviderKey);

        if (result.Succeeded)
        {
            await _signInManager.SignInAsync(user, isPersistent: false);
            message = ManageMessageId.RemoveLoginSuccess;
        }
    }

    return RedirectToAction(nameof(ManageLogins), new { Message = message });
}

Atribut ValidateAntiForgeryToken memerlukan token untuk permintaan ke metode tindakan yang ditandainya, termasuk permintaan HTTP GET. ValidateAntiForgeryToken Jika atribut diterapkan di seluruh pengontrol aplikasi, atribut dapat ditimpa dengan IgnoreAntiforgeryToken atribut .

Catatan

ASP.NET Core tidak mendukung penambahan token antiforgery ke permintaan GET secara otomatis.

Memvalidasi token antiforgery secara otomatis hanya untuk metode HTTP yang tidak aman

ASP.NET Core tidak menghasilkan token antiforgery untuk metode HTTP yang aman (GET, HEAD, OPTIONS, dan TRACE). Alih-alih menerapkan ValidateAntiForgeryToken atribut secara luas dan kemudian menimpanya dengan IgnoreAntiforgeryToken atribut, atribut AutoValidateAntiforgeryToken dapat digunakan. Atribut ini berfungsi secara identik dengan ValidateAntiForgeryToken atribut , kecuali bahwa atribut ini tidak memerlukan token untuk permintaan yang dibuat menggunakan metode HTTP berikut:

  • GET
  • HEAD
  • OPSI
  • TRACE

Sebaiknya gunakan AutoValidateAntiforgeryToken secara luas untuk skenario non-API. Atribut ini memastikan tindakan POST dilindungi secara default. Alternatifnya adalah mengabaikan token antiforgery secara default, kecuali ValidateAntiForgeryToken diterapkan ke metode tindakan individual. Lebih mungkin dalam skenario ini untuk metode tindakan POST dibiarkan tidak terlindungi secara tidak sengaja, membuat aplikasi rentan terhadap serangan CSRF. Semua POS harus mengirim token antiforgery.

API tidak memiliki mekanisme otomatis untuk mengirim non-bagiancookie token. Implementasi mungkin tergantung pada implementasi kode klien. Beberapa contoh ditunjukkan di bawah ini:

Contoh tingkat kelas:

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

Contoh global:

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

Mengambil alih atribut antiforgery global atau pengontrol

Filter IgnoreAntiforgeryToken digunakan untuk menghilangkan kebutuhan token antiforgery untuk tindakan tertentu (atau pengontrol). Saat diterapkan, filter ini mengambil alih ValidateAntiForgeryToken dan AutoValidateAntiforgeryToken filter yang ditentukan pada tingkat yang lebih tinggi (secara global atau pada pengontrol).

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

Refresh token setelah autentikasi

Token harus di-refresh setelah pengguna diautentikasi dengan mengalihkan pengguna ke halaman tampilan atau Razor Halaman.

JavaScript, AJAX, dan SPAs

Dalam aplikasi tradisional berbasis HTML, token antiforgery diteruskan ke server menggunakan bidang formulir tersembunyi. Di aplikasi dan SPAs berbasis JavaScript modern, banyak permintaan dibuat secara terprogram. Permintaan AJAX ini dapat menggunakan teknik lain (seperti header permintaan atau cookies) untuk mengirim token.

Jika cookies digunakan untuk menyimpan token autentikasi dan untuk mengautentikasi permintaan API di server, CSRF adalah masalah potensial. Jika penyimpanan lokal digunakan untuk menyimpan token, kerentanan CSRF mungkin dimitigasi karena nilai dari penyimpanan lokal tidak dikirim secara otomatis ke server dengan setiap permintaan. Menggunakan penyimpanan lokal untuk menyimpan token antiforgery pada klien dan mengirim token sebagai header permintaan adalah pendekatan yang direkomendasikan.

JavaScript

Menggunakan JavaScript dengan tampilan, token dapat dibuat menggunakan layanan dari dalam tampilan. IAntiforgery Masukkan layanan ke dalam tampilan dan panggil GetAndStoreTokens:

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

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

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

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

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

Pendekatan ini menghilangkan kebutuhan untuk berurusan langsung dengan pengaturan cookiedari server atau membacanya dari klien.

Contoh sebelumnya menggunakan JavaScript untuk membaca nilai bidang tersembunyi untuk header AJAX POST.

JavaScript juga dapat mengakses token dalam cookiedan menggunakan cookiekonten 's untuk membuat header dengan nilai token.

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

Dengan asumsi permintaan skrip untuk mengirim token di header yang disebut X-CSRF-TOKEN, konfigurasikan layanan antiforgery untuk X-CSRF-TOKEN mencari header:

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

Contoh berikut menggunakan JavaScript untuk membuat permintaan AJAX dengan header yang sesuai:

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

SudutJS

AngularJS menggunakan konvensi untuk mengatasi CSRF. Jika server mengirim cookie dengan nama XSRF-TOKEN, layanan AngularJS$http menambahkan cookie nilai ke header saat mengirim permintaan ke server. Proses ini bersifat otomatis. Klien tidak perlu mengatur header secara eksplisit. Nama header adalah X-XSRF-TOKEN. Server harus mendeteksi header ini dan memvalidasi isinya.

Agar ASP.NET Core API berfungsi dengan konvensi ini dalam startup aplikasi Anda:

  • Konfigurasikan aplikasi Anda untuk menyediakan token dalam yang cookie disebut XSRF-TOKEN.
  • Konfigurasikan layanan antiforgery untuk mencari header bernama X-XSRF-TOKEN, yang merupakan nama header default Angular untuk mengirim token XSRF.
public void Configure(IApplicationBuilder app, IAntiforgery antiforgery)
{
    app.Use(next => context =>
    {
        string path = context.Request.Path.Value;

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

        return next(context);
    });
}

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

Catatan

Ketika token antiforgery disediakan di header permintaan dan dalam payload formulir, hanya token di header yang divalidasi.

Autentikasi Windows dan antiforgery cookies

Saat menggunakan Autentikasi Windows, titik akhir aplikasi harus dilindungi dari serangan CSRF dengan cara yang sama seperti yang dilakukan untuk cookies. Browser secara implisit mengirim konteks autentikasi ke server sehingga titik akhir perlu dilindungi dari serangan CSRF.

Perluas antiforgery

Jenis ini IAntiforgeryAdditionalDataProvider memungkinkan pengembang untuk memperluas perilaku sistem anti-CSRF dengan melakukan round-tripping data tambahan di setiap token. Metode GetAdditionalData ini dipanggil setiap kali token bidang dihasilkan, dan nilai pengembalian disematkan dalam token yang dihasilkan. Pelaksana dapat mengembalikan tanda waktu, nonce, atau nilai lain lalu memanggil ValidateAdditionalData untuk memvalidasi data ini saat token divalidasi. Nama pengguna klien sudah disematkan dalam token yang dihasilkan, sehingga tidak perlu menyertakan informasi ini. Jika token menyertakan data tambahan tetapi tidak IAntiForgeryAdditionalDataProvider dikonfigurasi, data tambahan tidak divalidasi.

Sumber Daya Tambahan: