Konferencja Mega Sekurak Hacking Party w Krakowie – 26-27 października!
Adminie… Czy znamy Twoje grzechy? ;-) Sprawdź!
Konferencja Mega Sekurak Hacking Party w Krakowie – 26-27 października!
Adminie… Czy znamy Twoje grzechy? ;-) Sprawdź!
W niniejszym artykule przedstawiamy kilka podstawowych zasad, których stosowanie pozwala niskim kosztem zwiększyć ogólny poziom bezpieczeństwa aplikacji webowej.
Każda strona HTML powinna zaczynać się od zdefiniowania typu dokumentu (document type/doctype), dzięki czemu przeglądarka wie, w jaki sposób parsować dany dokument. Jeszcze kilka lat temu te deklaracje wyglądały jak „potworki”, np. <!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” „http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”> ; na szczęście standard HTML5 znacząco uprościł składnię i teraz wystarczy zdefiniować <!DOCTYPE html>.
Jeżeli na stronie nie zostanie zdefiniowany żaden doctype, przeglądarki internetowe będą próbowały go zgadywać na podstawie dalszej treści dokumentu. W najgorszym wypadku, może okazać się, że dokument zostanie wyrenderowany w tzw. „quirks mode”, którego celem jest zachowanie kompatybilności wstecznej z wczesnymi czasami sieci web, w których wiele technologii nie było jeszcze ustandaryzowanych. W tym trybie przeglądarki obsługują całą masę starych i przestarzałych konstrukcji składniowych, które mogą prowadzić do nieoczekiwanych XSS-ów lub wycieków danych innego typu. Jednym z bardziej znanych przykładów wykorzystania „quirks mode” do wykonania XSS-a jest użycie go do ominięcia ochrony anty-XSS z frameworka .NET. Linkowany artykuł odnosi się do Internet Explorera 9, jednak nawet w najnowszych wersjach IE nadal możliwe jest wymuszenie „quirks mode” w pewnych warunkach.
Podsumowując: na każdej stronie HTML należy zdefiniować doctype w postaci: <!DOCTYPE html>. Dzięki temu mamy gwarancję, że dokument nie zostanie nigdy wyrenderowany w „quirks mode”.
Jeśli wdrażamy webaplikację, która używana jest w protokole HTTPS i nie powinna nigdy być uruchamiana w HTTP, należy rozważyć wprowadzenie nagłówka HTTP Strict-Transport-Security (HSTS). Jeżeli dla danej domeny zdefiniujemy HSTS, zapewniamy sobie dwa dodatkowe zabezpieczenia przed atakami typu man-in-the-middle:
W definicji nagłówka HSTS wymagany jest parametr max-age określający w sekundach czas ważności dla tego nagłówka. Po upływie tego czasu, nagłówek przestanie obowiązywać i wykonywanie zapytań HTTP dla danej domeny będzie znów możliwe.
Przykład: aby zdefiniować HSTS z ważnością na rok, należy dodawać w odpowiedziach HTTP dodatkowy nagłówek:
Strict-Transport-Security: max-age=31536000
Niezależnie od swojego poziomu złożoności, spora część aplikacji webowych opiera się na zewnętrznych bibliotekach lub frameworkach – takich jak jQuery, Angular, KnockoutJS itp. W celu zmniejszenia ruchu sieciowego na swoich serwerach, często korzysta się z CDN-ów (Content Delivery Network), z których skrypt jest pobierany przez przeglądarkę. Przykładowo: jQuery możemy pobrać bezpośrednio z serwera autorów:
<script src="https://code.jquery.com/jquery-2.2.4.min.js"></script>
Zauważmy, że w ten sposób dajemy zewnętrznemu skryptowi pełny dostęp do drzewa DOM naszej strony. Jeżeli komuś uda się włamać na serwer code.jquery.com i podmienić plik z jQuery (na przykład wrzucając tam exploity na przeglądarki), wówczas i my oberwiemy rykoszetem.
Aby zabezpieczyć się przed takim ryzykiem, wprowadzono mechanizm Subresource Integrity (SRI). SRI pozwala dodać do tagów <script> lub <link> dodatkowy atrybut integrity, w którym podaje się enkodowany w Base64 hash SHA-256, SHA-384 lub SHA-512 dla zewnętrznego pliku. Jeżeli hash z atrybutu nie zgadza się z hashem pobranego pliku, przeglądarka nie wykona takiego pliku.
Aby więc skorzystać z dobrodziejstw SRI, wcześniej podany przykład z jQuery musimy zapisać następująco:
<script src="https://code.jquery.com/jquery-2.2.4.min.js" integrity="sha384-rY/jv8mMhqDabXSo+UCggqKtdmBfd3qC2/KvyTDNQ6PcUJXaxK1tMepoQda4g5vB"></script>
Aby obliczyć właściwą wartość atrybutu integrity dla danego pliku, możemy posłużyć się stroną: https://www.srihash.org/.
Do ciasteczek HTTP możemy dopisać dwie flagi zwiększające ich bezpieczeństwo: HttpOnly oraz Secure.
Flaga HttpOnly pozwala uchronić się przed jednym z najpowszechniejszych skutków ataków XSS, tj. wykradzeniem ciastka sesyjnego (np. JSESSIONID lub PHPSESSID). Typowo atak polegał na tym, że napastnik wyciągał w JavaScripcie zawartość zmiennej document.cookie, którą wysyłał na swój serwer, by następnie przejąć sesję użytkownika. Ciasteczko oznaczone flagą HttpOnly będzie wysyłane w zapytaniach do serwera, nie pojawia się jednak w document.cookie.
Flaga Secure, z kolei przydaje się, gdy mamy aplikację, która może zadziałać zarówno w HTTP, jak i HTTPS. Dzięki niej mamy gwarancję, że przeglądarka nie wyśle danego ciasteczka w ramach połączenia HTTP, a tylko i wyłącznie HTTPS.
Przykładowy nagłówek Set-Cookie z ustawieniem obu flag wygląda następująco:
Set-Cookie: PHPSESSID=dddjg49acm041jd0as; HttpOnly; Secure
Sposób ustawienia tych flag na ciastka sesyjne (jak również ewentualnie na inne ciastka) zależy od konkretnej używanej technologii. Stosowna instrukcja powinna się znaleźć w dokumentacji.
Przeglądarki Chrome oraz Internet Explorer posiadają wbudowany filtr chroniący przed atakami Reflected XSS. Działanie tych filtrów jest koncepcyjnie bardzo proste: sprawdzają one, czy w zapytaniu HTTP pojawiają się tagi HTML-owe lub inne fragmenty kodu JS – oraz czy później ten sam kod znajduje się w odpowiedzi. Jeżeli tak jest, to uznają, że mają do czynienia z atakiem XSS i blokują ten fragment kodu. Innymi słowy, jeżeli dla zapytania pod adres: http://example.com/<img+src=1+onerror=alert(1)>, w odpowiedzi pojawi się gdzieś tag <img src=1 onerror=alert(1)>, to przeglądarki nie dopuszczą do jego wykonania.
Okazuje się jednak, że takie zachowanie filtrów XSS-owych może pozwolić na wykonanie XSS-a w sytuacji, w której inaczej nie było to możliwe! Polecam przejrzeć prezentację japońskiego badacza bezpieczeństwa przeglądarek – Masato Kinugawy, pt. X-XSS-Nightmare.
Zarówno w IE, jak i Chromie istnieje możliwość włączenia innego trybu filtru XSS dzięki nagłówkowi X-XSS-Protection. Poniżej opis możliwych zawartości:
Najbardziej zalecanym trybem pracy jest ten ostatni: pozwala blokować ataki XSS, a zarazem uniknąć ryzyk omówionych m.in. we wspomnianej prezentacji X-XSS-Nightmare.
Nagłówek X-Content-Type-Options przyjmuje tylko jedną możliwą wartość:
X-Content-Type-Options: nosniff
Wyłącza on zgadywanie typu MIME strony przez przeglądarki, pozwala również ochronić się przed atakami polegającymi na dołączaniu plików w innym kontekście niż wskazuje na to ich Content-Type. Przykład: mamy aplikację webową, w której użytkownik może wgrywać obrazki. W innym miejscu tej aplikacji ma ograniczoną kontrolę nad plikiem JavaScript, który jest wykonywany – w związku z czym próbuje wykonać następujący atak:
<script src="http://example.com/uploads/image.png”></script>
Jeżeli użyjemy nagłówka X-Content-Type-Options, takie wykonanie skryptu nie powiedzie się jeżeli Content-type odpowiedzi będzie równy np. image/png. Przeglądarka wyświetli tylko w konsoli błąd, że typ MIME image/png nie pasuje do kontekstu skryptowego.
Nagłówek X-Frame-Options (XFO) został wprowadzony jako odpowiedź na ataki Clickjacking, choć przydaje się również przy ochronie przed innymi, bardziej subtelnymi atakami. Krótko mówiąc, nagłówek ten pozwala ograniczyć listę domen w jakich nasza webaplikacja może być umieszczana w tagach <frame>, <iframe> oraz <object>. Przyjmuje następujące wartości:
Jeżeli nie planujemy na naszej stronie udostępniać widgetów, które muszą być ramkowane na innych stronach, zaleca się ustawić nagłówek XFO z wartością SameOrigin lub Deny.
W artykule przedstawiono kilka podstawowych sposobów na zwiększenie bezpieczeństwa aplikacji webowej. Nie wyczerpuje on jednak całkowicie tematu. Między innymi, na Sekuraku opisywaliśmy nagłówek Public-Key-Pins; warto również zainteresować się nagłówkiem Content-Security-Policy, który pozwala precyzyjnie określić polityki ładowania zasobów dla danej aplikacji.
— Michał Bentkowski, pentester w Securitum
Super artykuł!
Michał, a może jeszcze paragraf o HTTP Access Control (CORS)? Chyba dobrze by pasował w tym towarzystwie :)
Dla ciasteczek można tez ustawić flagę SameSite: https://www.igvita.com/2016/08/26/stop-cross-site-timing-attacks-with-samesite-cookies/
Od razu można też wspomnieć o dwóch nowych nagłówkach, które właśnie są standaryzowane: https://chloe.re/2016/08/19/more-control-with-clear-site-data-and-feature-policy/
No to są już 4 paragrafy do dopisania ;) W sumie dobry poradnik by się z tego mógł zrobić.
Czyli strona, na której obecnie się znajdujemy jest podatna na Clickjacking :)