Sesje w aplikacjach internetowych
Ze względu na fakt, że protokół HTTP jest bezstanowy, wyszła potrzeba, aby identyfikować wywołania tego samego użytkownika i przechowywać zmienne pomiędzy nimi. Tym mechanizmem są sesje. Każda sesja jest identyfikowana ciągiem znaków (domyślnie jest to losowy, 32 znakowy łańcuch), który jest przechowywany w ciasteczku (cookies) lub przekazywany przez URL. Identyfikator sesji jest unikalny dla użytkownika, a więc osoba, która w nieładny sposób wejdzie w jego posiadanie, praktycznie wykrada tożsamość danego użytkownika w danej aplikacji (portalu, sklepie internetowym, blogu, portalu społecznościowym).
Zagrożenia
Jako że, ciasteczka, czyli mechanizm zapisu informacji w przeglądarce użytkownika przez aplikację internetową, są mechanizmem względnie bezpiecznym, projektanci aplikacji zawsze powinni wybierać ten sposób przechowywania identyfikatora sesji. Przekazywanie SESSID (session id) w url’u wystawia aplikację na zagrożenie atakiem session fixation.
Szkodnik, który przejmie naszą sesje, może poczynić spore spustoszenie w naszej przestrzeni systemu, od publikacji kompromitujących treści, poprzez dostęp do prywatnych danych, historii naszej działalności (np. zakupów), poprzez nawet wykonanie jakiś transakcji na nasze konto. Zagrożenia jakie za tym idą, są różne, ze względu na różne specyfiki aplikacji webowych.
Co to jest session fixation?
Session fixation polega na podsunięciu użytkownikowi linku do atakowanej aplikacji z spreparowanym identyfikatorem sesji, który jest znany atakującemu. Jak to działa w praktyce? Przygotowujemy url w postaci http://moja.aplikacja?sekcja=profil&SESSID=1234abcd1234abcd1234abcd1234abcd i sugerujemy użytkownikowi jego kliknięcie, posyłając np. emailem lub linkując go pod jakieś zdjęcie. Użytkownik wchodzi do atakowanej aplikacji. Jako, że korzysta z nowej sesji, loguje się do systemu i wykonuje jakieś operacje. Atakujący wchodzi do aplikacji z tego samego linka i ma do dyspozycji zalogowane konto, dzięki czemu może wykonać dowolne operacje w imieniu skompromitowanego użytkownika.
Ze względu na specyfikę tego ataku, często w sieci stosuje się inne określenie: session riding, ponieważ „jeździmy” na czyjejś sesji, gdzie uzyskano odpowiedni dostęp do systemu.
Jak się bronić przed tym atakiem z punktu widzenia programisty?
Metoda jest prosta i domyślnie włączona w nowych wersjach PHP. Nigdy nie powinno się używać identyfikatora sesji przekazywanego przez URL! Aby to osiągnąć, można użyć następujących ustawień PHP (w pliku php.ini):
Poza tym, powinniśmy regenerować id sesji przed logowaniami (metodą session_regenerate_id). Ostatnią rzeczą, która ochroni nas też przed innymi atakami, polegającymi na wyłudzeniu tożsamości, jest ponowne sprawdzenie hasła przed krytycznymi operacjami, takimi jak zmiana hasła, zmiana danych profilowych, usunięcie konta, czy dokonanie jakiejś sporej płatności. Tą metodę stosuje m.in. znany portal LinkedIn.
Jak się bronić przed tym atakiem z punktu widzenia użytkownika aplikacji?
Jako, że nie wiemy, czy aplikacja z której korzystamy jest podatna na tego typu ataki, powinniśmy zawsze ostrożnie korzystać z linków, które dostajemy z nieznanych źródeł. Jeśli jesteśmy zalogowani do portalu X, a za chwilę dostaniemy podejrzanie długi link, po wejściu na który znowu jesteśmy proszeni o hasło, to znaczy, że coś nie gra i należy się dwa razy zastanowić na dalszymi krokami.
Tags: bezpieczeństwo, php, security, sesje
[...] Zapraszam do lektury. Artykuł jest dostępny pod tym adresem. [...]
Warto również wspomnieć, że artykuł pojawił się na stronie http://www.hcsl.pl/2010/11/co-to-jest-session-fixation-i-jak-sie.html Gratki Wojtek : )
Kiedyś mocno interesowałem się tematem to od razu nasunęło mi się kilka uwag:
1) Ten atak jest o tyle perfidny, że nawet nie musimy sugerować komuś kliknięcia w link. Wystarczy, że zaszyjemy go np. w tag IMG, wtedy „sam się kliknie”, jak ktoś tylko wejdzie na stronie (). W ten sam sposób możemy właściwie wykorzystywać CSRF.
2) Aby upewnić się, że sesja została utworzona przez nas można np. na początku zapisac jakiś znacznik $_SESSION['our_session'] = true; i potem sprawdzać czy jest obecne. Sesje utworzone z zewnąrz oczywiście tego nie będą miały.
3) session.use_only_cookies = 1 to nie wszystko. Przy użyciu XSS można wstrzyknąć SESSID przez document.cookie. Właściwie to tylko dowód, że bezpieczeństwo to naczynia połączone.
4) Świetne dokumenty podejmujące ten temat to http://www.acrossecurity.com/papers/session_fixation.pdf oraz http://www.securenet.de/papers/Session_Riding.pdf. Zdecydowanie polecam.
5) Ogólnie standardowy mechanizm obsługi w PHP pozostawia wiele do życzenia jeśli chodzi o bezpieczeństwo (dlaczego w ogóle z automatu tworzy sesję gdy tylko jest obecny SESSID w query string???). Wydaje mi się, że kilka w miarę prostych zabiegów wystarczyłoby, żeby nie trzeba było się martwić o wiele rzeczy. Kiedyś nawet rzuciłem się na pisanie biblioteki, która całkiem zastępuję używanie rozszerzenia session (w surowej formie na https://github.com/sobstel/sesshin). Sesje są tworzone i utrzymywane dopiero kiedy checmy, nie musimy się martwić (lub martwimy się mniej) o rozmaite ataki Session Hijacking, Session Fixation, Session Exposure, Sesion Poisoning, etc. Dzięki, bo właściwie ten artykuł natchnął mnie, żeby dopracować ten lib (używałem go w trochę innej formie na produkcji i sprawdzał się ok), a nuż ktoś skorzysta, albo chociaż natchnie go poczytania o bezpieczeństwie sesji.