Blog Dla Programistów C#/.NET

wtorek, 18 listopada 2025

Cross-Site Scripting (XSS) to jedna z najczęstszych luk bezpieczeństwa w aplikacjach webowych. Polega ona na tym, że atakujący wstrzykuje złośliwy kod (najczęściej JavaScript) do strony internetowej w taki sposób, że kod ten uruchamia się w przeglądarce niczego niepodejrzewającego użytkownika. W efekcie napastnik może przejąć kontrolę nad interakcją użytkownika ze stroną – np. wykraść ciasteczka sesyjne lub tokeny uwierzytelniające, zmienić wyświetlaną zawartość strony, albo przekierować ofiarę na inną witrynę. Konsekwencje ataku XSS mogą być bardzo poważne – od drobnej uciążliwości po przejęcie konta użytkownika (np. przez kradzież jego cookie sesji). Dlatego jako początkujący programista .NET warto szybko nauczyć się, jak zapobiegać XSS i pisać bezpieczny kod.

Nie Daj Się XSS. Podstawy Ochrony Aplikacji C# Przed Atakami Cross-Site Scripting

Czym jest atak XSS?


W ataku XSS ofiara zazwyczaj sama ładuje stronę zawierającą złośliwy skrypt, nie zdając sobie z tego sprawy. Dzieje się tak najczęściej wtedy, gdy aplikacja webowa bierze dane wejściowe od użytkownika i następnie wyświetla je (wygeneruje z nich HTML) bez odpowiedniej walidacji czy kodowania. W praktyce może to być np. formularz komentarzy na stronie – jeśli nasz kod weźmie treść komentarza i wstawi ją na stronę "jak leci", atakujący może w komentarzu przemycić tag <script> i sprawić, że odwiedzający stronę uruchomią ten skrypt u siebie.

Rodzaje XSS: Wyróżnia się kilka odmian ataków cross-site scripting, m.in.:
    
Stored XSS (utrwalony): złośliwy skrypt zostaje trwale zapisany na serwerze (np. w bazie danych, jako część wpisu lub komentarza). Każdy użytkownik, który później wyświetli tę zawartość, uruchomi wstrzyknięty kod – to jak ukrycie pułapki, na którą ofiary natrafią podczas normalnego korzystania z aplikacji.
    
Reflected XSS (odbity): skrypt jest odbijany przez serwer w odpowiedzi HTTP i od razu wykonuje się w przeglądarce ofiary. Dzieje się tak zwykle, gdy atakujący nakłoni ofiarę do kliknięcia specjalnie spreparowanego linku lub wypełnienia formularza – złośliwy kod trafia wtedy do serwera w żądaniu, a serwer bezpiecznie (choć w tym przypadku niebezpiecznie) umieszcza go w odpowiedzi, która wraca do przeglądarki i wykonuje się.
    
DOM-based XSS: atak wykorzystujący manipulacje po stronie klienta – tu podatny jest kod JavaScript aplikacji, który np. interpretuje fragment URL lub danych z przeglądarki jako HTML i wstrzykuje w DOM. Ten rodzaj XSS nie wymaga bezpośredniego udziału serwera w generowaniu złośliwego skryptu.

Niezależnie od odmiany, sedno XSS jest jedno: aplikacja nieświadomie pomaga wstrzyknąć i wykonać obcy kod. Poniżej skupię się na tym, jak temu zapobiec w kontekście C# i ASP.NET, gdzie generujemy strony HTML po stronie serwera.


Jak zapobiegać atakom XSS?


Najważniejsza zasada: nie ufaj żadnym danym od użytkownika. Wszystko, co pochodzi z zewnątrz (formularze, parametry zapytań URL, nagłówki HTTP, a nawet dane z bazy danych) traktuj jako potencjalnie złośliwe. Poniżej przedstawiam podstawowe techniki ochrony przed XSS w aplikacjach .NET:
    
Walidacja i filtrowanie danych wejściowych: Zawsze sprawdzaj poprawność danych, które przyjmuje Twoja aplikacja. To taki punkt kontrolny bezpieczeństwa – przepuszczamy tylko dane w oczekiwanym formacie. Na przykład, jeżeli pole powinno zawierać tylko litery i cyfry, można użyć atrybutu [RegularExpression] lub innych [DataAnnotations] do walidacji modelu i odrzucić niepasujące treści. W ten sposób zablokujesz już na wejściu oczywiście podejrzane dane (np. fragmenty <script>). Pamiętaj jednak, że walidacja nie zastępuje innych metod ochrony – traktuj ją jako pierwszą warstwę zabezpieczeń.
   
Kodowanie danych wyjściowych (output encoding): Nigdy nie wyświetlaj surowych danych pochodzących od użytkownika bez uprzedniego zakodowania specjalnych znaków. Kodowanie HTML polega na zamianie znaków o specjalnym znaczeniu w HTML (takich jak <, > czy &) na odpowiadające im bezpieczne sekwencje (np. < na &lt;). Dzięki temu przeglądarka traktuje je jako zwykły tekst, a nie część kodu strony. To samo dotyczy danych w atrybutach HTML – one również muszą być odpowiednio zakodowane (cudzysłów, apostrof itp.). W ASP.NET Core na szczęście silnik Razor robi to automatycznie – każda zmienna wyświetlona poprzez @ w widoku zostanie domyślnie zakodowana w odpowiedni sposób. Dzięki temu, dopóki korzystasz z wbudowanych mechanizmów, zwykle jesteś bezpieczny. Problemy pojawiają się, gdy celowo lub przypadkowo ominiemy to kodowanie.
    
Nie wyłączaj domyślnej ochrony: Unikaj praktyk, które omijają mechanizmy zabezpieczające frameworku. Przykładowo, w Razor nie używaj metod typu Html.Raw(...) czy klas pokroju HtmlString do wyświetlania danych pochodzących od użytkownika. Takie konstrukcje wyłączają automatyczne kodowanie i spowodują, że złośliwy kod HTML/JS przedostanie się do odpowiedzi bez zmian – czyli dokładnie to, czego chcemy uniknąć. Jeśli masz potrzebę wyświetlenia HTML, który ufasz, lepiej skorzystać z bezpiecznych mechanizmów (np. przygotować częściowy widok, który generuje ten HTML, albo użyć tzw. whitelist tagów – o czym za moment).
    
Specjalne traktowanie danych w skryptach i URL: Jeżeli musisz umieścić dane użytkownika wewnątrz kodu JavaScript (np. w wygenerowanym skrypcie w tagu <script>), nie rób tego bezpośrednio. Najbezpieczniej jest przekazać dane przez HTML – np. umieścić je w atrybucie data-* elementu i dopiero odczytać w skrypcie po stronie klienta. Jeśli jednak dynamiczne generowanie kodu JS z danymi jest konieczne, zadbaj o tzw. JavaScript encoding – czyli zakodowanie znaków specjalnych w ciągach JS (np. < jako \u003C). Podobna zasada dotyczy adresów URL – wszelkie dane włączane do ciągów zapytania (query string) powinny być poddane kodowaniu URL (np. spacja na %20) zanim trafią do href czy src.
    
Sanityzacja HTML (filtrowanie złośliwych znaczników): Czasami chcemy świadomie pozwolić użytkownikom na wprowadzenie pewnych znaczników HTML – np. formatowanie tekstu w komentarzach (pogrubienia, linki itp.). W takiej sytuacji sam encoding może nie wystarczyć (bo chcemy jednak część HTML wyrenderować), a wyłączenie kodowania w całości byłoby bardzo niebezpieczne. Tu z pomocą przychodzą biblioteki do sanityzacji (oczyszczania) HTML, które usuwają lub neutralizują niedozwolone elementy. W .NET dostępna jest np. biblioteka Ganss.XSS, zawierająca klasę HtmlSanitizer. Można jej użyć do wyczyszczenia HTML-a wejściowego – niechciane tagi (script, iframe itp.) zostaną wycięte, pozostawiając tylko dozwolone formatowanie. Poniższy kod demonstruje użycie HtmlSanitizer z tej biblioteki:

var sanitizer = new Ganss.XSS.HtmlSanitizer();
string czystyHtml = sanitizer.Sanitize(nieufnyHtml);

Tak przefiltrowany fragment nieufnyHtml pozbawiony będzie szkodliwych elementów, które mogłyby posłużyć do XSS. Oczywiście sanitizację HTML stosuj tylko wtedy, gdy naprawdę potrzebujesz wpuszczać ograniczony HTML od użytkownika. W przeciwnym razie lepiej trzymać się prostego tekstu i kodowania wyjściowego.
Poniżej prosty przykład ilustrujący właściwe i niewłaściwe podejście do wyświetlania danych od użytkownika w widoku Razor:

@{
var input = "<script>alert('XSS');</script>";
}
<p>Bezpieczne wyświetlenie: @input</p>
<p>Niebezpieczne wyświetlenie: @Html.Raw(input)</p>

W powyższym fragmencie pierwsza linia wyświetli zakodowany tekst (użytkownik zobaczy ciąg &lt;script&gt;alert('XSS');&lt;/script&gt; zamiast wykonania skryptu), podczas gdy druga linia wstawi kod bez kodowania – w efekcie przy renderowaniu strony przeglądarka uruchomi złośliwy alert. Wniosek: w 99% przypadków nie potrzebujesz Html.Raw – pozostaw domyślne kodowanie Razor, a uchronisz się przed większością XSS.


Podsumowanie


Ataki XSS to poważne zagrożenie, ale trzymając się powyższych zasad, znacznie zminimalizujesz ryzyko. Pamiętaj, że najważniejsze filary obrony to: uważna walidacja danych wejściowych oraz pewne kodowanie danych wyjściowych. Wykorzystuj wbudowane mechanizmy ASP.NET Core (automatyczne kodowanie w Razor, atrybuty [Validate...] itp.) i nie wyłączaj ich bez potrzeby. Dzięki temu nawet jeśli napastnik spróbuje przesłać złośliwy kod, Twoja aplikacja go rozbroi zanim trafi do przeglądarki.

Oczywiście, bezpieczeństwo aplikacji to temat rzeka – XSS to tylko jeden z wielu wektorów ataku. Jeśli zainteresowało Cię, jak kompleksowo chronić aplikacje webowe oparte o C#/.NET, to zapraszam do mojego szkolenia online "Szkoła Bezpieczeństwa w C#/.NET". W szkoleniu omawiam szczegółowo nie tylko obronę przed XSS, ale także inne kluczowe zagadnienia bezpieczeństwa w ASP.NET Core, dzięki czemu dowiesz się, jak tworzyć odporne i bezpieczne aplikacje.

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.