Preorder drugiego tomu książki sekuraka: Wprowadzenie do bezpieczeństwa IT. -15% z kodem: sekurak-book

Kolejny XSS w www.google.com (Custom Search Engine)

06 marca 2015, 13:55 | Teksty | komentarzy 6
W tym artykule opiszę kolejny błąd XSS znaleziony niedawno w domenie www.google.com. Tym razem jest to działający wyłącznie w Internet Explorerze reflected XSS przez nagłówek Host.

Błąd został znaleziony w Custom Search Engine (CSE). Jest to usługa uruchomiana przez Google w 2006 roku, pozwalająca na spersonalizowanie strony wyszukiwarki i ograniczenie zakresu wyszukiwania na przykład tylko do własnej domeny.

Internet Explorer i manipulacja nagłówkiem Host

Opisywany poniżej błąd w Internet Explorerze został odkryty przez Siergieja Bobrowa, znanego pod pseudonimem Black2Fan. Zgłoszony został do Microsoftu w marcu 2013, kiedy też MS zapewnił, że błąd zostanie poprawiony w kolejnej wersji IE. W międzyczasie jednak pojawił się IE11, gdzie problem nadal występuje.

Internet Explorer ma bardzo specyficzne zachowanie związane z interpretacja nagłówka Location w przekierowaniach. Prowadzi to do niespotykanej w innych przeglądarkach możliwości manipulacji nagłówkiem Host.

Przypomnijmy sobie, jak standardowo wygląda odpowiedź serwera z przekierowaniem.

HTTP/1.1 302 Found
Date: Fri, 06 Mar 2015 08:30:23 GMT
Server: Apache/2.2.22 (Debian)
X-Powered-By: PHP/5.4.36-0+deb7u3
Location: http://example.com/login.php
Vary: Accept-Encoding
Content-Length: 0
Connection: close
Content-Type: text/html

Najistotniejsza jest linia 5 – z nagłówkiem Location, bowiem znajduje się w niej informacja dla przeglądarki pod jaki zasób ma wysłać kolejne żądanie.

Analiza zachowania IE wskazuje na to, że ta przeglądarka buduje kolejne żądanie umieszczając w nagłówku Host wszystko to, co znajduje się pomiędzy http:// a kolejnym znakiem slasha (/) lub końcem linii. W powyższym przypadku byłoby to example.com. Wygląda to jak zupełnie prawidłowe zachowanie. Proponuję jednak małą zagadkę: co zrobi Internet Explorer, gdy otrzyma poniższą odpowiedź?

HTTP/1.1 302 Found
Date: Fri, 06 Mar 2015 08:35:32 GMT
Server: Apache/2.2.22 (Debian)
X-Powered-By: PHP/5.4.36-0+deb7u3
Location: http://example.com%2flogin.php
Vary: Accept-Encoding
Content-Length: 0
Connection: close
Content-Type: text/html

Znak / został zamieniony na jego reprezentację w URL-encodingu %2f. W zasadzie przeglądarka nie powinna wykonać żadnego żądania w odpowiedzi na to przekierowanie, gdyż wartość nagłówka Location jest wyraźnie niepoprawna. Tak zachowują się inne popularne przeglądarki (Chrome, Firefox). Internet Explorer z kolei wysyła kolejne żądanie – w dodatku o całkiem ciekawej treści.

GET /login.phphp/ HTTP/1.1
Accept: text/html, application/xhtml+xml, */*
Accept-Language: pl-PL
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko
Accept-Encoding: gzip, deflate
Host: example.com/login.php
DNT: 1
Connection: Keep-Alive
Cache-Control: no-cache

Wow! Okazało się, że IE w nagłówku Host umieścił URL-zdekodowaną formę ciągu znaków pobranego wcześniej z nagłówka Location! Ponadto „dziwnie” wypełnił pierwszą linię żądania – bo skąd wzięło się tam login.phphp skoro nigdzie nie było takiego stringa w żądaniu? Z opisu umieszczonego niegdyś na stronie odkrywcy błędu wynika, że IE nakłada na siebie dwie postaci ścieżki zapytania: postaci przed wykonaniem URL-decode i po jego wykonaniu (Rys 1.).

Rys 1. Sposób budowania ścieżki przez IE

Rys 1. Sposób budowania ścieżki przez IE

Oczywiście błąd pozwalający na wrzucanie dowolnych ciągów znaków do nagłówka Host możemy wykorzystać do wykonania XSS-a jeżeli jest on na stronie gdzieś przepisywany bez enkodowania.

Podsumowując: jeśli wyślemy odpowiedź http z nagłówkiem Location: http://example.com%2F<script>alert(1)<%2fscript> i wartość tego nagłówka zostanie gdzieś przepisana w odpowiedzi – mamy XSS-a.

W praktyce jednak możemy spodziewać się, że serwery będą odpowiadały kodem 400 Bad Request, ze względu na fakt, iż taki nagłówek Host jest wyraźnie niepoprawny (Rys 2.).

Rys 2. Serwer odpowiada kodem 400 na "dziwny" nagłówek Host

Rys 2. Serwer odpowiada kodem 400 na „dziwny” nagłówek Host

Manipulacja nagłówkiem Host w serwerach Google

Serwery Google, podobnie jak pokazałem na Rys 2. nie lubiły, gdy wysyłało im się znaki niealfanumeryczne w nagłówku Host. Zacząłem szukać możliwości na obejście tego problemu. Rozwiązaniem okazały się numery portów. Jak wiadomo, po nazwie hosta można dodać dwukropek wraz z numerem portu, np. mail.google.com:1024. Serwery Google nie walidowały wartości znajdujących się po dwukropku, mogłem więc dopisać tam cokolwiek chciałem. Od razu udało mi się znaleźć kilka miejsc, gdzie nagłówek Host był przepisywany na stronie. Niestety – z enkodowaniem ;)

Rys 3. Wstrzyknięcie własnych znaków do nagłówka Host i odpowiedź Gmaila

Rys 3. Wstrzyknięcie własnych znaków do nagłówka Host i odpowiedź Gmaila

Potrzebowałem więc odnaleźć miejsce, w którym owo enkodowanie nie będzie wykonywane. Zanim jednak do niego przejdę, opiszę jeszcze jedno zachowanie serwera Google’a, które było mi potrzebne do wykorzystania podatności.

Serwery Google i średnik w ścieżce

Sztuczka opisana w tym rozdziale była mi potrzebna do obejścia filtra XSS-owego z Internet Explorera (więcej o nim jeszcze później).

Serwery Google domyślnie normalizują ścieżkę wysyłaną w zapytaniach. Na przykład, żądanie GET /test/../test2 HTTP/1.1 nie zostanie obsłużone przez serwer aplikacyjny, tylko wpierw nastąpi przekierowanie do ścieżki znormalizowanej, a więc /test2 (Rys 4.).

Rys 4. Normalizacja ścieżki przez serwer Google

Rys 4. Normalizacja ścieżki przez serwer Google

Okazuje się jednak, że to zachowanie można „wyłączyć” dodając znak ; w ścieżce. Serwer najwyraźniej kończy interpretacje ścieżki na średniku (traktując średnik jako separator tzw. path parameters) i za nim można umieścić już dowolny ciąg znaków. Przykładowo, dla żądania GET /test/;/../test2 HTTP/1.1 serwer nie odpowie już przekierowaniem, ale błędem 404 – co dowodzi, że próbował po prostu wykonać zapytanie dla tej ścieżki bez normalizacji (Rys 5.).

Rys 5. Brak przekierowania dla ścieżki ze średnikiem

Rys 5. Brak przekierowania dla ścieżki ze średnikiem

XSS w Google CSE

Przejdźmy wreszcie do właściwego XSS-a w Google Custom Search Engine. Było to jedyne miejsce, w którym udało mi się znaleźć przepisywanie nagłówka Host bez enkodowania (Rys 6.)

Rys 6. Nagłówek Host przepisywany bez enkodowania

Rys 6. Nagłówek Host przepisywany bez enkodowania

Sposób kolorowania kodu przez Burpa wprowadza w błąd. W rzeczywistości kod skryptu znajduje się poza tagiem <textarea> oraz komentarzem HTML i zostanie wykonany przez przeglądarkę.

Przygotowałem więc stronę, która odpowiadała następującym przekierowaniem:

HTTP/1.1 302 Found
Server: Apache/2.2.22 (Debian)
Location: https://www.google.com%3a443%2fcse%2ftools%2fcreate_onthefly%3b%3c%2ftextarea%3e%3cscript%3ealert(1)%3c%2fscript%3e

Oczekując, że w kolejnym żądaniu zostanie wysłany nagłówek Host: www.google.com:443/cse/tools/create_onthefly;</textarea><script>alert(1)</script>. W istocie ten nagłówek został wysłany, ale IE był czujny… (Rys 7.)

Rys 7. Filtr XSS-owy z IE blokuje wykonywanie skryptu

Rys 7. Filtr XSS-owy z IE blokuje wykonywanie skryptu

Musiałem zatem zastosować sztuczkę, o której pisałem wspomniałem wcześniej w tekście. Sztuczka ta była też opisywana przez Black2Fana. Filtr XSS-owy z IE porównuje zawartość paska adresu z tym, co znajduje się na stronie. Jeżeli wykryje, że skrypt, który ma zostać wykonany, znajduje się w adresie – odrzuca je jako próba ataku XSS. Okazuje się jednak, że można to porównanie łatwo oszukać stosując wielokrotnie ciąg znaków ../ po średniku. Dzieje się tak dlatego, że IE sam normalizuje ścieżkę, którą wyświetla w pasku adresu. Oznacza to, że gdyby w pasku adresu miało się znaleźć http://example.com/;<script>alert(1)</script>/../../, to IE zostawi tam tylko http://example.com/ i filtr XSS-owy nie będzie już „widział”, że złośliwy skrypt został wysłany w adresie.

Ostatecznie utworzyłem stronę, która odpowiadała nagłówkiem:

Location: https://www.google.com%3a443%2fcse%2ftools%2fcreate_onthefly%3b%3c%2ftextarea%3e%3csvg%2fonload%3dalert%28document%2edomain%29%3e%3b%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f

(gdzie wartość dekoduje się do Location: https://www.google.com:443/cse/tools/create_onthefly;</textarea><svg/onload=alert(document.domain)>;/../../../../../../../../../../../../../../)

Zaś wynik wykonania tego skryptu możecie zobaczyć na filmiku poniżej:

Kalendarz

  • 2015-01-27 (01:12) – zgłoszenie błędu do Google,
  • 2015-01-27 (16:03) – potwierdzenie błędu przez członka Google Security Teamu,
  • 2015-02-25 – potwierdzenie, że błąd został naprawiony,
  • 2015-03-06 – publikacja na Sekuraku.

Podsumowanie

W artykule pokazałem XSS-a w domenie www.google.com, który wykorzystywał znany od kilku lat problem w Internet Explorerze pozwalający na manipulację nagłówkiem Host. Ponadto musiałem znaleźć sposób, by dało się go wykorzystać na serwerach Google (poprzez numer portu) oraz obejście filtra XSS-owego.

–Michał Bentkowski, prowadzi bloga, pentester w Securitum.

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



Komentarze

  1. bug bounty ile wyniosło ? :)

    Odpowiedz
  2. marcin

    Może warto byłoby zgłosić jeszcze do Microsoftu? Niech poprawią filtr XSS i to dziwne zachowanie.

    Odpowiedz
  3. Odpowiedz
  4. Jack

    Gratuluję wspaniałej pracy autora:) Bardzo ciekawy artykuł i bardzo zrozumiały opis problemu. Oby więcej takich postów :)

    Odpowiedz
  5. Ibrahim

    Amazing find and I believe it worth more than $5K. I would be extremely thankful if you can translate this to English :) … Google translate isn’t bad but I there are a lot of stuff missing :S

    Odpowiedz

Odpowiedz