Powrót do strony głównej

Obejście 2FA w banku: atak brute-force

W pentescie banku wykryto obejście SMS-2FA przez brute-force 4-cyfrowego kodu bez limitów prób. Dostęp do LK umożliwiał oszustwa. Analiza API, JS-exploit, CVSS 9.1 i rekomendacje poprawek.

Brute-force włamanie 2FA banku: pełna analiza
Advertisement 728x90

Obchód SMS-2FA przez brute-force: analiza pentestu banku

W trakcie zatwierdzonego testu penetracyjnego typu black-box w dużym systemie bankowym (4000 hostów, 4500 użytkowników) wykryto lukę umożliwiającą obchód dwustopniowej autoryzacji SMS. Złośliwy użytkownik z numerem telefonu ofiary mógł całkowicie automatycznie przeprowadzić próbę odgadnięcia 4-cyfrowego kodu bez ograniczeń liczby prób, uzyskując dostęp do danych osobowych, historii wniosków i narzędzi do oszustw.

Uzyskanie dostępu pozwalało na składanie kredytów, finansowanie projektów oraz potwierdzanie wypłat poprzez obsługę klienta — bez dodatkowych sprawdzeń. Entropia kodu (10 000 kombinacji) umożliwiała jego złamanie w ciągu kilku sekund.

Analiza API i logiki uwierzytelniania

Proces logowania opierał się na dwóch punktach końcowych:

Google AdInline article slot
  • Wysłanie SMS-a: POST zwraca "repeat":180, blokując ponowne wysłanie przez 3 minuty.
  • Sprawdzenie kodu: POST /api/*****/login z ciałem "{code":"0548","phone":"+7(111)222-22-22"}.

Odpowiedź na niepoprawny kod to HTTP 400 z komunikatem "Numer telefonu lub kod jest nieprawidłowy". Poprawna odpowiedź to HTTP 200 z ciasteczkami (JSESSIONID, PHPSESSID). Brakowało liczników prób, CAPTCHA, blokady IP lub sesji. Każdy żądanie był przetwarzany niezależnie.

POST /api/*****/login HTTP/1.1
Host: ****
Content-Type: application/json

{"code":"0548","phone":"+7(111) 222-22-22"}

Implementacja ekspluatacji w JavaScript

Proof-of-concept (PoC) wykorzystywał sesję przeglądarkową do obejścia CORS i SameSite. Główny cykl to równoległy permutacyjny atak w 20 wątkach:

await fetch('https://roga_and_copyta/*****/api/*****/login', {
    method: 'POST',
    headers: {'Content-Type': 'application/json'},
    body: JSON.stringify({code: codeStr, phone: phone})
});

for (let i = 0; i < 20; i++) {
    turboThread(i, start, end); // Zakres kodów
}

if (response.status === 200) {
    foundCode = codeStr;
    // Automatyczne uzupełnianie pola
}

Powodzenie określano po statusie 200. Podobny skrypt działał w Pythonie. Czas ataku: 35 sekund na 10 000 żądań.

Google AdInline article slot

Klasyfikacja i przyczyny luki

Luka odpowiada CWE-307 (Niewłaściwe ograniczenie nadmiernych prób uwierzytelniania). CVSS 3.1: 9.1 (Krytyczny) — sieć, niska złożoność, brak uprawnień, brak interakcji użytkownika.

Kluczowe błędy projektowe:

  • Priorytet wygody: brak blokad dla uniknięcia reklamacji o błędne wpisywanie.
  • Ignorowanie automatyzacji: 4 cyfry są trudne dla człowieka, ale łatwe dla skryptu.
  • Brak testów przeciwko brute-force.

Zalecenia dotyczące usunięcia luki

Dla wielowarstwowej ochrony należy wdrożyć:

Google AdInline article slot
  • Limit 3–5 prób na kod z rotacją SMS.
  • CAPTCHA po 2–3 błędach.
  • 6-cyfrowe kody (1 milion kombinacji, czas przebrania — godziny).
  • Monitorowanie anomalii: częstotliwość żądań, reputacja IP.
  • Ograniczanie szybkości (rate limiting) według numeru telefonu i sesji.
// Przykład rate limiting na serwerze (pseudokod)
if (attempts[phone] > 5) {
    invalidateCode(phone);
    requireCaptcha();
}

Co jest ważne

  • Obchód 2FA daje pełny dostęp do konta: dane osobowe, wnioski, dane bankowe, potwierdzenie wypłat.
  • 4-cyfrowy kod bez limitów — 10 000 kombinacji, złamanie w 35 sekund.
  • CWE-307 (CVSS 9.1): brak ochrony przed automatycznym przebraniem.
  • Zalecenie: limity + CAPTCHA + 6 cyfr + monitorowanie.
  • Pentest wykrył lukę przed wykorzystaniem; wszystko zostało zamknięte.

— Editorial Team

Advertisement 728x90

Czytaj dalej