Bezpieczeństwo HTML5 – podstawy (część 2.)

21 marca 2013, 17:00 | Teksty | komentarze 2
Tagi:
: zin o bezpieczeństwie - pobierz w pdf/epub/mobi.
Z tekstu dowiesz się:

  • Czym jest Same Origin Policy i jakie sprawia problemy.
  • Jakie niebezpieczeństwa grożą aplikacjom napisanym w HTML4 w dobie HTML5.
  • Dlaczego najmniejsze wstrzyknięcie może okazać się krytyczną dziurą bezpieczeństwa dzięki nowym interfejsom HTML5.
  • W jaki sposób historia użytkownika może trafić w ręce cyberprzestępców i jak może zostać wykorzystana.

Tekst jest kontynuacją artykułu:

Bezpieczeństwo HTML5 – podstawy (część. 1.)

 

Same Origin Policy

1.  Fundamentalny mechanizm bezpieczeństwa przeglądarki

Same Origin Policy, w skrócie SOP, lub reguła tego samego pochodzenia to pomysł wprowadzony w 1995 roku do Netscape Navigatora jako pewnego rodzaju zabezpieczenie Javascript. SOP uniemożliwia dwóm osobnym kontekstom Javascript modyfikacji swoich drzew DOM. Dzięki temu strona Agresora aggressive.com nie może modyfikować DOM strony Banku bank.com, w sytuacji kiedy np. te dwie strony są otwarte w kartach przeglądarki.

Powyższa sytuacja jest dość jasna. Jednak niekiedy chcemy, aby skrypty z jednego kontekstu modyfikowały inny kontekst (np. gdy na jednej stronie mamy dwie ramki i chcemy, aby akcje z jednej ramki oddziaływały na inną). Javascript w każdej ramce jest osobnym kontekstem, mimo tego może on modyfikować drzewo DOM ramki obok. Dlaczego w tym przypadku jest to możliwe, a w poprzednim nie?

Reguła Same Origin Policy odnośnie JS DOM mówi, że dwa konteksty mogą modyfikować DOM tylko wtedy, gdy oba mają takie same pochodzenie (ang. origin).

Pochodzenie to trzy właściwości:

  • protokół,
  • host,
  • port.

Gdy dwa konteksty JS mają to samo pochodzenie, wtedy mogą modyfikować swoje DOM. Strona Agresora ma inny host niż strona Banku, więc nie może modyfikować jej treści.

Regułę SOP łatwo można zrozumieć analizując poniższą tabelę, w której reguła SOP względem strony http://www.example.com/dir/page.html spełniona jest tylko w dwóch pierwszych przypadkach:

img4

2. SOP w dobie HTML5

Idea reguły tego samego pochodzenia została przytoczona nie bez powodu. W dobie HTML5, kiedy korzysta się z zasobów pochodzących z wielu różnych źródeł, SOP staje się jednocześnie zbawieniem i przekleństwem. Z jednej strony, jest to mechanizm skutecznie chroniący każdą stronę internetową, z drugiej – ogranicza developerów, którzy chcą np. asynchronicznie pobrać zasób z innej domeny.

Dlaczego to takie trudne? Ponieważ trudno określić obecnie, gdzie dana strona się zaczyna, a gdzie kończy. Aby sobie to uświadomić, wystarczy odpowiedzieć sobie na pytanie: które z poniższych stron są zaufane, a które nie?

bank.com ; login.bank.com ; aggressor.bank.com ; friend-bank.com ; evil-bank.com

Sytuacja zaczyna robić się coraz bardziej skomplikowana, a do tej pory omawiany był wyłącznie SOP dotyczący DOM JS. Jak interpretować SOP względem np. ciasteczek, które z definicji nie mają protokołu i portu, a wartość domeny mogą mieć pustą? Jak się ma sprawa z zasobami Flash, Silverlight czy Java? No i jak do tego wszystkiego ma się AJAX?

Jak widać SOP dzisiaj wcale nie jest prostym mechanizmem. Jedno jest pewne – zabezpieczenie to pojawia się praktycznie w każdym elemencie technologii HTML i Javascript i trzeba mieć świadomość, że ono istnieje.

W kontekście bezpieczeństwa HTML5 omówimy między innymi błędy takie jak Cross Domain Content Inclusion czy Cross Origin Request Security (CORS), które wynikają z niewiedzy dotyczącej SOP. Ale najpierw spójrzmy na prostsze luki webaplikacji HTML5, mając już ogólne pojęcie o problematyce reguły tego samego pochodzenia.

 

Ataki HTML Future Proof

1.  Zagrożenia dla aplikacji HTML4

Temat bezpieczeństwa HTML5 zaczniemy od badania stron napisanych w starym HTML4. Tak, to nie pomyłka. Okazuje się, że wprowadzenie nowej technologii, która jest kompatybilna wstecz może spowodować, że starsze strony staną się podatne na nowe niebezpieczeństwa. Dlaczego tak się dzieje?

Powodem jest zazwyczaj niedbałość programistów, którzy napisali niebezpieczny kod niedający o sobie znać przez kilka lat. Do takich błędów można przede wszystkim zaliczyć różnego rodzaju filtry (np. anty-XSS) działające na tzw. blacklistach. Kilka lat temu programista nie był wstanie zdefiniować listy zabronionych tagów/atrybutów, które pojawią się w przyszłości (w HTML5, HTML6…). Takie podatności możemy nazwać atakami Future Proof.

Do takich sytuacji oczywiście nie doszłoby, gdyby programista zdefiniował listę dozwolonych tagów, czyli tzw. whitelistę. Na razie jednak skupmy się na tym, jak HTML5 potrafi pomóc w ominięciu filtrów w celu wstrzyknięcia złośliwego kodu.

2.  Nowe atrybuty i zdarzenia HTML5

Specyfikacja HTML5 wprowadza wiele nowych tagów, atrybutów i zdarzeń.

Z perspektywy wstrzyknięcia złośliwego kodu szczególnie interesujące są poniższe atrybuty rozszerzające możliwości pola input:

  • autofocus,
  • formaction,
  • formenctype,
  • formmethod,
  • formtarget,
  • pattern.

Również niektóre nowe zdarzenia formularzy form mogą znacznie ułatwić wstrzyknięcie kodu:

  • onformchange,
  • onforminput,
  • oninput.

Warto też wspomnieć o następujących zdarzeniach:

  • onerror,
  • onunload,
  • onscroll.

3.  Omijanie blacklist HTML4

­Załóżmy, że testujemy stronę, w której co prawda widzimy szansę na wstrzyknięcie kodu (XSS), ale filtr jest dla nas na tyle nieprzyjazny, że nie potrafimy wykonać wrogiego skryptu. Treść zwracanego kodu HTML w badanej webaplikacji jest następująca:

Niech pole wpisywania komentarzy będzie oparte na blacklistach i wycina wszystkie znane webmasterowi tagi/atrybuty z wyjątkiem dozwolonych (b, i, img).

Od razu widać tutaj niebezpieczne podejście. Mimo wszystko często się okazuje, że takie blacklisty (które wykorzystują np. wyrażenia regularne) bardzo ciężko ominąć. Widzimy na przykład, że po dodaniu komentarza:

jesteśmy w stanie uciec z kontenera div, ale nie potrafimy dodać złośliwego kodu:

Gdy zmienimy nazwę użytkownika np. na:

filtr również utrudni nam atak:

Metod, które doprowadziły do poprawnego wstrzyknięcia, jest wiele. Tutaj skupmy się jednak na nowościach HTML5.

Zacznijmy od tagów multimedialnych, czyli w naszym wypadku img. W HTML5 img obsługuje zdarzenie onerror, które zostanie wywołane np. w momencie, gdy obrazek nie będzie mógł być załadowany. Jeśli więc w polu komentarza wpiszemy następującą treść:

pomyślnie wykonamy wstrzyknięcie, ponieważ blacklista sprzed paru lat nie mogła posiadać wpisu onerror:

Podobnie sytuacja wygląda, gdy zmienimy nazwę użytkownika:

wtedy również uda nam się wykonać złośliwy kod:

img5

Oczywiście w celu omijania filtrów anty-XSS możemy testować różne atrybuty HTML5. Ciekawym pomysłem jest np. zastosowanie kombinacji onscroll oraz autofocus, która bardzo często prowadzi do automatycznego wykonania skryptu w błędnie wypełnionych polach textarea lub kontenerach takich jak div. Autofocus przenosi kursor użytkownika od razu do danego pola, przez co skrypt wykonuje się bez jakiejkolwiek akcji ofiary (czyli ofiara nie musi wykonać scrolla).

 img6

Atrybuty takie jak formaction, formmethod, formtarget oraz formenctype pozwalają zmieniać zachowanie formularzy. Dotychczas wszystkie wartości pól między znacznikami <form></form> były wysyłane pod adres wskazany w atrybutach form action/method/target itp. Obecnie istnieje możliwość przedefiniowania pojedynczego pola input, aby zachowywało się ono w odmienny sposób. Jest to bardzo przydatne, gdy mamy do czynienia np. z formularzem z wieloma przyciskami. Do każdego możemy przypisać osobny formaction, a reszta atrybutów zostanie odziedziczona z elementu nadrzędnego form.

Taka wygoda niesie ze sobą spore zagrożenie. Najmniejsza możliwość wstrzyknięcia nawet w nieistotnym formularzu może doprowadzić do wykonania wrogiej akcji w całkowicie innym miejscu strony. Wystarczy, że dodamy do pola input właściwość formmethod=”post”, formaction=”/delete”, co pozwoli na wykonanie zupełnie innej akcji, niż została zdefiniowana w bloku <form>. W pewnym sensie przypomina to atak CSRF, ponieważ użytkownik wykonuje inną akcję niż ta, której się spodziewa.

Warto też wspomnieć o właściwości pattern, która jest niczym innym jak wyrażeniem regularnym sprawdzanym podczas wprowadzania danych do pola input. W ekstremalnych przypadkach kontrola tej właściwości może spowodować atak DoS, zawieszając przeglądarkę użytkownika. Jest to szczególnie niebezpieczne przy atakach Stored XSS, które uruchamiają wstrzyknięcie wielu użytkownikom serwisu.

 

Ataki na historię

1.  History API

HTML5 to nie tylko nowe znaczniki, dzięki którym mamy dostęp do nowych kontrolek. Nowy HTML to wiele powiązanych technologii – w szczególności nowych API Javascript. History API jest właśnie taką nowością.

History API ma na celu zwiększenie możliwości zarządzania historią przeglądarki z poziomu skryptu. Z punktu widzenia bezpieczeństwa intefejs ten posiada kilka ciekawych metod.

Pierwszą z nich jest history.pushState(), przy pomocy której możemy wprawdzie ustawić adres w pasku przeglądarki na dowolny inny, jednak na taki, który spełnia zasadę Same Origin Policy względem skryptu. Możemy więc zmienić adres paska adresu na stronie http://vizzdoom.net/tags/html5 na http://vizzdoom.net/i/<3/you (czyli nawet na taki, który nie istnieje), a nie będziemy mogli już zmienić adresu na http://sekurak.pl (SOP nie spełniony – vizzdoom.net != sekurak.pl).

Podobną funkcją do history.pushState() jest history.replaceState(). Działa ona identycznie z tym wyjątkiem, że zamiast dodawania nowego wpisu w historii przeglądarki (pushState), zastępuje aktualny wpis.

Obie funkcje należy wywoływać w następujący sposób:

history.pushState (any data, DOMString title, optional DOMString url)
history.replaceState (any data, DOMString title, optional DOMString url)

  • data – dane obiekty, które mogą być odczytane w skrypcie (JSON),
  • title – tytuł strony, który ma być widoczny w historii przeglądarki (String, część przeglądarek ignoruje to pole),
  • url – adres wynikowy, który ma być widoczny w pasku przeglądarki (String, uwaga na SOP).

Ciekawe są również dwa nowe zdarzenia związane z nowym History API. Zdarzenie window.onpopstate jest wywoływane, gdy jakikolwiek wpis historii zostanie zmieniony. Stanie się tak, gdy np. powrócimy do poprzedniej strony lub użyjemy funkcji pushState/replaceState.

Drugim zdarzeniem jest window.onHashChange. Jest ono wywoływane, gdy na stronie zmieni się wartość występująca po znaku hash w pasku adresu. Zmiana takiego URL-a nie powoduje przeładowania strony i w połączeniu z nowym zdarzeniem programiści mają wygodną możliwość wykonywania responsywnych akcji.

Poznaliśmy już nowy interfejs. Poznajmy teraz jego możliwości w ataku na użytkowników przeglądarek wspierających HTML5.

 2.  Phishing i maskowanie ataków Reflected XSS

Nietrudno się domyśleć, że History API może służyć do ataków phishingowych. Pamiętajmy jednak, że ograniczani jesteśmy przez SOP, więc musimy najpierw znaleźć miejsce wstrzyknięcia skryptu na atakowanej stronie. Z uwagi na fakt, że w momencie poprawnie wykonanego wstrzyknięcia możemy zrobić poważniejsze rzeczy niż phishing, ten rodzaj ataku przy pomocy History API nie ma większego sensu.

Ale czy ograniczenie SOP całkowicie zabija sens ataków przez History API? Okazuje się, że nie zawsze. Metody pushState/replaceState bardzo dobrze sprawdzają się w momencie, gdy znajdujemy błąd rodzaju Reflected XSS. Błędy tego rodzaju z natury wykonują się tylko raz, zazwyczaj poprzez otwarcie długiego URL-a przez ofiarę. Link taki może być skrócony, ale uważny użytkownik po wykonaniu payloadu zauważy złośliwy skrypt w pasku przeglądarki.

Aby ukryć fakt wykonania złośliwego skryptu przy ataku Reflected XSS  i pozostawić użytkownika w fałszywym poczuciu niebezpieczeństwa, wystarczy na końcu payloadu dodać wywołanie pushState(). Dzięki temu zamiast następującego paska adresu:

img7

po wykonaniu złośliwego skryptu możemy zamaskować atak Reflected XSS w URI:

img8

Aby zamaskować atak w taki sposób, wystarczy pozbyć się wszystkiego co występuje po znaku zapytania. Przykładowy payload maskującego się GET Reflected XSS przedstawiono poniżej:

 

Ataki na technologie XML

1.  SVG

SVG jest popularnym formatem grafiki wektorowej, w której jakość obrazu nie zależy od rozdzielczości ekranu. Dzięki HTML5 i technologiom pochodnym takim jak SVG, grafika wektorowa może być wyświetlona bezpośrednio w przeglądarkach jako część strony internetowej.

SVG jest skomplikowanym formatem opisanym w XML. W swojej strukturze może zawierać nie tylko opisy kształtów, kolorów i innych elementów kojarzących się z grafiką, ale również daje możliwość używania stylów CSS czy… skryptów JavaScript.

Skomplikowana struktura oraz możliwość wykonywania skryptów stwarza wiele problemów:

  • programiści mogą zapomnieć o wykorzystywaniu filtrów antyXSS w modułach wgrywania obrazków (np. podczas wgrywania awatarów),
  • skrypty zaszyte w SVG są trudno wykrywalne przez różnego rodzaju filtry czy reguły IDS/IPS/WAF,
  • istnieje bardzo mała liczba narzędzi/bibliotek dedykowanych filtrowaniu niebezpiecznych elementów SVG,
  • skomplikowana struktura powoduje, że bardzo często błędy bezpieczeństwa pojawiają się na poziomie przeglądarki internetowej, a nie strony internetowej (jednak te są z reguły szybko poprawiane).

Łatwo zauważyć, że SVG jest idealnym kandydatem do wstrzyknięcia złośliwego kodu JS do webaplikacji. Na szczęście wstrzyknięcia XSS w plikach SVG są kłopotliwe, ponieważ nie zawsze zadziałają one w każdej przeglądarce.

Przyjrzyjmy się kilku uniwersalnym wstrzyknięciom, które mogą zostać użyte przez agresora w celu wykonaniu złośliwego skryptu w popularnych przeglądarkach:

  • <svg xmlns=”http://www.w3.org/2000/svg”>
    <script>alert(1)</script></svg>
  • <svg xmlns=”http://www.w3.org/2000/svg”
    onload=”javascript:alert(1)” ></svg>
  • <svg xmlns=”http://www.w3.org/2000/svg”>
    <g onload=”javascript:alert(1)„></g></svg>
  • <svg xmlns=”http://www.w3.org/2000/svg”>
    <a xmlns:xlink=”http://www.w3.org/1999/xlink”  xlink:href=”javascript:alert(1)>
    <rect width=”1000″ height=”1000″ fill=”white”/></a>
    </svg>

Pierwszy i drugi payload w prosty sposób pozwala wykonać javascript agresora. Tego typu kod jest łatwy do wykrycia, ale trzeba pamiętać, że webdeveloperzy bardzo często zapominają filtrować kod SVG w uploadowanych obrazkach.

Trzeci i czwarty payload jest już bardziej skomplikowany. Wykorzystywany jest tutaj element <g> oraz namespace xlink dla elementu <a>. W obu tych elementach agresor może wykonać pewien kod javascript (w ostatnim przypadku wymagana jest jednak interakcja użytkownika przez kliknięcie linku).

Zobaczmy przykłady kilku ciekawych wstrzyknięć, które wykonują się tylko w wybranych przeglądarkach. Dla przykładu weźmy Operę, która otwiera ogromną liczbę miejsc wstrzyknięć XSS w SVG (w porównaniu do innych przeglądarek). W poniższych trzech przypadkach w przeglądarce Opera zostanie wykonany kod Javascript atakującego:

Agresor może wykonywać skrypty także poprzez właściwości CSS definiowane w samym SVG (jako filtry obrazu). Poniższy kod spowoduje wykonanie javascriptu w przeglądarce Opera 11.60+ oraz 12.0+:

Jak widać, niektóre payloady SVG mogą być skomplikowane i bardzo trudno jest je wychwycić w filtrach antyXSS czy regułach WAF. Skomplikowana struktura XML i trudna obróbka tekstu powoduje wiele problemów.

W jaki sposób bronić się przed złośliwym skryptem zaszytym w pliku SVG? Obecnie jedyną opcją jest rezygnacja z wykorzystywania formatu SVG przez użytkowników webaplikacji. Trzeba zwrócić szczególną uwagę na miejsca takie jak wgrywanie plików – awatarów, zdjęć i im podobnych mediów. Sprawdzajmy zawsze rozszerzenie pliku (zarówno przed, jak i po uploadowaniu) i odrzucajmy format SVG.

Jeżeli jednak logika biznesowa webaplikacji wymaga stosowania plików SVG przez użytkowników, należy w bardzo dokładny sposób filtrować przychodzące grafiki. W momencie pisania artykułu nie istniały jeszcze dopracowane narzędzia, które usuwałyby złośliwy kod z grafik SVG. W zasadzie znany jest tylko jeden projekt, który rzucił rękawicę skryptom w SVG – projekt dr Heidericha o nazwie „SVG Purifier”. Istnieje publicznie dostępna wersja testowa tego narzędzia, w której możemy sprawdzić bezpieczeństwo czyszczenia złośliwych plików SVG.

Przykładów wstrzyknięć XSS poprzez znaczniki SVG jest bez liku. Temat bezpieczeństwa SVG został ciekawie opisany w pracy naukowej „Crouching Tiger – Hidden Payload: Security Risks of Scalable Vectors Graphics”, która jest dobrym rozwinięciem opisanego tutaj tematu. Wiele zawartych w niej metod została opisana przez wspomnianego dr Mario Heidericha. Warto śledzić  jego wystąpienia na różnych konferencjach w obszarze security, na ktorych często porusza temat XSS oraz SVG.

img9

2. Egzotyczny XML i egzotyczne wstrzyknięcia

MathML jest językiem, który może zastąpić formuły TEX/LATEX w celu łatwego renderingu równań matematycznych i elementów wykorzystywanych w formatowaniu dokumentów naukowych. Obsługę formatu można sprawdzić w tym miejscu. Szacuje się, że obecnie wsparcie MathML posiada niemalże 50% przeglądarek internautów. A jak wygląda sprawa bezpieczeństwa HTML? No cóż… podobnie jak w SVG.

Użytkownicy przeglądarki Firefox mogą na przykład zostać ofiarami ataku XSS, gdy atakującemu uda się wstrzyknąć następujący payload w XML (wymagane kliknięcie w napis CLICKME):

Złośliwe skrypty mogą być wstrzyknięte przez agresora dużo prościej, webaplikacja musi jednak zwracać kod XML, czyli np. XHTML. Poniższy payload wykorzystuje XML ATTLIST pozwalający na wykonanie skryptu w przeglądarkach Chrome, Safari, Firefox oraz Opera:

Po raz kolejny widać, że XML jest bardzo niebezpieczną technologią. Za każdym razem, gdy możemy dać użytkownikom możliwość korzystania z mechanizmów, które przetwarzają kod XML, powinniśmy się zastanowić, czy nie możemy zaproponować innego rozwiązania. W przeciwnym wypadku musimy z niezwykłą starannością filtrować kod XML.

MathML, XML-style, WML i wiele innych rozszerzeń wykorzystujących XML sprawia podobne problemy bezpieczeństwa jak opisany w poprzednim paragrafie SVG. We wszystkich tych technologiach możemy szukać ciekawych wstrzyknięć, których nie bylibyśmy w stanie zrobić w prostych webaplikacjach pisanych w dobie HTML4.

 Źródła

O autorze

Adrian Vizzdoom Michalczyk: pasjonat bezpieczeństwa teleinformatycznego od najmłodszych lat, obecnie student wydziału Informatyki Politechniki Śląskiej w Gliwicach.

Czasem programista, czasem gracz papierkowych gier RPG, ale zawsze fascynat klimatów post-apokaliptycznych. W swoim życiu nosił zarówno czarny, jak i biały kapelusz, teraz w wolnym czasie próbuje rozwijać swój kąt Internetu: http://vizzdoom.net.

Spodobał Ci się wpis? Podziel się nim ze znajomymi:



Komentarze

  1. Robi się coraz ciekawiej, nie zawiodłem się ;)

    Odpowiedz
  2. Uprzedzając – w następnej części już nie będzie XSSowania ;)

    Odpowiedz

Odpowiedz