session fixation
| Po angielsku | session fixation |
|---|---|
| Którą formą pisać | po angielsku Polski odpowiednik istnieje, ale w praktyce nikt tak nie pisze. Zostaw angielski, polski trzymaj jako synonim. |
| Inne formy | fiksacja sesji · utrwalenie sesji · narzucenie identyfikatora sesji |
| Kategoria | Podatności i klasy błędów |
Session fixation to podatność w zarządzaniu sesją: aplikacja uwierzytelnia użytkownika albo zakłada nową sesję, nie unieważniając istniejącego identyfikatora sesji, co daje atakującemu okazję do przejęcia uwierzytelnionej sesji [1]. W odróżnieniu od kradzieży identyfikatora atakujący nie musi go zdobywać po zalogowaniu ofiary. Sam go wybiera albo uzyskuje wcześniej, a następnie narzuca ofierze [2]. Słabość ma w katalogu CWE numer CWE-384 [1].
Jak działa
OWASP opisuje session fixation jako atak pozwalający przejąć ważną sesję użytkownika przez wykorzystanie ograniczenia w sposobie, w jaki aplikacja zarządza identyfikatorem sesji [2]. Kluczowy błąd polega na tym, że aplikacja nie przydziela nowego identyfikatora w chwili uwierzytelnienia [2]. Identyfikator, który istniał przed logowaniem, zostaje więc nośnikiem uprawnień zalogowanego użytkownika.
MITRE wymienia trzy sytuacje, w których pojawia się ta słabość [1]:
- aplikacja loguje użytkownika bez unieważnienia dotychczasowej sesji i dalej używa sesji już z nim powiązanej;
- atakujący może narzucić użytkownikowi znany sobie identyfikator, więc po zalogowaniu ofiary ma dostęp do uwierzytelnionej sesji;
- aplikacja albo kontener używa przewidywalnych identyfikatorów sesji.
Typowy przebieg według OWASP ma sześć kroków: atakujący nawiązuje połączenie i uzyskuje identyfikator, wysyła ofierze link z tym identyfikatorem, ofiara wchodzi na stronę, serwer rozpoznaje istniejącą sesję i nie tworzy nowej, ofiara loguje się, a atakujący używa znanego identyfikatora, by wejść na jej konto [2]. Schemat poniżej pokazuje ten scenariusz.
Odmiany
Odmiany różnią się sposobem, w jaki identyfikator trafia do przeglądarki ofiary. OWASP wymienia pięć najczęstszych technik [2].
| Technika | Jak identyfikator trafia do ofiary |
|---|---|
| argument w adresie URL | link z identyfikatorem w parametrze [2] |
| ukryte pole formularza | ofiara loguje się przez formularz przygotowany przez atakującego [2] |
| skrypt po stronie klienta | wstrzyknięty kod ustawia ciasteczko sesji [2] |
| znacznik META | wstrzyknięty znacznik ustawia ciasteczko bez użycia skryptu [2] |
| nagłówek odpowiedzi HTTP | atakujący wstawia do odpowiedzi nagłówek Set-Cookie [2] |
Trzy ostatnie techniki wymagają innego błędu na tej samej witrynie, najczęściej XSS (Cross-Site Scripting) albo wstrzyknięcia nagłówka. Session fixation bywa więc drugim ogniwem łańcucha, a nie samodzielnym atakiem. Najprostszy wariant, z identyfikatorem w adresie, rozsyła się jak zwykły phishing.
W WordPressie
Rdzeń WordPressa nie opiera logowania na mechanizmie sesji PHP. Funkcja wp_set_auth_cookie() ustawia ciasteczka uwierzytelniające dla danego użytkownika, a gdy nie dostanie gotowego tokenu sesyjnego, tworzy nowy przez WP_Session_Tokens [6]. Każde logowanie daje więc nowy token, którego atakujący nie zna z góry.
Ryzyko dotyczy przede wszystkim wtyczek, które same wywołują session_start() i przechowują stan w tablicy $_SESSION: koszyki, formularze wieloetapowe, własne ekrany logowania. To obszar, w którym powstaje podatność we wtyczce. Narzędzie Zdrowie witryny ma osobny test wykrywający aktywną sesję PHP. Komunikat mówi, że sesja utworzona wywołaniem session_start() zakłóca żądania REST API i żądania zwrotne (loopback) i powinna być zamknięta przez session_write_close() przed wykonaniem żądań HTTP [7]. Test dotyczy wydajności i działania, nie bezpieczeństwa, ale przy okazji ujawnia wtyczki, które używają sesji PHP i warto sprawdzić, czy odnawiają identyfikator po zalogowaniu.
Zagrożenia i skutki
MITRE klasyfikuje skutek jako uzyskanie uprawnień lub przyjęcie cudzej tożsamości [1]. W praktyce oznacza to przejęcie sesji (session hijacking), a przez nie przejęcie konta: atakujący działa w aplikacji tak jak ofiara, dopóki sesja jest ważna. Jeżeli ofiarą jest administrator, skutki obejmują zmianę ustawień, instalację kodu i dodanie własnego użytkownika, czyli pełną eskalację uprawnień.
Atak jest trudny do zauważenia w logach. Żądania atakującego niosą prawidłowy identyfikator, a samo logowanie wykonała ofiara, podając prawdziwe dane uwierzytelniające.
Jak się bronić
Podstawowa zasada jest jedna. OWASP stwierdza, że aplikacja musi odnowić albo wygenerować identyfikator sesji po każdej zmianie poziomu uprawnień w sesji, a najczęstszym takim momentem jest uwierzytelnianie [3]. MITRE zaleca unieważnienie istniejących identyfikatorów przed autoryzacją nowej sesji użytkownika [1].
W PHP służy do tego session_regenerate_id(), które zastępuje bieżący identyfikator nowym i zachowuje dane sesji [4]. OWASP podaje jako przykład wywołanie z argumentem true [3], które usuwa stary plik sesji [4]. Dokumentacja PHP zastrzega jednak, że natychmiastowe usuwanie starych danych może wywołać wyścig przy równoległych żądaniach i wyłącza wykrywanie przejęcia sesji; zaleca znacznik czasu zniszczenia i kontrolę dostępu do starego identyfikatora [4].
// po poprawnym sprawdzeniu hasła, przed zapisaniem użytkownika w sesji
session_regenerate_id( true );
$_SESSION['user_id'] = $user_id;
Druga warstwa to tryb ścisły. Opcja session.use_strict_mode sprawia, że moduł sesji nie przyjmuje niezainicjowanych identyfikatorów i w ich miejsce wysyła nowy; dokumentacja PHP nazywa jej włączenie obowiązkowym dla bezpieczeństwa sesji, choć domyślna wartość to 0 [5]. OWASP formułuje to ogólniej: aplikacja nie powinna nigdy przyjmować identyfikatora, którego sama nie wygenerowała [3].
Trzecia warstwa to wyłączenie identyfikatorów w adresach. Opcja session.use_only_cookies jest domyślnie włączona i zapobiega atakom polegającym na przekazywaniu identyfikatora w URL; jej wyłączanie jest od PHP 8.4.0 przestarzałe [5]. Pomagają też flagi ciasteczek (cookie flags) i usuwanie błędów XSS, które umożliwiają ustawienie ciasteczka z zewnątrz. Jako dodatkową warstwę wykrywania MITRE wymienia zapory aplikacyjne [1], czyli WAF.
Historia i przykłady
Katalog CWE podaje jako obserwowany przykład CVE-2022-2820: oprogramowanie stron serwerów gier nie kończyło poprawnie sesji użytkowników, co umożliwiało session fixation [1]. Dokumentacja PHP opisuje wprost ryzyko sesji w adresach: użytkownik może wysłać komuś link zawierający aktywny identyfikator albo zapisać go w zakładkach i stale wracać z tym samym identyfikatorem [5].
Przypisy
7- [1] CWE-384: Session Fixation · MITRE
- [2] Session fixation · OWASP
- [3] Session Management Cheat Sheet · OWASP Cheat Sheet Series
- [4] session_regenerate_id — PHP Manual · The PHP Group
- [5] Runtime Configuration (Sessions) — PHP Manual · The PHP Group
- [6] wp_set_auth_cookie() — Code Reference · WordPress.org
- [7] WP_Site_Health::get_test_php_sessions() — Code Reference · WordPress.org