Niewłaściwy encoding #1
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:
!“#$%25&'()*+,–./:;<=>?@[]^_`{|}~
Na wyjściu natomiast dostaje się coś takiego:
demo 1
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:
demo 1
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('%2561%256c%2565%2572%2574%2528%252f%2578%2573%2573%252f%2529'))+'
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%25; height: 100%25” foo=”
W rezultacie da to następujący kod:
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).
Oryginał tego wpisu dostępny jest pod adresem Niewłaściwy encoding #1
Autor: Paweł Goleń