Blog Dla Programistów C#/.NET

środa, 19 listopada 2025

Cross-Site Request Forgery (CSRF) to jedna z częstszych luk bezpieczeństwa aplikacji webowych. Atak tego typu może sprawić, że zalogowany użytkownik nieświadomie wykona niepożądaną akcję w Twojej aplikacji – na przykład zleci przelew bankowy – jeśli aplikacja nie jest odpowiednio zabezpieczona. W tym artykule wyjaśnię, na czym polega atak CSRF i jak bronić się przed nim w aplikacjach ASP.NET Core, wykorzystując wbudowane mechanizmy platformy.

Nie Daj Się Atakom CSRF w ASP.NET Core - Podstawy Ochrony

Czym jest atak CSRF?


Atak CSRF wykorzystuje fakt, że przeglądarka internetowa automatycznie dołącza uwierzytelnienie użytkownika (np. cookie sesyjne) do każdego żądania HTTP kierowanego do danej domeny. W ataku CSRF agresor przygotowuje złośliwą stronę (lub e-mail czy inny wektor), która zawiera np. ukryty formularz HTML albo skrypt JavaScript wysyłający żądanie HTTP do zaufanej aplikacji webowej ofiary. Gdy ofiara będąca zalogowanym użytkownikiem wejdzie na taką stronę, przeglądarka bez wiedzy użytkownika wyśle spreparowane żądanie do naszej aplikacji wraz z wszystkimi danymi uwierzytelniającymi (ciasteczkami sesyjnymi itp.). Serwer przyjmie żądanie i wykona szkodliwą akcję, myśląc że pochodzi ono od samego użytkownika. W efekcie ofiara może nieświadomie zrealizować czynność zaplanowaną przez atakującego, np. wykonując przelew na konto napastnika.

Dlaczego taka sztuczka w ogóle działa? Aplikacje podatne na CSRF to te, które ufały będącym poprawnie uwierzytelnionym żądaniom, nie weryfikując dodatkowo ich źródła. Przeglądarki przechowują ciasteczka sesyjne zalogowanego użytkownika i dołączają je automatycznie do każdego żądania kierowanego do danej domeny – niezależnie od tego, skąd to żądanie pochodzi. Oznacza to, że jeśli użytkownik jest zalogowany w Twojej aplikacji, a jednocześnie odwiedzi w innej karcie złośliwą witrynę, to ta druga może wygenerować zapytanie do Twojego serwisu, które będzie zawierało ważne ciasteczko sesyjne ofiary. Bez dodatkowych zabezpieczeń serwer nie ma sposobu odróżnić takiego fałszywego żądania od prawdziwego. Warto dodać, że atak CSRF nie ogranicza się tylko do metod POST – jeżeli jakieś operacje zmieniające stan aplikacji wywoływane są przez HTTP GET, to również mogą zostać wykorzystane (np. przez osadzenie specjalnego obrazka <img> z URL-em wywołującym akcję). Dlatego jedną z podstawowych zasad bezpieczeństwa jest nigdy nie wykonywać zmian stanu aplikacji przy użyciu żądań GET. Podsumowując, mamy problem: potrzebujemy mechanizmu, który pozwoli nam zweryfikować, czy żądanie faktycznie pochodzi z naszej strony, a nie zostało wygenerowane gdzieś indziej.


Ochrona przed CSRF w ASP.NET Core


Najpopularniejszym sposobem obrony przed CSRF jest stosowanie tokenów anty-CSRF (ang. anti-CSRF tokens), czyli wdrożenie tzw. synchronizowanego wzorca tokenu (Synchronizer Token Pattern). Pomysł jest prosty: serwer generuje unikalny, trudny do odgadnięcia token i przekazuje go przeglądarce (np. osadzając jako ukryte pole formularza HTML). Gdy przeglądarka wysyła kolejne żądanie zmieniające stan (np. podczas wysyłania formularza), musi dołączyć ten token. Serwer weryfikuje, czy otrzymany token jest prawidłowy i zgadza się z tym, co wcześniej wygenerował – tylko wtedy realizuje żądanie. Dzięki temu nawet jeśli atakujący wyśle ofierze swój formularz, nie zna wygenerowanej wartości tokenu, więc jego żądanie zostanie odrzucone. Token anty-CSRF zmienia się najczęściej przy każdej sesji lub żądaniu, dlatego nawet odkrycie tokenu po fakcie nic napastnikowi nie da (nie można go użyć ponownie, bo następne żądanie wymaga już innej wartości).

Platforma ASP.NET Core ma wbudowane mechanizmy CSRF, z których warto korzystać zamiast wymyślać własne. W aplikacjach MVC oraz Razor Pages generowanie i sprawdzanie tokenów odbywa się niemal automatycznie. W praktyce zabezpieczenie aplikacji przed CSRF sprowadza się do dwóch kroków:
    
Dodanie tokenu anty-CSRF po stronie klienta (widoku): W każdym formularzu HTML wysyłanym metodą POST należy umieścić ukryty input z tokenem. W Razor widokach można to zrobić wywołując pomocnik @Html.AntiForgeryToken(), ale nawet nie jest to zawsze wymagane – domyślny Tag Helper dla formularzy automatycznie generuje token przy metodzie POST. Dzięki temu każda wysyłka formularza będzie zawierać dodatkowy ukryty parametr z wartością tokenu, unikalną dla użytkownika (i ewentualnie dla danej sesji lub żądania).
    
Weryfikacja tokenu po stronie serwera: Metody akcji, które obsługują modyfikacje danych (np. akcje POST w kontrolerach), należy oznaczyć atrybutem [ValidateAntiForgeryToken]. Ten filtr sprawdzi automatycznie przy każdym żądaniu, czy w przesyłanych danych znajduje się prawidłowy token anty-CSRF. Jeśli token jest nieobecny lub niepoprawny – framework zablokuje wykonanie akcji (zwracając błąd 400) i tym samym ochroni nas przed potencjalnym atakiem.
Poniżej prosty przykład ilustrujący użycie tokenu anty-CSRF w formularzu ASP.NET Core MVC i odpowiadającej mu akcji kontrolera:

<form asp-action="TransferFunds" method="post">
@Html.AntiForgeryToken()
<!-- pola formularza: np. kwota, odbiorca -->
<input type="number" name="amount" placeholder="Kwota" />
<button type="submit">Wyślij</button>
</form>
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult TransferFunds(decimal amount)
{
/* ... logika transferu środków */
return View();
}

W powyższym kodzie widoku wywołanie @Html.AntiForgeryToken() generuje ukryty pole formularza z tokenem. Atrybut [ValidateAntiForgeryToken] zapewnia, że metoda TransferFunds przyjmie wyłącznie żądania posiadające ważny token – inaczej żądanie zostanie odrzucone. W przypadku Razor Pages framework również dba o te szczegóły za nas (tokeny są tam domyślnie dołączane i sprawdzane dla metod obsługujących POST). Dla wygody można także zastosować atrybut [AutoValidateAntiforgeryToken] – umieszczony globalnie (np. w konfiguracji filtrów) lub na klasie kontrolera – który automatycznie wymaga tokenu anty-CSRF dla wszystkich akcji modyfikujących stan (czyli dla metod innych niż GET) bez potrzeby dekorowania każdej z osobna. Takie ustawienie to dobry pomysł w większości typowych aplikacji webowych (poza czysto API backendami), ponieważ gwarantuje, że nawet nowo dodane akcje będą chronione domyślnie i trudno przez przypadek pominąć zabezpieczenie.

Warto również wspomnieć o mechanizmie SameSite dla ciasteczek, który stanowi dodatkową warstwę obrony. Ustawienie flagi SameSite dla ciastek sesyjnych na Strict (lub przynajmniej Lax) sprawia, że przeglądarka nie dołączy cookie sesji do żądania pochodzącego z innej strony, co samo w sobie blokuje sporą część ataków CSRF. Trzeba jednak pamiętać, że nie jest to rozwiązanie kompletne – SameSite ma pewne ograniczenia (np. dotyczy domen, nie konkretnych originów) i należy traktować go jako uzupełnienie klasycznej obrony tokenowej. Innymi słowy, SameSite to dodatkowa przeszkoda dla napastnika, ale nadal główne zabezpieczenie powinny stanowić tokeny anty-CSRF.


Podsumowanie


Ataki CSRF należą do klasycznych zagrożeń bezpieczeństwa aplikacji webowych, ale na szczęście można się przed nimi skutecznie zabezpieczyć, stosując proste i sprawdzone metody. W przypadku ASP.NET Core sprowadza się to do wykorzystania wbudowanego mechanizmu tokenów anty-CSRF – generowania tokenu po stronie klienta i walidacji po stronie serwera – oraz trzymania się dobrych praktyk (jak niezmienianie stanu aplikacji przez żądania GET). Dzięki temu nasza aplikacja od razu staje się odporna na całe spektrum ataków typu CSRF przy minimalnym wysiłku programistycznym. Pamiętaj, że bezpieczeństwo w świecie web developmentu to proces ciągły – warto stale poszerzać swoją wiedzę i korzystać z dostępnych narzędzi.

Jeśli zainteresował Cię temat zabezpieczania aplikacji w C#/.NET, rozważ dołączenie do mojego szkolenia online "Szkoła Bezpieczeństwa w C#/.NET". W tym szkoleniu krok po kroku omawiamy m.in. obronę przed atakami takimi jak CSRF oraz wiele innych aspektów tworzenia bezpiecznych aplikacji webowych w ASP.NET Core. Dzięki temu zdobędziesz kompleksową wiedzę, która pozwoli Ci tworzyć odporne na ataki oprogramowanie.

Autor artykułu:
Kazimierz Szpin
Kazimierz Szpin
CTO & Founder - FindSolution.pl
Programista C#/.NET. Specjalizuje się w Blazor, ASP.NET Core, ASP.NET MVC, ASP.NET Web API, WPF oraz Windows Forms.
Autor bloga ModestProgrammer.pl
Dodaj komentarz

Wyszukiwarka

© Copyright 2025 modestprogrammer.pl | Sztuczna Inteligencja | Regulamin | Polityka prywatności. Design by Kazimierz Szpin. Wszelkie prawa zastrzeżone.