Podręcznik
3. Błędy uwierzytelnienia i kontroli sesji
Kontynuując temat rozpoczęty w poprzednim rozdziale przyjrzyjmy się innym rodzajom błędów związanych z uwierzytelnieniem użytkowników.
Pierwszym z nich jest wykorzystanie domyślnych poświadczeń i kont użytkowników w systemach i aplikacjach. Prosta analiza prób włamań do systemów operacyjnych z rodziny Linux-a pokazuje, że bardzo często sprawdzane nazwy użytkowników obejmują typowe usługi i konta systemowe jak admin, apache2, ftp, ipc, backup, mysql, postgres, proxy, root, sync, upload, uucp a także powiązane z wieloma typowymi dystrybucjami i narzędziami jak ubuntu, bitnami, advantage, azureuser, cactiuser, cassandra, centos, huawei, tempuser, user0 etc. (na podstawie własnych analiz).
Domyślne konta użytkowników można wykorzystać m.in. do ataku na router domowy w celu zmiany ustawień serwera DNS i przekierowywania ofiary na podstawione strony www (CVE-2013-2645) [19].
Zabezpieczeniem przed atakami brute-force może być ograniczenie ilości poprawnie wykonywanych prób uwierzytelnienia w jednostce czasu (np. zezwalamy na k prób w ciągu N minut, a następnie przez następne X minut próby, nawet poprawne zostaną zignorowane). Ogranicza to skuteczność ataku nie powodując dodatkowego obciążenia serwera. Uwaga: alternatywna technika spowalniania reakcji wraz ze wzrostem liczby prób konsumuje zasoby serwera ułatwiając atak typu DoS (denial-of-service). Z drugiej strony znaczącym ułatwieniem dla atakującego jest nieprawidłowe sygnalizowanie powodu błędu uwierzytelnienia – komunikat błędu nie powinien wskazywać powodu odrzucenia danych uwierzytelniających a dodatkowo czas potrzebny na wygenerowanie komunikatu nie powinien zależeć od rodzaju błędu (side-channel). Wiedza o tym, czy dane konto istnieje czy nie jest istotna z punktu widzenia procesu poszukiwania hasła.
Jednym z bardziej skutecznych sposobów ograniczania skuteczności ataków na hasła użytkowników jest stosowanie uwierzytelnienia wieloetapowego. Dodanie dodatkowych komponentów do procesu uwierzytelnienia zgodnie z zasadą:
- coś co znam (hasło),
- coś co mam (token sprzętowy, aplikacja generująca kod, karta inteligentna),
- coś czym jestem (biometria),
znacząco utrudnia lub wręcz uniemożliwia obejście procesu uwierzytelnienia prostymi metodami. Więcej o tematyce obchodzenia zabezpieczeń wieloetapowych można przeczytać w książce [20].
Kolejnym problemem jest utrzymywanie i ujawnianie danych sesji uwierzytelnionej poprzez
- ujawnianie identyfikatorów sesji w pasku adresu URL przeglądarki, co umożliwia podejrzenie identyfikatora przez osoby postronne lub ujawnienie na filmie/zdjęciu. Ujawnienie identyfikatorów sesji może prowadzić do jej przejęcia przez atakującego – Session Hijacking,
- zaniechanie zmiany identyfikatora sesji po uwierzytelnieniu użytkownika – niezaufany identyfikator staje się zaufany, co w przypadku jego poznania przed uwierzytelnieniem prowadzi do jednego z wariantów ataku Session Fixation,
- przewidywalne identyfikatory sesji,
- brak unieważniania identyfikatora sesji po wylogowaniu (częsty błąd przy wykorzystaniu tokenów JWT),
- możliwość wymuszenia znanego identyfikatora sesji poprzez podanie go jako ciasteczko, identyfikator w URL, efekt ataku cross-site scripting – przy braku regeneracji identyfikatora przy uwierzytelnieniu umożliwia drugi wariant ataku Session Fixation.
Przykład podstawienia identyfikatora sesji w JavaScript:
<script>document.cookie="JSESSIONID=32784652376453764573645";</script>
lub jako tag HTML (HTML injection):
<meta http−equiv=Set−Cookie content="PHPSESSID=3278465237645376"/>
Metodami obrony w tym przypadku są:
- regeneracja identyfikatora sesji przy każdej zmianie poziomu uprawnień, a nawet co ustalony czas,
- ukrycie identyfikatora sesji przed kodem JavaScript poprzez użycie atrybutu HttpOnly dla ciasteczka,
- używanie nieprzewidywalnych, losowych identyfikatorów sesji o długości >=128 bitów,
- w przypadku sesji podlegających wymaganiom PCI DSS 3.2 czas życia identyfikatora do regeneracji <= 15min,
- skuteczne unieważnianie identyfikatora sesji po wylogowaniu – w przypadku tokenów JWT oznacza to przechowywanie unieważnionych tokenów do upływu ich zdefiniowanego czasu życia.
Dobrym zaleceniem w kontekście przejmowania sesji jest też uniemożliwienie posiadania wielu równoległych sesji dla tego samego użytkownika, a jeżeli aplikacja to umożliwia to warto dać użytkownikowi możliwość sprawdzenia jakie uwierzytelnione sesje posiada (patrz ekosystem Google).