Wykrywanie XSS

Wykrywanie XSS

Ten artykuł jest częścią serii o zagrożeniu XSS:

  1. Co to jest XSS?
  2. Wykrywanie XSS
  3. Automatyczne wykrywanie XSS
  4. Zabezpieczenie przed XSS

W tym artykule skupimy się na metodach wykrywania podatności typu XSS. Dowiesz się, w jaki sposób identyfikować potencjalnie zagrożone elementy aplikacji oraz jak weryfikować, czy rzeczywiście są one zagrożeniem.Zachęcam również do przeczytania pierwszego wpisy – o tym czym jest XSS i dlaczego jest groźny. W szczególności, gdy nie jesteś jeszcze zaznajomiony z tematem.

Ręcznie testowanie

Zacznijmy od tego, w jaki sposób samodzielnie wykrywać i weryfikować podatności XSS w aplikacji. Cały proces możemy podzielić na kilka następujących części.

Wykrywanie XSS - schemat
Wykrywanie XSS – schemat

Identyfikacja potencjalnego miejsca

Pierwszym krokiem zawsze jest analiza aplikacji (lub danej funkcjonalności) pod kątem miejsc, które potencjalnie mogą stać się punktem wejścia dla ataku.
W przypadku podatności XSS są to wszelkie miejsca, poprzez które użytkownik może wstawić do systemu dane tekstowe. W szczególności w sytuacji, gdy te dane są później dostępne dla innego użytkownika (lub użytkowników) w tej samej bądź innej aplikacji.

Dla uproszczenia można założyć, że niebezpieczne są wszelkie dane przekazywane:

  • w adresie URLu, 
  • poprzez pola tekstowe w aplikacji, 
  • przez parametry requestów na API, 
  • poprzez upload plików. 

Dla przykładu rozważmy aplikację – sklep internetowy. Załóżmy, że zidentyfikowaliśmy 3 potencjalne miejsca ataku w naszej aplikacji. Dla uproszczenia skupiamy się na wybranych przypadkach (w takiej aplikacji może istnieć dużo więcej “wejść” do systemu). 

  1. parametr w URL przekazujący kod produktu /item/[product_code]
  2. parametr w URL przekazujący nazwę do wyszukiwarki ?search=[search_phrase]
  3. imię, nazwisko i komentarz do zamówienia – jako pola tekstowe do wpisania. 

Klasyfikacja podatności

Zidentyfikowane potencjalne podatne miejsce w aplikacji trzeba zaklasyfikować. Należy zacząć od przemyślenia, gdzie w aplikacji są dostępne wprowadzone przez nas dane. W zależności od tego będziemy mogli zaklasyfikować do jakiego rodzaju XSS należy dana podatność. Jeżeli:

  • wprowadzony tekst wyświetla się od razu na ekranie, źródło tekstu jest zawarte w treści requestu HTTP (np. query parameter, header, User-Agent, itp.) to Reflected XSS;
  • wprowadzony tekst zapisuje się do bazy danych i może się wyświetlić innemu użytkownikowi to Stored XSS;
  • jeżeli wprowadzony tekst jest przetwarzany przez JavaScript i dopiero potem wyświetlany na ekranie to DOM-based XSS. W tym przypadku tekst może przyjść bezpośrednio z requestu lub z serwera. Dlatego można powiedzieć, że nie jest to osobny typ, lecz niejako dodatkowe utrudnienie w weryfikacji takiej podatności. 

Najprościej to zweryfikować, gdy znamy kod aplikacji. Na szczęście nawet jeżeli to nie my ją stworzyliśmy, nadal możemy dokonać takiego sprawdzenia. Wystarczy odpowiedzieć sobie na dwa pytania:

  • czy jest możliwość, że tekst wpisany przez jednego użytkownika zostanie wyświetlony innemu użytkownikowi?
  • czy parametry requestu zawarte w adresie URL są wyświetlane na stronie? 

W ten sposób zbadaliśmy z jakiego rodzaju podatnością możemy mieć do czynienia. Wróćmy do przykładu sklepu internetowego.

  1. parametr w URL przekazujący kod produktu /item/[product_code] – Reflected XSS, 
  2. parametr w URL przekazujący nazwę do wyszukiwarki ?search=[search_phrase] – Reflected XSS, 
  3. imię, nazwisko i komentarz do zamówienia – jako pola tekstowe do wpisania – Stored XSS. 

Weryfikacja podatności

Samo wyświetlenie wprowadzonego tekstu na stronie jeszcze nie oznacza problemów. To bardzo popularna i wygodna z punktu widzenia użytkownika praktyka.Dla przykładu Google tak wyświetla tekst, którego poszukujemy: https://www.google.com/search?q=test

Jeżeli takie wyświetlanie jest zrobione dobrze, nie stanowi problemu bezpieczeństwa.Najprostszą metodą na weryfikację, czy aplikacja jest podatna na XSS jest wykonania w ten sposób kodu, który uruchomi się w przeglądarce. Najłatwiej to zrobić, próbując po prostu uruchomić kod alert(1), który wyświetli okienko z wiadomością.

Wykrywanie XSS - przykład
Wykrywanie XSS – przykład

Bardzo trudno coś takiego przegapić podczas testowania, dzięki czemu łatwo można zweryfikować podatność.

Najprostszy przykład to próba wstawienia ciągu <script>alert(1)</script> w pole tekstowe lub parametr URL. W totalnie niezabezpieczonych aplikacjach to powinno zadziałać. Pod warunkiem że ten tekst jest bezpośrednio wstawiany w kod HTML, a nie w atrybut, kod CSS, itp. Wielu przypadkach istnieje jakaś przynajmniej podstawowa ochrona przed XSS, więc możemy być zmuszeni do użycia bardziej skomplikowanych tekstów. Na szczęście nie musimy tutaj wszystkiego wymyślać i próbować różnych kombinacji. Z pomocą przychodzą nam zestawienia takie jak https://owasp.org/www-community/xss-filter-evasion-cheatsheet. Zawierają one gotową listę formuł, które mogą służyć do obejścia filtrów XSS i wykonania kodu. Warto skorzystać z takiej pomocy przy weryfikacji.

Patrząc na nasz przykład, możemy po kolei sprawdzać, jak reaguje aplikacja na wstawianie różnego rodzaju wektorów ataku w miejsca o potencjalnej podatności. Jeżeli zobaczymy okienko z alertem przeglądarki, to znaleźliśmy podatność.Bardziej skomplikowanym przykładem jest przypadek trzeci, gdzie mamy powiązanie pomiędzy dwoma systemami. W ogólności wystarczy wstawić w pole podlegające podatności złośliwy kod i zapisać go do bazy. Następnie trzeba uruchomić drugą aplikację, w której można podejrzeć dane i po kolei przeglądać zapisane teksty. Jeżeli dla jakiegokolwiek rekordu zobaczymy na ekranie okienko alertu – znaleźliśmy podatność.

Narzędzia wspomagające

Gdybyśmy chcieli zweryfikować każde potencjalne miejsce w aplikacji, używając wielu różnych schematów tekstów, zajęłoby nam to sporo czasu. Zamiast tego dużo lepiej jest skorzystać z gotowych narzędzi. 

Jednym z takich narzędzi jest OWASP ZAP (tutaj pełen opis możliwości tego programu []). Posiada on funkcje fuzzingu, co pozwala nam uruchomić określone funkcje (requesty sieciowe) w systemie dla wielu różnych tekstów wejściowych. Co więcej OWASP ZAP ma dostępne (do pobrania) słowniki zawierające najpopularniejsze wektory ataku XSS. Dzięki temu w przypadku podatności Stored XSS możemy bardzo szybko wypełnić bazę danymi zawierającymi różnorodne niebezpieczne teksty.

Poniżej skrócona instrukcja, jak to zrobić.

OWASP ZAP – fuzzing XSS

Zaczynamy od zidentyfikowanie wszystkich requestów wykonywanych przez nasz system.

OWASP ZAP - zidentyfikowane requesty - wykrywanie XSS
OWASP ZAP – zidentyfikowane requesty

Następnie znajdujemy interesujący nas request i przechodzimy do podglądu jego szczegółów. 

OWASP ZAP - szczegóły requestu
OWASP ZAP – szczegóły requestu

Tam możemy zaznaczyć określony fragment requestu (który podejrzewamy o bycie potencjalnie podatnym miejscem), kliknąć prawym przyciskiem myszy i wybrać “Fuzz…”

OWASP ZAP - przycisk fuzzowiania
OWASP ZAP – przycisk fuzzowiania

W ten sposób otworzymy okno Fuzzera. W naszym przypadku wybieramy Payloads…

OWASP ZAP - opcje fuzzowiania
OWASP ZAP – opcje fuzzowiania

Następnie dodajemy payload.

OWASP ZAP - dane do fuzzowiania
OWASP ZAP – dane do fuzzowiania

Wybierając odpowiedni zbiór danych, które będą podstawiane pod zaznaczony fragment requestu.

OWASP ZAP - dane do fuzzowiania - wykrywanie XSS
OWASP ZAP – dane do fuzzowiania

Po zatwierdzeniu Fuzzingu będziemy mieli zapełniona bazę różnego rodzaju złośliwymi tekstami.

Żeby mieć dostęp do większej ilości słowników ataków XSS można zainstalować wtyczkę https://www.zaproxy.org/docs/desktop/addons/fuzzdb-offensive/

Podsumowanie

Podatności typu XSS wydają się być proste. Być może cały ten schemat wydaje się nieco przekomplikowany. Z jednej strony ciężko obecnie znaleźć podatności XSS tak proste jak <script>alert(1)</script>, bo wiele aplikacji ma pewne podstawowe zabezpieczenia. Z drugiej jednak strony istnienie podatności XSS otwiera pole do popisu bardzo niebezpiecznym atakom o potencjalnie dużym wpływie na użytkowników systemu (np. kradzież tokenu wszystkim adminom systemu). Warto zatem poświęcić trochę energii na poszukiwanie tego typu podatności. A jak już ją znajdziemy, to prawidłowo ją poprawić (co opisuje w artykule Zabezpieczenie przed XSS).

Powiązane: