2FA czasem zawodzi

Tak, uwierzytelnienie 2FA nie jest nie do przejścia dla atakujących i w związku z tym można przeczytać takie artykuły: Chinese Hackers Bypass 2FA in Attacks Spanning 10 Countries. Warto zdawać sobie sprawę ze sposobów, w jaki 2FA może zawieść (innymi słowy – warto wiedzieć jak inni zepsuli 2FA).

Sposobów jest kilka, na początek warto zastanowić się nad tymi obszarami:

Ta lista oczywiście nie jest kompletna, ale na początek jest wystarczająca.

Inicjowanie 2FA

Jednym z typowych scenariuszy jest aktywacja uwierzytelnienia dwuskładnikowego, a konkretniej skojarzenie drugiego składnika z kontem użytkownika.

Wiele rozwiązań 2FA oparte jest na kodach jednorazowych wyliczanych na podstawie określonego algorytmu z wykorzystaniem pewnego sekretu dzielonego między serwerem i użytkownikiem. W wielu przypadkach ten algorytm to HMAC-based One-time Password algorithm i, o ile ktoś nie stara się go zaimplementować w „twórczy i kreatywny” sposób, sam algorytm jest bezpieczny. Większym problemem jest ustalenie wspomnianego sekretu.

Wspomniany sekret można uzgodnić na wiele sposobów i można to zrobić w sposób bezpieczny i przyjazny dla użytkownika. Nie chcę generalizować, ale do pewnego stopnia im nowsze rozwiązanie, tym lepiej. Dlaczego? Dlatego, że sprzęt poszedł do przodu, wymiana sekretu może być oparta o kody QR i/lub dialog między aplikacją implementującą 2FA i serwerem, oba podejścia pozwalają na uzgodnienie długiego, losowego sekretu. W starszych rozwiązaniach ustalanie sekretu odbywało się za pośrednictwem „interfejsu białkowego”, czyli (najczęściej nieświadomego) użytkownika, dla którego wygody często wykorzystywany był „kod aktywacyjny” składający się z 6, 8 lub 9 cyfr. Jeśli jest to tymczasowy kod, który wykorzystywany jest „pod spodem” do ustalenia właściwego sekretu, nie jest to problemem, ale co jeśli ten kod jest bezpośrednio przekształcany w sekret? Ile możliwych wartości daje 9 cyfr? Ile to bitów?

Może i 1 000 000 000 możliwych wartości sekretu (seed) to więcej niż ilość użytkowników, którzy z danego rozwiązania będą korzystać, ale 30 bitów to po prostu za mało i realne jest przygotowanie sekwencji kodów OTP dla wszystkich (a przynajmniej znaczącej części możliwych wartości seed), zidentyfikowanie konkretnego seed na podstawie sekwencji kilku kolejnych kodów OTP co w rezultacie efektywnie skutkuje „sklonowaniem” takiego tokenu 2FA.

Tak, inicjalizacja 2FA jest zdecydowanie pierwszym obszarem, który należy dokładnie przeanalizować.

A w zasadzie jak działa ten drugi składnik

To jest bardzo szerokie zagadnienie i nie ogranicza się wyłącznie do tematu algorytmu używanego do generowania OTP, w zasadzie można zacząć od pytania czym jest ten drugi składnik. Pomijając biometrię możemy mieć do czynienia z dwoma głównymi scenariuszami:

Dedykowane urządzenie z reguły jest bezpieczniejsze, ale przy tym nie zawsze wygodne. Zresztą z tym bezpieczeństwem też bywa różnie, bo ilość sposobów na interakcję z takim urządzeniem rośnie, często nie jest to już kod wyświetlany na wyświetlaczu, urządzenie może być podłączone do innych urządzeń korzystając z portów (np. USB), Bluetooth czy NFC. W efekcie rosnącej złożoności można potem oglądać takie informacje: Google Will Replace Titan Security Key Over a Bluetooth Flaw, ciekawą lekturą może być również sekcja Security Advisories dla Yubico.

Pod względem (nie)bezpieczeństwa zdecydowanie ciekawsze są aplikacje na telefony. Z ciekawszych zagadnień warto wspomnieć:

Zarówno Android jak i iOS oferują obecnie bezpieczne sposoby przechowania sekretów i rozwiązania te działają dość dobrze, przynajmniej do czasu, gdy integralność systemu nie zostaje naruszona (rooting / jailbreak). Zdecydowanie więcej „radości” dają sytuację, gdy sekret (seed) przechowywany jest „lokalnie” i jest zabezpieczony w sposób wymyślony przez autorów aplikacji.

Tutaj trzeba pamiętać, że nawet posiadanie seeda z urządzenia niekoniecznie oznacza możliwość generowania prawidłowych kodów OTP, bo w procesie tworzenia OTP może być uwzględniany sekret pochodzący od użytkownika (np. dodatkowy PIN). Teoretycznie nawet stosunkowo krótki PIN (np. 6 cyfr) będzie wystarczający, pod warunkiem, że sekret będzie blokowany po wielokrotnym błędnym podaniu kodu.

Jak można to zepsuć? Proste – pozwolić atakującemu na „łamanie” PIN offline. By to było możliwe potrzebny jest jakiś sposób weryfikacji poprawności kodów OTP, na przykład:

Ale dajmy już spokój takim niskopoziomowym atakom, czasami po prostu wystarczy poprosić aplikację o wygenerowanie kodu OTP. Aplikacja „tokena” może dla wygody użytkownika pozwalać innym aplikacjom na generowanie i otrzymywanie kodów. Samo w sobie nie jest to złe, pod warunkiem, że:

Jak można zepsuć to w sposób spektakularny? Sytuacja, w której token jest „odblokowywany” po pierwszym podaniu kodu PIN (czyli przy kolejnych prośbach o kod OTP użytkownik nie jest proszony o podanie kodu PIN) i zezwolenie dowolnej aplikacji na poproszenie o kod OTP nie jest najlepszym pomysłem.

Nie zapominajmy, że na końcu mamy aplikację, do której się uwierzytelniamy. Być może wcale nie trzeba się skupiać na sposobie działania 2FA, ale na procesie uwierzytelnienia w aplikacji. Coraz częściej proces ten składa się z wielu kroków z wieloma przekierowaniami oraz potencjalnie różnymi ścieżkami wykonania, bo przecież:

Im bardziej skomplikowany jest proces, tym większe prawdopodobieństwo błędu. Co się stanie, gdy jeden lub kilka kroków tego procesu zostanie pominiętych lub wykonanych w nieoczekiwanej kolejności?

Pytają, to podam

2FA jest rozwiązaniem technicznym a rozwiązania techniczne nie są w stanie poradzić sobie z kreatywnością (właściwie – ignorancją) użytkowników. Można to tłumaczyć jako typowy przykład PEBCAK, albo zaprojektować system w taki sposób, by był zrozumiały dla użytkownika oraz by zachowanie niezgodne z oczekiwaniami było dla użytkownika „trudne”, czyli wymagało jakiegoś wysiłku, który być może skłoni go do refleksji.

Tradycyjne kody jednorazowe (np. hardware token) w żaden sposób nie są powiązane z inną akcją wykonaną przez użytkownika, kod OTP jest wyświetlany przez urządzenie niezależnie od akcji użytkownika, a użytkownik w wielu wypadkach jest proszony o jego podanie. Phishing to też nic innego, jak próba skłonienia użytkownika do określonej akcji, a wielkiej różnicy między podaniem hasła a kodu OTP tak naprawdę nie ma.

Tu warto zastanowić się, czy:

Tutaj dość dobrze sprawdzają się aplikacje na telefonach, które reagują na akcję użytkownika w aplikacji (często oparte jest to na powiadomieniach PUSH). Na przykład w procesie uwierzytelnienia użytkownik jest proszony o potwierdzenie próby logowania na urządzeniu, na którym jednocześnie pojawia się stosowny komunikat z dodatkowymi informacjami o akcji, która zostanie potwierdzona.

Przykładem takiego rozwiązania może być Microsoft Authenticator. Trochę inaczej działają rozwiązania Apple, ale tam również jest informacja o zdarzeniu (próba uwierzytelnienia) oraz geolokacja.

Zgubiłem (...), możecie wyłączyć 2FA?

No i tutaj zaczyna robić się naprawdę ciekawie. Sam kiedyś miałem problem z MFA używanym w Amazon (Google Authenticator) gdy telefon odmówił współpracy. I co wtedy? Wówczas wystarczyło zgłoszenie problemu, po pewnym czasie na mój numer telefonu zadzwonił miły pan, który zapytał co się stało, bardzo zmartwił się moim problemem z telefonem i... wyłączył 2FA na moim koncie. Tak, wiem. Teraz ten proces uległ zmianie i wygląda nieco inaczej, ale czy na pewno dużo lepiej?

Po co atakować (mocne) 2FA jeśli można użyć innej, mniej bezpiecznej metody? Często używane „zapasowe metody” to:

Co lepiej (gorzej) często skonfigurować trzeba wszystkie te metody. Dlaczego gorzej? Bo o ile lista kodów jednorazowych może być dość dobrze chroniona fizycznie to co z telefonem lub mailem?

Najpierw SMS / wiadomość głosowa – jeśli SMS sam w sobie nie jest uważany za bezpieczną metodę przekazywania haseł jednorazowych to nie staje się on bezpieczny, gdy jest używany jako backup dla innego, bardziej bezpiecznego rozwiązania.

A co z mailem? To zależy, czy na tym adresie też jest aktywowane 2FA? Jeśli tak, to „(...) by zrozumieć rekurencję należy najpierw zrozumieć rekurencję (...)”.

Podobne wyzwania są z zarządzaniem 2FA. Pytanie – czy jeśli atakujący przejmie aktywną sesję użytkownika jest on w stanie zmienić konfigurację 2FA, na przykład:

Co zrobić, jak żyć?

Po pierwsze – rozwiązania 2FA, nawet jeśli nie są doskonałe, są lepsze niż 1FA (brak 2FA). Nawet 2FA, które jest słabe (wspomniane SMS) jest lepsze niż jego kompletny brak i dla części zastosowań może być wystarczające.

Po drugie – warstwy. Użytkownik powinien być informowany o potencjalnie istotnych zdarzeniach, a zdarzenia związane z uwierzytelnieniem są istotne. Zalicza się do nich nie tylko udane lub nieudane uwierzytelnienie (przy okazji – im więcej szczegółów o tych zdarzeniach, tym lepiej), ale również wszelkie zdarzenia związane z zarządzaniem kontem (np. próba resetu hasła, próba resetu 2FA).

Kilka słów na koniec

Oryginał tego wpisu dostępny jest pod adresem 2FA czasem zawodzi

Autor: Paweł Goleń