Testowanie aplikacji internetowych w znacznym stopniu sprowadza się do nudnego testowania poszczególnych parametrów przekazywanych do aplikacji. Oczywiste jest, że w takich sytuacjach człowiek chce sobie ułatwiać życie...
XSS fuzzing, czyli o ułatwianiu sobie życia
Ułatwianie życia w przypadku XSS jest wbudowane choćby w WebScarab zakładka (plugin) XSS/CRLF. Problem w tym, że działa jak chce, a chyba mnie nie lubi, bo w większości przypadków - nie działa. W związku z tym popełniłem własny fuzzer, który w szukaniu XSS ma mnie wspomagać.
A teraz będzie po mojemu...Zasada działania jest bardzo prosta. Na wejściu narzędzie to dostaje cały request (na przykład przeklejony z WebScarab). Kolejnym krokiem jest wybór parametrów, które mają być fuzzowane. Dla każdego fuzzowanego parametru generowany jest request, w którym wartość parametru zastępowana jest ciągiem typu '';!--"<XSS>=&{()}_<id>, gdzie <id> jest unikalnym (w ograniczonym czasie) identyfikatorem.
Po odczytaniu response z serwera sprawdzane jest, czy zawiera wyżej podany pattern (bez fragmentu _<id>). Konkretnie to nawet nie tylko cały pattern, ale również jego podfragmenty. Dlaczego? Bo może się zdarzyć, że encodowana na wyjściu jest tylko część znaków. Czasami wystarcza to, by w konkretnym przypadku XSS nie udało się zrobić... Dla przykładu w jednej aplikacji dość konsekwentnie encodowany był znak ", dzięki czemu nie udało się "uciec" z fragmentu value="wartość". W innym miejscu ta sama wartość była wypisywana bezpośrednio w fragmencie kodu JavaScript, dzięki czemu ładnego XSS udało się zrobić bez wykorzystania znaku ". Swoją drogą to jest doskonały przykład, że encoding musi być interpreter depended. Inaczej znaki są encodowane dla przeciwdziałania XSS (interpreterem jest przeglądarka), a inaczej dla przeciwdziałania sql injection (interpreterem jest baza danych). Co więcej, w przypadku bazy danych encoding musi być zależny od tego, jaka baza jest wykorzystywana! Dlaczego? Dlatego, że na przykład w części baz znak ' jest maskowany w sposób następujący: '', a w części tak: \' (na przykład magic_quotes_sybase w PHP).
Po co ten identyfikator???Po co jest identyfikator? Bywa tak, że wprowadzona wartość jest wypisywana w wielu różnych miejscach aplikacji. Może się zdarzyć więc taka sytuacja, że testowa wartość gdzieś się pojawi, ale ciężko sobie przypomnieć skąd ona się tam wzięła. Jeśli string testowy jest do pewnego stopnia unikalny, w logach można wyszukać miejsce, gdzie został wprowadzony do aplikacji.
Ale ten pattern, to nie jest XSS!Test ten nie sprawdza bezpośrednio XSS, raczej weryfikuje, czy dane otrzymane od użytkownika są encodowane przed wypisaniem na wyjście. Oczywiście, można użyć XSS (Cross Site Scripting) Cheat Sheet (z którego zresztą wykorzystany przeze mnie pattern pochodzi) i testować wszystkie podane tam przykłady. Na chwilę obecną wydaje mi się jednak, że ewentualne dopracowanie XSS w przypadku, gdy już wiem, że prawdopodobnie da się je w tym miejscu zrobić, nie zajmie tyle czasu, by proces ten w pełni automatyzować.
Tokeny...Co może być problemem? Coraz częściej można spotkać w aplikacjach internetowych rozwiązania wymuszające kolejność formatek, chroniące przez wielokrotnym wysłaniem tej samej formatki. Jest to realizowane przez umieszczenie w formularzu tokenu, unikalnego dla każdej wygenerowanej strony. W przypadku, gdy wartość tokenu nie jest zgodna z oczekiwaniami (nie był wygenerowany, został już wykorzystany), formatka nie jest przetwarzana. Oczywiście, zawsze można napisać rozszerzenie, które najpierw pobiera stronę z fuzzowaną formatką, wyszukuje w niej unikalny token, uzupełnia jego wartością parametr i... Ale na razie mi się nie chce :)