Problem na zamówienie (cz. 2)

Aplikacje na zamówienie to coraz częściej rozwiązania dostępne za pośrednictwem przeglądarki - wszędzie i o każdej porze. Ta wygoda ma swoją cenę w postaci zagrożeń czyhających na źle skonstruowaną komunikację przeglądarki z serwerem WWW

Aplikacje na zamówienie to coraz częściej rozwiązania dostępne za pośrednictwem przeglądarki - wszędzie i o każdej porze. Ta wygoda ma swoją cenę w postaci zagrożeń czyhających na źle skonstruowaną komunikację przeglądarki z serwerem WWW .

Protokół HTTP stworzono z myślą o udostępnianiu statycznych dokumentów. "Interfejs dokumentowy" - z charakterystyczną dla niego łatwością osadzania różnorakich obiektów i hiperłączami szybko przyjął się jednak jako interfejs dla aplikacji. Stało się tak w dużej mierze dzięki popularyzacji specyfikacji CGI (Common Gateway Interface), opisującej metody dynamicznego generowania kodu HTML przez programy działające po stronie serwera. Obecnie zdecydowana większość serwisów WWW to rozbudowane aplikacje generujące strony dynamicznie. Oprócz CGI w powszechnym użyciu są dedykowane motory aplikacyjne w rodzaju PHP, przez ASP, aż po najbardziej zaawansowane rozwiązania zgodne z J2EE.

Niestety, mimo ogromnego postępu w wydajności, skalowalności i wygodzie budowy aplikacji internetowych/intranetowych, sposób komunikowania się serwera z klientami nie uległ zmianie. Bezstanowy protokół HTTP wciąż jest fundamentem, wspólnym mianownikiem aplikacji WWW, który jest jednak bardzo kosztowny. Brak sesyjności wymusza na twórcach aplikacji samodzielne tworzenie kodu realizującego tę funkcjonalność, co w wielu przypadkach kończy się fatalnie.

Błędy w obsłudze sesji użytkownika od lat należą do czołówki problemów związanych z bezpieczeństwem aplikacji WWW. Podatność w tej dziedzinie to dla potencjalnego włamywacza smakowity kąsek, dostępny często bez większego wysiłku. Bezpieczeństwo sesji użytkownika sprowadza się do bezpieczeństwa identyfikatora sesji. Jeśli intruz pozna identyfikator sesji, będzie mógł niepostrzeżenie przejąć sesje użytkownika i konwersować z serwerem, podszywając się pod niego.

Kłopoty z sesją

Protokół HTTP jest protokołem bezstanowym - w serwisie statycznym każde żądanie HTTP jest traktowane przez serwer niezależnie. W przypadku dynamicznej aplikacji WWW użytkownik wielokrotnie komunikuje się z serwerem w tym samym kontekście, co tworzy warunki do przyporządkowania wielu połączeń jednej sesji. Tym, co łączy poszczególne żądania i odpowiedzi HTTP w jedną sesję, jest jej identyfikator. Mechanizm ten działa następująco: (1) przy utworzeniu sesji serwer ustawia w przeglądarce identyfikator sesji; (2) przeglądarka przy każdym kolejnym odwołaniu do aplikacji przedstawia się nadanym jej identyfikatorem sesji; (3) na podstawie identyfikatora serwer kojarzy wywołanie przeglądarki z konkretną sesją HTTP.

Po stronie serwera sesja jest implementowana jako "obiekt", w którym jest zapamiętany stan działań użytkownika w aplikacji, np.: nieuwierzytelniony/uwierzytelniony, przelew krok1/krok2/krok3 itd. W ten sposób bezstanowy protokół HTTP może zostać wykorzystany jako transport dla aplikacji, dla których pojęcie "stanu" działań użytkownika jest niezbędne.

Identyfikator może być przekazywany na różne sposoby. Większość aplikacji wykorzystuje do tego celu mechanizm cookie.

Opisany wyżej proces obsługi sesji zaimplementowany przy użyciu cookie wygląda następująco. Serwer, korzystając z nagłówka HTTP "Set-Cookie", tworzy w przeglądarce plik cookie zawierający identyfikator sesji użytkownika, który jest skojarzony z adresem serwera oraz ścieżką URL przypisaną do pliku cookie. Przy każdym kolejnym odwołaniu do serwera i do tej ścieżki URL, aplikacja ma obowiązek przedstawienia zapamiętanego cookie. Zwykły plik cookie jest pamiętany przez przeglądarkę do czasu jej zamknięcia.

Są jednak także cookie trwałe (persistent cookie), które są zapisywane na dysku i "żyją" do upłynięcia skojarzonej z nimi daty ważności. Naturalnie do zapamiętywania identyfikatora sesji powinno się używać wyłącznie cookies nietrwałych.

Dla przeglądarek nieobsługujących lub z wyłączonym mechanizmem cookie obsługa sesji jest możliwa dzięki mechanizmowi URL-rewriting. Polega on na tym, że do każdego URL na generowanych stronach HTML serwer dodaje identyfikator sesji jako parametr. Kliknięcie przez użytkownika dowolnego łącza powoduje przesłanie identyfikatora sesji wraz z żądaniem HTTP. Trzecią metodą przekazywania identyfikatora sesji jest umieszczenie go w parametrze typu hidden na generowanej stronie HTML, jednak metoda ta jest rzadko używana przez współczesne aplikacje.

Jeśli użytkownik nie zamknie aplikacji wylogowując się, lecz po prostu wyłączy przeglądarkę, jego sesja nadal będzie aktywna na serwerze. Problem ten jest powszechny. Ponieważ nie ma innej metody poinformowania serwera, że użytkownik zakończył pracę, wszystkie serwery aplikacji wykorzystują mechanizm polegający na dopuszczalnym czasie braku aktywności, po którym sesja jest uznawana za nieważną.

Opisane wyżej mechanizmy zarządzania sesją użytkownika, jakkolwiek bardzo proste i przejrzyste, wprowadzają bardzo istotne zagrożenie. Osoba, która w jakiś sposób podejrzy identyfikator sesji HTTP użytkownika, może bardzo łatwo podszywać się pod niego. Poznanie identyfikatora sesji jest w praktyce równoważne z możliwością przejęcia sesji użytkownika i modyfikacji danych z jego uprawnieniami - bez poznania loginu i hasła, niezależnie od tego, jak wymyślny mechanizm wierzytelnienia był zastosowany (np. hasła jednorazowe, token itd.). Identyfikator taki można zdobyć na kilka sposobów, np. podsłuchać, przewidzieć albo wykraść.

Zdobyć klucz

Podsłuchanie identyfikatora sesji użytkownika w ruchu HTTP jest możliwe, o ile intruz ma dostęp do sieci LAN, w której działa użytkownik, np. gdy intruz przejął kontrolę nad jedną ze stacji roboczych. Podsłuchanie nie jest oczywiście możliwe, o ile cały ruch aplikacji jest szyfrowany za pomocą SSL. Wymaga to jednak uwzględnienia przy projektowaniu środowiska serwerowego obciążenia serwera aplikacji operacjami kryptograficznymi. Serwer może wymusić na przeglądarce przesyłanie plików cookie tylko przez połączenia szyfrowane SSL. Podsłuch ruchu sieciowego nie jest jedyną metodą podsłuchania identyfikatora sesji. Jeśli identyfikator jest przekazywany w adresie URL metodą URL-rewrite, wraz z adresem pojawia się w logach serwera WWW, a także - co gorsza - w logach proxy.

Zgadnięcie identyfikatora sesji jest możliwe, o ile aplikacja generuje identyfikatory sesji w sposób przewidywalny. Aby temu zapobiec, identyfikator sesji powinien być liczbą losową wystarczająco długą, by przeszukanie całej przestrzeni możliwych identyfikatorów nie było możliwe w rozsądnym czasie. Kiedyś był to poważny problem - przewidywalne identyfikatory generował m.in. serwer aplikacji IBM WebSphere 4.0. Obecnie większość aplikacji udostępniają interfejsy API do sprawdzonych mechanizmów zarządzania sesją, w tym generowania identyfikatora. Nie znaczy to jednak, że projektant musi je wykorzystywać. Niektóre aplikacje nie korzystają ze standardowych mechanizmów zarządzania sesją oferowanych przez serwer i same implementują nadawanie identyfikatora. Jeśli programista nie zadbał o jego losowość i długość, to identyfikator taki może być przewidywalny.

Uwierzytelnienie nie wystarczy

Z punktu widzenia bezpieczeństwa aplikacji WWW identyfikator sesji jednoznacznie przedstawia użytkownika. To właśnie dlatego większość aplikacji obsługujących bankowość elektroniczną wymaga dodatkowego uwierzytelnienia każdej transakcji. Szyfrowanie za pomocą SSL jedynie uwierzytelnienia, bez szyfrowania dalszej komunikacji, jak ma to miejsce w wielu portalach, jest zabezpieczeniem wirtualnym - poznanie identyfikatora aktywnej sesji pozwala przejąć sesję bez względu na siłę zastosowanych metod uwierzytelniania.


TOP 200