XSS
Jak działa
1) Atakujący identyfikuje punkt wejścia, gdzie dane sterowane przez użytkownika (parametr URL, pole formularza, nagłówek, zawartość bazy danych) są umieszczane w odpowiedzi bez neutralizacji. 2) Konstruuje ładunek zawierający znaczniki lub kod skryptu (np. <script>, atrybut zdarzenia onerror, javascript: URI). 3) Ładunek jest dostarczany: w Reflected XSS przez spreparowany link lub żądanie, którego skrypt jest natychmiast odbijany w odpowiedzi; w Stored XSS przez trwałe zapisanie ładunku na serwerze (komentarz, wpis forum, log), skąd trafia do kolejnych odwiedzających; w DOM-based XSS przez kod JavaScript po stronie klienta, który zapisuje niezaufane dane do niebezpiecznego 'sink' (np. innerHTML) bez opuszczania przeglądarki. 4) Przeglądarka ofiary wykonuje skrypt w origin zaufanej witryny, uzyskując dostęp do ciasteczek, tokenów sesji i DOM, co umożliwia przejęcie sesji, kradzież danych, keylogging lub dalsze żądania w imieniu ofiary.
Rozwiązany problem
Porządkuje i nazywa klasę podatności, w której niezaufane dane wejściowe trafiają do kontekstu wykonywalnego przeglądarki (HTML, atrybuty, JavaScript, CSS, URL) bez właściwego kodowania lub sanityzacji. Zrozumienie XSS pozwala projektować obronę: kodowanie wyjścia zależne od kontekstu, sanityzację HTML i Content Security Policy, dzięki którym dane pozostają danymi, a nie kodem.
Komponenty
Wstrzyknięty skrypt jest natychmiast odbijany przez serwer w odpowiedzi (np. komunikat błędu, wynik wyszukiwania) i wykonywany, gdy ofiara otworzy spreparowany link lub żądanie. Nazywany też nieutrwalonym lub Type-I XSS.
Złośliwy skrypt jest trwale zapisany na serwerze docelowym (baza danych, forum, log odwiedzin, pole komentarza) i serwowany kolejnym użytkownikom. Nazywany też utrwalonym lub Type-II XSS. Wariant Blind XSS to Stored XSS, którego ładunek wykonuje się później, gdy treść otworzy np. administrator zaplecza.
Podatność po stronie klienta, zidentyfikowana w 2005 roku, występująca gdy JavaScript manipuluje DOM przy użyciu niezaufanych danych, zapisując je do niebezpiecznego 'sink' (np. innerHTML, document.write, eval) bez udziału serwera.
Implementacja
Użycie innerHTML, document.write, eval lub odpowiedników frameworkowych (React dangerouslySetInnerHTML, Angular bypassSecurityTrustAs*, Lit unsafeHTML) do wstawiania danych sterowanych przez użytkownika omija wbudowane zabezpieczenia i prowadzi do DOM-based XSS.
Umieszczanie danych bez kodowania właściwego dla kontekstu (HTML, atrybut, JavaScript, CSS, URL) pozwala na wyjście z kontekstu danych. Kodowanie HTML nie chroni wewnątrz <script>, komentarzy HTML, bloków <style> ani atrybutów zdarzeń.
Próby blokowania XSS przez czarne listy słów/znaków są łatwe do obejścia (kodowanie, alternatywne wektory, nowe elementy HTML) i dają fałszywe poczucie bezpieczeństwa.
Content Security Policy bywa błędnie traktowane jako podstawowa obrona; źle skonfigurowane lub zbyt liberalne polityki (np. unsafe-inline) nie powstrzymają XSS, a jednolite polityki korporacyjne mogą psuć starsze systemy.
Ewolucja
Inżynierowie bezpieczeństwa Microsoftu ukuli termin 'cross-site scripting'; CERT/CC opublikował advisory CA-2000-02 opisujące wstrzykiwanie złośliwych znaczników HTML w żądaniach webowych.
Opisano DOM-based XSS jako odrębny, po stronie klienta wariant podatności, w którym ładunek nigdy nie opuszcza przeglądarki.
W zestawieniu OWASP Top 10 (2013) Cross-Site Scripting sklasyfikowano jako osobną kategorię ryzyka A3.
W OWASP Top 10 (2021) Cross-Site Scripting zostało włączone do szerszej kategorii A03:2021 – Injection.