Translate: 
EnglishFrenchGermanItalianPolishPortugueseRussianSpanish

Ciasteczka HttpOnly oraz Secure, czyli zabezpieczenia których nie ma

Zgodnie z dokumentacją Microsoftu flaga HttpOnly przesłana w nagłówku HTTP Set-Cookie sprawia, że w przeglądarkach WWW obsługujących ten mechanizm skrypty JavaScript nie są w stanie odczytywać, ani modyfikować zawartości ciasteczka którego ten parametr dotyczył.

Podobnie działa mechanizm Secure, z tym że nie ukrywa on danych przed skryptami JS, lecz dotyczy rodzaju połączenia, przez które przesyłane jest ciasteczko. Jeśli zostało ono ustawione jako bezpieczne, przeglądarka WWW wyśle je do serwera jedynie wtedy, gdy połączenie jest szyfrowane (HTTPS).

Poniżej prezentuję prosty przykład w języku JavaScript łamiący częściowo te zabezpieczenia.

Jak obejść zabezpieczenia?

Wartości ciasteczek w trybie Secure lub HttpOnly nie można odczytać wbrew flagom bezpieczeństwa, można je jednak nadpisać własnymi wartościami i to mimo tego, że przeglądarki nie pozwalają na takie operacje.

Oto przykładowe zabezpieczenia różnych przeglądarek dla flagi HttpOnly:

Przeglądarka                  Wersja      Ochrona
                                      Odczytu  Zapisu 
-----------------------------------------------------
Microsoft Internet Explorer 	8       Tak     Tak
Microsoft Internet Explorer 	7       Tak     Tak
Microsoft Internet Explorer 	6 (SP1) Tak     Nie
Mozilla Firefox              3.0.0.6+   Tak     Tak
Netscape Navigator             9.0b3    Tak     Tak 
Opera                          9.23     Nie     Nie 
Opera                          9.50     Tak     Nie 
Safari                          3.0     Nie     Nie 
Google's Chrome                         Tak     Nie

Sztuczka nadpisująca bezpieczne ciasteczka jest niezmiernie prosta: większość przeglądarek posiada wbudowane limity dotyczące ilości ciasteczek, które mogą być ustawione dla pojedynczej domeny WWW.

Jeśli przeglądarka pozwala na ustawienie tylko 1000 ciasteczek, stworzenie ciasteczka nr. 1001 dla tej samej domeny spowoduje dodanie nowego, oraz równoczesne usunięcie najstarszego (w tym przypadku ciasteczka o nr. 1).

Nietrudno sobie wyobrazić, że najstarszym ciasteczkiem może być to, które było zabezpieczone flagami HttpOnly lub Secure i należało do atakowanego serwisu.

W tym celu wystarczy uruchomić niewielki kod JavaScript:

function setCookie(c_name,value,exdays,domain)
{
    var exdate = new Date();
    exdate.setDate(exdate.getDate() + exdays);
    var c_value = escape(value) + ((exdays == null) ? "" : "; expires=" 
       + exdate.toUTCString()) 
       + "; domain="+domain+"; path=/";
    document.cookie = c_name + "=" + c_value;
}
for(var i=0; i<1000; i++) {
    setCookie("trash"+i, "trash", 14, ".bank.com");
}
setCookie("SESSION_ID", "DEADBEEF", 14, ".bank.com");
alert("POISONING FINISHED");

Przedstawiony skrypt nie wymaga większych objaśnień: w pętli generowane jest tysiąc ciasteczek HTTP w nadziei na przepełnienie limitu przeglądarki (w przypadku Mozilla Firefox wystarczy ich 150).
Następnie tworzone jest nowe ciasteczko z ID sesji ustawionym na przykładową wartość DEADBEEF (wymyśloną przez napastnika i zapamiętaną przez niego do późniejszych operacji).

Powyższa metoda działa równie dobrze na ciasteczka typu HttpOnly, jak i Secure. Po ich nadpisaniu, kod JavaScript ma pełną kontrolę nad takim ciasteczkiem do czasu, aż atakowany serwis nie wygeneruje nowego.

W przykładzie posłużyłem się językiem JavaScript aby uzmysłowić wagę zagrożenia: skrypt w tym języku może zostać w prosty sposób wstrzyknięty do kodu HTML zwykłych, słabo zabezpieczonych stron WWW, np. poprzez atak XSS.

Jakie jest zagrożenie?

W przypadku źle napisanych serwisów internetowych nadpisanie ciasteczka naraża ofiarę na atak typu Session fixation.

Napastnik jest wtedy w stanie wygenerować dla użytkownika własne ID sesji bez konieczności wykradnięcia już istniejącej. Następnie po ustawieniu własnego ID, napastnik podszywa się pod ofiarę bez znajomości jej loginu lub hasła do strony.

Czy można się zabezpieczyć?

Tak, przede wszystkim należy pilnować, by ID sesji generowane było tylko przez oprogramowanie serwera. Gdy aplikacja wykryje, że użytkownik wchodzi na serwis z nieznanym ID, należy je wtedy natychmiast zmienić na inne, zamiast używać otrzymanego z przeglądarki użytkownika.

Często głównym błędem w tym przypadku jest używanie własnych, niesprawdzonych mechanizmów obsługi sesji. Wiele gotowych bibliotek i frameworków zabezpieczonych jest na wypadek takiego ataku, ryzyko wykorzystania takiej luki jest więc wtedy znikome.

Dodaj odpowiedź