Cross-Site Scripting (XSS)¶
XSS to podatność aplikacji webowej umożliwiająca atakującemu wstrzyknięcie danych, które w określonym kontekście mogą zostać zinterpretowane jako kod wykonywany w przeglądarce użytkownika.
Podatność XSS powstaje najczęściej, gdy niezaufane dane trafiają ze źródła, np. parametru URL lub formularza, do miejsca, w którym przeglądarka może potraktować je jako fragment kodu napisanego w języku HTML lub JavaScript. Ochrona musi być dostosowana do miejsca użycia danych. Przykładowo aplikacja może pobierać dane od użytkownika, a następnie umieszczać je bez odpowiedniego kodowania lub sanityzacji w kodzie HTML, atrybucie HTML, kodzie JavaScript lub innym kontekście, w którym mogą zostać zinterpretowane jako kod.
Ważna informacja
Sama akceptacja lub zapisanie niezaufanych danych przez aplikację nie jest jeszcze podatnością XSS. Do wykonania dochodzi dopiero w momencie, gdy te dane trafiają z powrotem do przeglądarki i zostają przez nią zinterpretowane jako kod, a nie zwykły tekst.
Skutki udanego ataku¶
Udany atak XSS może prowadzić do:
- wykonywania operacji w kontekście aktywnej sesji użytkownika,
- odczytu lub kradzieży danych dostępnych dla kodu JavaScript,
- przejęcia konta, jeżeli aplikacja umożliwia zmianę danych uwierzytelniających bez dodatkowego potwierdzenia,
- wyświetlania fałszywych formularzy i wyłudzania danych,
- modyfikowania zawartości strony,
- przekierowywania użytkownika do złośliwych stron.
Reflected XSS¶
Reflected XSS to rodzaj podatności XSS, w której złośliwy kod jest przesyłany w żądaniu użytkownika (najczęściej poprzez adres URL), następnie zostaje „odbity” przez serwer w odpowiedzi HTTP, a na końcu wykonany w przeglądarce ofiary. Dane nie są trwale przechowywane przez aplikację, dlatego atak zazwyczaj wymaga nakłonienia ofiary do otwarcia przygotowanego odnośnika lub wysłania określonego żądania.
Typowymi miejscami występowania podatności Reflected XSS są funkcjonalności wykorzystujące dane dostarczane przez użytkownika, takie jak wyszukiwarki, formularze, komunikaty o błędach, strony logowania, parametry URL oraz mechanizmy filtrowania i sortowania wyników.
Przykładem może być funkcjonalność wyszukiwania na stronie internetowej - użytkownik korzysta z wyszukiwarki:
Aplikacja wyświetla wpisaną wartość:
Atakujący może zmodyfikować parametr q i zamiast zwykłego tekstu przesłać kod JavaScript:
Jeżeli aplikacja wyświetli zawartość parametru bez odpowiedniego escapowania:
przeglądarka zinterpretuje znacznik jako kod JavaScript i wykona go. Efektem wykonania będzie popupu z cyfrą "1".
Stored XSS (Persistent XSS)¶
Stored XSS, nazywany również Persistent XSS, to wariant podatności, w którym niezaufane dane zostają zapisane przez aplikację, np. w bazie danych, a następnie wyświetlone bez odpowiedniego zabezpieczenia. Jeżeli przeglądarka zinterpretuje je jako aktywną treść, kod może zostać wykonany u użytkowników odwiedzających podatną stronę.
Stored XSS może mieć większy zasięg niż Reflected XSS, ponieważ zapisane dane mogą być wyświetlane wielu użytkownikom. Atak nie musi wymagać otwarcia specjalnie przygotowanego odnośnika - może wystarczyć odwiedzenie strony, na której aplikacja wyświetla niezaufane dane bez odpowiedniego zabezpieczenia.
Użytkownik dodaje komentarz:
Komentarz zostaje zapisany w bazie danych. Następnie aplikacja wyświetla go na stronie:
Przeglądarka interpretuje tag jako kod JavaScript i wykonuje go. Efektem będzie wyświetlenie popupu z cyfrą "1".
DOM XSS¶
DOM XSS powstaje, gdy kod JavaScript działający w przeglądarce pobiera dane z niezaufanego źródła i przekazuje je do funkcji, która interpretuje je jako HTML lub JavaScript. Do podatności może dojść bez umieszczania szkodliwej treści w odpowiedzi HTML generowanej przez serwer.
Reflected XSS i Stored XSS opisują sposób dostarczenia lub przechowywania danych, natomiast DOM XSS opisuje mechanizm przetwarzania danych po stronie przeglądarki. Kategorie te nie zawsze są całkowicie rozłączne.
Przykład podatności¶
Kod aplikacji (JavaScript):
Użytkownik odwiedza stronę:
Strona wyświetli:
Wstrzyknięcie złośliwego kodu:
Po załadowaniu strony JavaScript wstawi:
Ponieważ dane zostały przekazane bezpośrednio do innerHTML, zawarty w nich znacznik HTML może zostać zinterpretowany przez przeglądarkę, a obsługa onerror może doprowadzić do wykonania kodu JavaScript:
Info
DOM XSS najczęściej wynika z niebezpiecznego wykorzystania danych ze źródeł takich jak np: location.hash, location.search, document.referrer, postMessage, danych z localStorage / sessionStorage. Przykładami typowych niebezpiecznych sinków (ang. sink), czyli miejsc w kodzie JavaScript, które mogą zinterpretować przekazane dane jako HTML lub kod wykonywalny, są: innerHTML, outerHTML, document.write(), eval() oraz insertAdjacentHTML().
Rekomendacje¶
Aby ograniczyć ryzyko XSS, należy:
- wyświetlać niezaufane dane jako zwykły tekst, korzystając z mechanizmów automatycznego kodowania dostępnych w używanym frameworku,
- dostosowywać sposób zabezpieczenia do miejsca użycia danych. Dane umieszczane w zwykłym tekście HTML, atrybucie, adresie URL, CSS lub JavaScript wymagają różnych metod kodowania,
- unikać umieszczania niezaufanych danych bezpośrednio wewnątrz skryptów, stylów CSS, obsługi zdarzeń, takich jak
onclick, oraz innych miejsc, w których samo kodowanie może być niewystarczające, - jeżeli użytkownicy mogą wprowadzać HTML, oczyszczać go za pomocą aktualizowanej i sprawdzonej biblioteki, np. DOMPurify, oraz ograniczać dozwolone elementy i atrybuty. Nie należy modyfikować treści po jej oczyszczeniu w sposób, który może ponownie wprowadzić niebezpieczne elementy,
- w kodzie JavaScript korzystać z funkcji traktujących dane jako tekst, takich jak
textContent, oraz bezpiecznie tworzyć elementy za pomocącreateElement(). Unikać przekazywania niezaufanych danych doinnerHTML,outerHTML,insertAdjacentHTML(),document.write()ieval(), - stosować Content Security Policy (CSP) jako dodatkową warstwę ochrony, ograniczającą możliwość wykonania niepożądanego kodu w przypadku wystąpienia podatności XSS,
- walidować dane wejściowe względem oczekiwanego formatu i zakresu, ale traktować walidację jako zabezpieczenie dodatkowe, a nie zamiennik bezpiecznego wyświetlania danych.
Zapamiętaj
Wszystkie niezaufane dane należy bezpiecznie przetwarzać w miejscu ich użycia. Sam fakt, że dane pochodzą z formularza, adresu URL, bazy danych, pamięci przeglądarki lub innego komponentu aplikacji, nie oznacza, że są bezpieczne.
Jeżeli aplikacja pozwala użytkownikowi dostarczyć dane, a następnie interpretuje je jako kod wykonywalny, istnieje ryzyko wystąpienia podatności XSS.