Pierwsze wyjaśnienie odnośnie ćwiczeń z nieprawidłowego encodingu. Na pierwszy ogień pójdzie pierwsze miejsce, w którym wprowadzone dane są wypisywane. Jako string testowy wykorzystam następujący zestaw znaków:
!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~
Na wyjściu natomiast dostaje się coś takiego:
<a href="#" onclick="javascript:doStuff('!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~')">demo 1</a>
Jak widać, specjalnie traktowane są tylko nieliczne znaki, które są przekształcane w następujący sposób:
& -> &
< -> <
> -> >
Byłoby to zabezpieczenie wystarczające, gdyby dane te były wypisywane w kontekście HTML. Problem w tym, że nie są. Są wypisywane w kontekście atrybutu HTML, który, tak się dodatkowo składa, zawiera kod JavaScript.
Jak w takim przypadku uczynić ZŁO? Sposobów jest wiele. Pokażę dwa proste przykłady. Jak ktoś chce magii, proszę bardzo: http://blog.kotowicz.net/.
Pierwszy przykład jest trywialny, payload, który go demonstruje, wygląda następująco:
'+alert(/xss/)+'
W kodzie strony przypadek wygląda następująco:
<a href="#" onclick="javascript:doStuff(''+alert(/xss/)+'')">demo 1</a>
W chwili, gdy ofiara kliknie na tak przygotowany link, w pierwszej kolejności wyświetli się alert. Zamiast tej funkcji można umieścić choćby payload oparty na funkcji eval z dodatkowym unescape. Na przykład mogłoby wyglądać to tak:
'+eval(unescape('%61%6c%65%72%74%28%2f%78%73%73%2f%29'))+'
Ten powyższy payload dedykuję Wysokiej Klasy Specjalistom, którzy "rozwiązali" problem z XSS poprzez zablokowanie słowa alert. W mojej bezgranicznej złośliwości zrobiłem dokładnie takiego samego PoC co w oryginalnym raporcie, właśnie z użyciem tego typu "wyrafinowanych sztuczek". Swoją drogą czekam, kiedy zacznie być blokowany mój ulubiony znacznik, mroczne pmq.
Co jest główną wadą wyżej zademonstrowanego sposobu? Z punktu widzenia atakującego oczywiście? Tak, chodzi o to, że ofiara musi kliknąć w ten element. Można jednak nieco zwiększyć swoje szanse na sukces. Tak (i to jest ten drugi sposób):
" onmouseover="alert(/xss/)" style="z-index: 100; position: absolute; top: 0; left: 0; width: 100%; height: 100%" foo="
W rezultacie da to następujący kod:
<a href="#" onclick="javascript:doStuff('" onmouseover="alert(/xss/)" style="z-index: 100; position: absolute; top: 0; left: 0; width: 100%; height: 100%" foo="')">demo 1</a><
Te powyższe dwa przykłady to nie są bynajmniej wszystkie sposoby, na jakie można w tym konkretnym miejscu zrobić kuku. Wystarczająco dobitnie pokazują jednak to, że encoding prawidłowy (lepsze określenie: wystarczający) w kontekście "czystego" HTML nie musi być wystarczający w innym kontekście. Tu - w kontekście atrybutu HTML (drugi przypadek) lub funkcji JavaScript (pierwszy przypadek).
Po pierwszym przykładzie niewłaściwego encodingu, pora na drugi. Dla analogicznego jak w pierwszym przypadku zestawu znaków: !"#$%&'()*+,-./:;?@[\]^_`{|}~ na wyjściu otrzymuje się:
Przesłany: Dec 15, 06:06
Raz, dwa, trzy (to teraz). To make long story short:
Przesłany: Dec 16, 08:24
Pora na zakończenie tematu przykładu z niewłaściwym encodingiem (patrz: #1, #2, #3 i #4). Ponownie, by nie przeciągać, dla tradycyjnego zestawu znaków testowych otrzymujemy: doStuff('!\\"#$%&\'()
Przesłany: Dec 17, 15:15
Pokazanie przykładów niewłaściwego encodingu mamy za sobą (patrz: #1, #2, #3, #4 i #5). Na koniec przykład: http://bootcamp.threats.pl/lesson09b/, w którym encoding jest realizowany za pośrednictwem ESAPI (konkretnie owasp-esapi-php, jest to jeszcze wersj
Przesłany: Dec 18, 14:47