Sekcje

Przejdź na skróty do treści. | Przejdź do nawigacji


Baza wiedzy Publikacje Fuzzing aplikacji webowych - część druga

Fuzzing aplikacji webowych - część druga

— w kategorii: , ,

 Po przeczytaniu dowiesz się:

  • Bezpieczeństwo aplikacji Jak napisać własny fuzzer
  • Dlaczego autorskie rozwiązania czasami są lepsze od gotowych, zaawansowanych narzędzi
  • Z jakich elementów składowych zbudowany jest fuzzer aplikacji webowych
  • Jakie są główne problemy projektowe związane z pisaniem fuzzera
  • Jak posługiwać się takimi narzędziami jak Wfuzz
  • Jak efektywnie bronić się przed fuzzingiem

 Wstęp

W poprzedniej części artykułu przybliżyłem pojęcie fuzzingu oraz opisałem jego główne wady i zalety. W poniższej publikacji chciałbym skupić się na bardziej zaawansowanych aspektach fuzz testingu, obejmujących tworzenie własnego oprogramowania testującego, związane z tym problemy projektowe a także omówić praktyczne wykorzystanie takich narzędzi jak WFuzz.

Czy warto budować swój fuzzer?

W Internecie można znaleźć wiele interesujących programów stworzonych zgodnie z ideami fuzzingu. Aplikacje te są zróżnicowane – możemy odszukać proste, wyspecjalizowane fuzzery, których kod źródłowy mieści się w kilkuset linijkach, a także rozbudowane frameworki oferujące ogromne możliwości. Mnogość rozwiązań prowadzi do pytania czy warto budować kolejny, autorski fuzzer mając do dyspozycji setki innych, czasami bardzo dobrych programów. Odpowiedź zależy od rodzaju problemu, do rozwiązania którego chcemy wykorzystać fuzzer. Jeżeli ograniczymy się tylko i wyłącznie do aplikacji webowej, to wykorzystanie autorskiego fuzzera może być godne rozpatrzenia, gdy:

  • testowana aplikacja posiada specyficzną strukturę (nietypowe katalogi, pliki, przechowywane dane)
  • znamy, przynajmniej w minimalnym stopniu, budowę aplikacji, co pozwala na lepsze dobranie danych testowych
  • aplikacja bazuje na danych, które są trudne do wygenerowania przez tradycyjne fuzzery webowe (np. nietypowe formaty plików, protokoły)

 

W przypadku gdy powyższe wymagania nie są spełnione, budowanie fuzzera od podstaw może mijać się z celem. W takim przypadku lepiej zastanowić się nad wykorzystaniem framework-a (np. RFuzz) lub gotowego fuzzera (np. opisywany dalej WFuzz).

Elementy składowe fuzzera

Jeżeli już zdecydujemy się na pisanie swojego, unikalnego fuzzera przeznaczonego do testowania aplikacji webowych to należy przed przystąpieniem do pracy zastanowić się nad jego logiczną strukturą i przemyśleć budowę każdej z jego części składowych. Fuzzer możemy podzielić na następujące bloki funkcjonalne:

  • Blok odpowiadający za nawiązywanie połączeń, wysyłanie, odbieranie oraz kodowanie danych .
  • Blok odpowiedzialny za generowanie danych wysyłanych do testowanej aplikacji.
  • Blok odpowiedzialny za identyfikację punktów wejściowych, do których będą wysyłane dane.
  • Blok odpowiedzialny za wykrywanie błędów.
  • Blog odpowiedzialny za agregowanie wyników działania fuzzera.

Każdy z powyższych bloków ma identyczny priorytet i jest integralną częścią fuzzera. Tworząc własny program testowy warto poświęcić czas na dopracowanie każdego z wymienionych bloków i w miarę możliwości starać się traktować je jako niezależne elementy, które mogą być wykorzystane w kolejnych projektach.

Problemy projektowe

Testowanie aplikacji webowej na pierwszy rzut oka może wydawać się czynnością dość prostą. Co więcej, kierując się takim przeświadczeniem możemy dojść do wniosku, że napisanie aplikacji automatyzującej cały proces testowania także jest łatwe i przyjemne. Najczęściej, po rozpoczęciu prac nad autorskim fuzzerem nasz optymizm jest niwelowany przez rzeczywiste problemy, którym musi sprostać programista.

Po pierwsze, aby rozpocząć proces fuzzingu musimy określić potencjalne wektory ataku, punkty wejściowe aplikacji (czyli takie, do których możemy przekazywać dane) oraz zebrać jak największą liczbę informacji odnośnie samego programu. W przypadku aplikacji webowej będą to wszelkiego rodzaju parametry (przekazywane metodą POST, GET czy innymi wchodzącymi w skład protokołu HTTP), odnośniki w formie tzw. „pretty links” (odnośników pozbawionych rozszerzeń, np. www.example.com/users/list/ zamiast www.example.com/users/list.php), ukryte katalogi, pliki konfiguracyjne oraz elementy jednoznacznie wskazujące na wykorzystanie konkretnej technologii (np. występowanie jsessionid). Aby zebrać informacje tego typu będziemy potrzebować kilku narzędzi, które możemy napisać sami (często wiąże się to z dużymi nakładami czasowymi, na które w wielu wypadkach nie możemy sobie pozwolić) lub wykorzystać rozwiązania udostępnione np. na licencji OpenSource. Będą to:

  • Dobry (czyt. wydajny i niezawodny) parser HTML/XML, który będzie odpowiadał za pobieranie interesujących nas danych z kodu strony.
  • Web Crawler/Web Spider, odpowiadający za przechodzenie po kolejnych stronach i zbieranie informacji w nich zawartych.
  • Narzędzie, które będzie w stanie identyfikować ukryte katalogi oraz pliki. W większości wypadków jesteśmy zmuszeni do napisania własnego kodu.
  • Opcjonalne jest wykorzystanie wyszukiwarek internetowych, które często zwracają duże ilości informacji o testowanej witrynie, z uwzględnieniem plików, które w założeniu miały być plikami ukrytymi.

Kolejnym problemem jest sposób generowania danych. Nie możemy polegać na pełnej losowości i przekazywaniu dowolnych danych do testowanego programu – takie postępowanie w znacznym stopniu zmniejszyłoby wydajność (chociaż prędzej czy później cel zostałby osiągnięty). Aby dobrze wykorzystać potencjał tkwiący w fuzzingu, dane które generujemy muszą być oparte na z góry ustalonym wzorcu, ale ich struktura musi zmieniać się w sposób losowy. Znaczy to mniej więcej tyle, że w zależności od rodzaju testowanej podatności musimy generować dane, które nawiązują do struktury popularnych payload’ów, ale nie są to wartości ustalone „na sztywno” np. w zewnętrznym pliku. Jeżeli np. testujemy aplikację pod kątem występowania błędów typu SQL Injection to naszym wzorcem będzie np. payload ‘or 1=1--, który możemy modyfikować w sposób losowy dodając kolejne słowa kluczowe SQL’a czy wildcard’y.

Ostatni problem projektowy jest najtrudniejszy do rozwiązania i obecnie w środowisku związanym z bezpieczeństwem komputerowym  trwają zaawansowane badania, które pozwoliłyby na jego wyeliminowanie. Problem ten polega na rozróżnieniu reakcji aplikacji webowej będącej wynikiem wystąpienia błędu od reakcji występującej przy wprowadzeniu poprawnych danych. Na chwilę obecną fuzzery wykorzystują głównie heurystykę – przeszukiwanie zwracanych danych pod kątem występowania błędów generowanych przez bazy danych, serwery czy interpretery a także występowania wprowadzanych wartości w postaci niezmienionej (przydatne podczas wykrywania np. XSS). Stosuje się także metody czasowe, znane chociażby z wykrywania błędów typu Blind SQL Injection.

Jednak co zrobić gdy aplikacja nie zwraca jednoznacznych komunikatów o zaistniałym błędzie? Np. gdy przekażemy parametr, który pozwoli nam ominąć autoryzację i uzyskamy dostęp do panelu administratora lub gdy strona podatna jest na Blind SQL Injection? Jak odróżnić zwracane wyniki od standardowych, poprawnych danych zwracanych w większości przypadków? Niewątpliwie jest to problem, który nie doczekał się do tej pory ujednoliconego i najlepszego rozwiązania. Obecnie trwają prace nad wykorzystaniem analizy semantycznej oraz algorytmów genetycznych, które byłyby wstanie wykrywać nawet minimalne zmiany w zachowaniu aplikacji webowej (a dokładniej w strukturze zwracanych przez nią danych) i jednoznacznie określać czy wystąpił błąd.

Na chwilę obecną nie ma w pełni funkcjonalnego fuzzera wykorzystującego algorytmy genetyczne (mam nadzieję, że mój autorski fuzzer Devvv będzie pierwszym tego typu rozwiązaniem?) . Powstanie takich narzędzi z pewnością ułatwi pracę pentesterom, ale także dość szybko doprowadzi do kompromitacji ogromnych ilości stron, na których występują podatności…

WFuzz – fuzzer w praktyce

W artykule poruszyłem dużą liczbę zagadnień, które w większości były głównie teoretycznymi dywagacjami. Nadszedł jednak czas na praktykę. Poniżej chciałbym zaprezentować jeden z ciekawszych fuzzerów webowych o nazwie WFuzz. Program stworzony jest przez organizację Edge-security i można pobrać go ze strony http://www.edge-security.com/wfuzz.php.

WFuzz cechuje się kilkoma ciekawymi możliwościami:

  • Testowanie aplikacji pod kątem występowania takich podatności jak XSS, SQL Injection, LDAP Injection
  • Wykorzystanie słowników lub zakresów wartości (np. a-z, 1-100) w celu wygenerowania danych
  • Wsparcie dla wielowątkowości
  • Wsparcie dla PROXY
  • Implementacja wielu metod kodowania danych (m.in. SHA1, MD5, UTF8)
  • Rekurencyjne skanowanie katalogów
  • Intuicyjna obsługa
  • Możliwość fuzzingu plików cookie
  • Obsługa uwierzytelnienia (Ntlm, Digest,Basic)

 

Wfuzz - menu

Ilustracja 1: WFuzz menu

Obsługa WFuzz nie wymaga od użytkownika większego wysiłku. W większości wypadków wystarczy określić miejsce w adresie URL, które ma przyjmować generowane dane (można tego dokonać za pomocą słowa kluczowego FUZZ lub opcji -V) oraz źródło danych (dynamiczne generowanie lub predefiniowany plik tekstowy). Daje nam to możliwość wygenerowania swojego pliku źródłowego i wykorzystania go w WFuzz.

Przykładowe wywołanie WFuzz wygląda następująco:

wfuzz.py -z file -f wordlists/Injection/SQL.txt -V allvars http://www.example.com/users.php?id=1&akcja=1

Wywołanie to powoduje, że wszystkie parametry przekazywane do pliku users.php (id oraz akcja) będą podlegać testom przy wykorzystaniu wartości zdefiniowanych w pliku SQL.txt.

Wfuzz - run

Ilustracja 2: Przykład działania WFuzz

Na stronie domowej programu WFuzz można znaleźć ciekawe przykłady, które wyśmienicie ilustrują sposób korzystania z aplikacji. WFuzz mogę śmiało polecić wszystkim osobom mającym związek z bezpieczeństwem aplikacji webowych, bo jak twierdzą twórcy programu, jest to aplikacja od pentesterów dla pentesterów :)

Obrona przed fuzzingiem

Fuzzery można powstrzymać poprzez restrykcyjną walidację danych wejściowych kierowanych do aplikacji. Aby dane wejściowe zostały przyjęte muszą spełniać określone wymagania (odpowiednia długość, odpowiednie wartości alfanumeryczne wchodzące w skład przesyłanych danych, odpowiednia struktura). Źle zbudowany zbiór danych jest pomijany. W przypadku fuzzingu ważna jest także wczesna walidacja i odrzucanie niepoprawnych danych możliwie najwcześniejszym etapie.

Podsumowanie

W pewnych okolicznościach wymagane jest stworzenie własnego fuzzera, który będzie dostosowany do konkretnego, specyficznego problemu. Postępowanie zgodnie z regułami tworzenia tego typu oprogramowania i odpowiednie podejście do problemów projektowych pozwoli na łatwiejsze ukończenie projektu. Należy jednak pamiętać, że w większości wypadków możemy skorzystać z aplikacji dostępnych już w Internecie.

Więcej informacji

 O autorze

Piotr Łaskawiec

Konsultant d/s Bezpieczeństwa
Securitum

piotr.laskawiec@securitum.pl

Fuzzing jest ciągle ewoluującą metodą wykrywania potencjalnych luk w bezpieczeństwie, a nowe narzędzia oraz techniki fuzzingu pojawiają się w bardzo krótkich odstępach czasowych. Osobom zainteresowanym polecam regularnie śledzić poniższe źródła informacji.

Strony internetowe:

Jeżeli zamierzamy poznać podstawy fuzzingu oraz przyjrzeć się metodom tworzenia własnych fuzzerów - polecam niniejsze książki.

Książki:

  • Fuzzing for Software Security Testing and Quality Assurance
  • Fuzzing: Brute Force Vulnerability Discovery
  • Open Source Fuzzing Tools

 

Przydatne informacje? Polub nas na facebooku.

Nawigacja
 
Darmowy magazyn o ITsec

zine
Subskrybuj RSS:
RSS