Lis
23

XSS via URL

Czy kiedykolwiek zastanawiałeś się, w jaki sposób dane, wpisane do paska adresu przeglądarki są przez nią traktowane? Zrobimy dziś mały eksperyment, pokazujący pewne zagrożenie z serii ataków Cross-Site Scripting, które związane jest bezpośrednio z URI wprowadzanym przez użytkownika.

Stwórzmy prosty plik PHP, który odpowiada za wyświetlenie interesującego nas elementu: $_SERVER[‚REQUEST_URI’].

<?php
echo $_SERVER['REQUEST_URI'];
?>

Na pierwszy rzut oka powyższy przykład podatny jest na atak typu XSS. Brak jakiegokolwiek enkodowania/escape’owania + możliwość kontroli danych wprost od użytkownika (w końcu to końcowy użytkownik kontroluje to, co wpisuje jako adres URL do przeglądarki). Spróbujmy więc przeprowadzić jakiś prosty PoC:

poc.php?<script>alert(1)</script>

Wszystko wskazuje na to, że nasza przeglądarka w większości przypadków (a tym dlaczego nie we wszystkich przypadkach – za chwilę) powinna wyświetlić uroczy alert(). Okazuje się jednak, że zamiast niego, wyświetla:

/poc.php?%3Cscript%3Ealert(1)%3C/script%3E

Wprowadzony przez nas ciąg znaków poddany został procesowi URL-encode. Potrzebne do przeprowadzenia ataku znaki >< zostały zamienione na odpowiedniki %3E oraz %3C. Dlaczego tak się stało? Czy ma to coś wspólnego ze zmienną $_SERVER? Czas na zapowiedziany eksperyment.

Przygotujmy kilka przeglądarek. Np. Firefox, Chrome i Internet Explorer. Odpalmy narzędzie Wireshark i obserwujmy pakiety HTTP, które przechwycone zostały w momencie odwiedzania powyższego zasobu:

GET /poc.php?%3Cscript%3Ealert(1)%3C/script%3E HTTP/1.1
Host: 127.0.0.1
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:33.0) Gecko/20100101 Firefox/33.0
GET /poc.php?%3Cscript%3Ealert(1)%3C/script%3E HTTP/1.1
Host: 127.0.0.1
Connection: keep-alive
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.111 Safari/537.36
GET /poc.php?<script>alert(1)</script> HTTP/1.1
Accept: text/html, application/xhtml+xml, */*
Accept-Language: pl-PL
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko
Accept-Encoding: gzip, deflate
Host: 127.0.0.1

Okazuje się, że część przeglądarek dokonuje URL-enkodowania jeszcze przed wysłaniem danych do serwera. Innym zachowaniem cechuje się przeglądarka Internet Explorer. Oznacza to, że powyższy alert() wykona się właśnie w tej przeglądarce. Pozostałe (Firefox, Chrome) – jak zaobserwowaliśmy na przechwyconych przez narzędzie Wireshark pakietach – dokonają URL-enkodowania (co w tym przypadku pozwoli zapobiec atakowi XSS).

Poniższy skrypt pozwoli poeksperymentować Wam z różnymi przeglądarkami.

Nie tylko REQUEST_URI

Podobny problem występuje w przypadku nagłówka Referer.

Tym razem, dla zachowania różnorodności, nagłówek Referer otrzymamy w wyniku prostego skryptu JS.

/* index.html */
// (...)
window.location = "xssPoC.html?aaa<>\"bbb";
// (...)
 
/* xssPoC.html */
// (...)
var linkElem = document.createElement('a');
linkElem.href = "xss.html";
document.body.appendChild(linkElem);
linkElem.click();
// (...)
 
/* xss.html */
// (...)
alert(document.referrer);
// (...)

Uruchamiając powyższy kod w różnych przeglądarkach, zauważymy podobną jak w przypadku REQUEST_URI rzecz. Otóż nagłówek Referer, również został poddany URL-enkodowaniu w przypadku przeglądarek Firefox i Chrome, natomiast IE wyświetlił go bez zmian.

Zajmijmy się przypadkiem bezpośrednio z życia wziętym. Stosunkowo dawno temu (kwiecień), polski CERT opublikował narzędzie umożliwiające sprawdzenie, czy nasz klient (w tym przypadku przeglądarka) podatna jest na głośny w tamtych czasach atak Heartbleed – http://www.cert.pl/heartbleed/.

Po kliknięciu w button „Run test” aplikacja wyświetlała wynik testu oraz nagłówki zapytania wysłane do serwera. Jednym z tych nagłówków jest Referer i to on będzie dla nas najbardziej interesujący.

Odwiedzając adres http://www.cert.pl/heartbleed/?test=abc i klikając w przycisk „Run test„, wyświetlony zostanie nagłówek:

Referer: http://www.cert.pl/heartbleed/?test=abc

Wygląda więc na to, że mamy możliwość kontroli nad danymi wyświetlanymi po stronie webaplikacji. Co stanie się, w przypadku wprowadzenia np. takiego adresu:

http://www.cert.pl/heartbleed/?x<h1 onmouseover=window.location='http://google.pl'>aaa

Jak już zapewne wiemy, część przeglądarek dokona URL-enkodowania znaków >< – wtedy nie stanie się nic złego. Problem nastąpi jednak w momencie, gdy użytkownik korzysta z przeglądarki Internet Explorer. Scenariusz ataku może wyglądać następująco.
1. Atakujący nakłania użytkownika korzystającego z przeglądarki IE do odwiedzenia powyższego linku.
2. Użytkownik klika w link „Run test” i czeka na wyniki testu.
3. Po wyświetleniu rezultatu, użytkownik klika w button „Show/Hide advanced information„, pokazujący szczegółowe nagłówki wysłane do serwera.
4. Wśród pokazanych nagłówków znajduje się Referer, którego wartość zawiera tagi html/elementy javascript (<h1> oraz atrybut onmouseover). Z uwagi na brak enkodowania/escape’owania wyświetlanych danych, przeglądarka parsuje przekazane dane do postaci HTML. Użytkownikowi wyświetla się duży napis (z uwagi na <h1>). Kiedy wskaże na niego kursorem (onmouseover), nastąpi przekierowanie do innej domeny (window.location).

Poniżej przedstawiono dwa przykładowe payloady, prezentujące podatność:



Zgłoszony błąd (19.04) poprawiony został bardzo szybko (już 23.04 został załatany). Czas reakcji zasługuje na olbrzymią pochwałę.

  

Dodaj komentarz

*

Audio-CAPTCHA