Уязвимости второго фактора
Двухфакторная аутентификация

Вступление
Двухфакторная аутентификация давно стала стандартом цифровой гигиены. Банки, соцсети, облачные сервисы, корпоративная инфраструктура — все требуют подтверждать вход чем-то сверх пароля. Казалось бы, это решает проблему угонов аккаунтов раз и навсегда.
Но в реальности 2FA — это не броня, а лишь дополнительная дверь. Она значительно усложняет атаку, но не делает пользователя «неуязвимым». Современные злоумышленники научились обходить многие популярные способы 2FA, причём иногда — без каких-либо технических навыков, исключительно методом социальной инженерии.
В сегодняшнем материале разбираем устройство 2FA, популярным методам атак и практическим мерам защиты.
Что такое 2FA
2FA — это проверка пользователя двумя независимыми факторами. Обычно они делятся на три категории:
- Что-то, что вы знаете — пароль, PIN, секретная фраза.
- Что-то, что у вас есть — телефон, токен, смарт-карта, аппаратный ключ.
- Что-то, чем вы являетесь — биометрия: лицо, отпечаток пальца.
Главная идея в том, что взлом пароля не означает взлом аккаунта – например, на момент введения Steam Guard в 2011 году Гейб Ньюэлл публично озвучил свой пароль и предложил попасть в его аккаунт. Сделать этого никому не удалось.
Базовый 2FA флоу выглядит следующим образом:
- Пользователь вводит свой логин и пароль в форму ввода.
- Сервер предоставленные учетные данные и создает предварительную сессию и контекст аутентификации.
- Сервер проверяет, требуется ли второй фактор (политики, настройки аккаунта) и инициирует генерацию/отправку OTP или отправляет push-запрос/требует аппаратный ключ.
- Пользователь получает код (SMS/TOTP/Email) или видит пуш-запрос на своем устройстве/подключает ключ и подтверждает действие.
- Клиент отправляет подтверждение (код/подпись/ответ) обратно на сервер вместе с session_id.
- Сервер валидирует второй фактор: проверяет, что код совпадает, что он отправлен в нужном контексте, не истек, не использовался ранее.
Если проверка успешна – сервер помечает сессию как аутентифицированную и допускает пользователя к защищенным ресурсам.

Но безопасность 2FA зависит от того, какой именно фактор используется и как именно реализован этот процесс. SMS-код — это 2FA, но защита от перехвата у него минимальная, в то же время аппаратный ключ — тоже 2FA, взломать который практически нереально.
Типы 2FA
Рассмотрим основные методы, встречающиеся в реальной жизни:
- SMS-коды. Код подтверждения приходит по SMS.
- TOTP-коды (Google Authenticator, Steam Guard, etc.) – генерация одноразовых кодов целиком происходит на зарегистрированном устройстве
- Push-подтверждения (Microsoft Authenticator, Google) – подтверждение происходит через пуш-уведомление, отправленное на уже известное устройство
- Аппаратные ключи – используют криптографию, не отправляют код в сеть, не поддаются перехвату.
Как атакуют 2FA
Существует колоссальное количество методик атак на MFA, однако подавляющее большинство подобных атак требуют глубокого понимания процесса авторизации и ручного тестирования
- Отсутствие рейт-лимитов. Начнем с классики – в уязвимом приложении просто могут быть не предусмотрены рейт-лимиты и неважно, на чьей именно стороне:
- Пользователь может иметь неограниченное количество попыток ввода одноразового кода, т.е. может просто его подобрать, в то время как простые ограничения по IP либо сигнатурам запроса легко обходятся через IP Rotate и модификацию каждого нового запроса.
- Нет лимита на количество запросов OTP. Пользователь может бесконечно запрашивать новые OTP до тех пор, пока не подберет нужный.
- Отсутствие лимита на отправку кодов так же позволяет исчерпывать ресурсы компании
- Уязвимости на уровне сессии.
- Уязвимое приложение может позволить отключить либо изменить флоу двухфакторной аутентификации, при этом не требуя проходить двухфакторную аутентификацию.
- Puzzling атаки – в некоторых сценариях приложение запрашивает у пользователя прохождение 2FA, однако его можно обойти просто обратившись напрямую к нужному эндпоинту.
- Race Condition – при неграмотной реализации криптографической составляющей генератора OTP-кодов может возникнуть ситуация, что два разных запроса, отправленных одновременно, получат одинаковый OTP. Таким образом возникает состояние гонки, когда мы одновременно инициируем авторизацию с учетной записью жертвы и со своей учетной записью, а код двухфакторной аутентификации при этом одинаков для обоих.
- Проблемы в логике.
- OTP может быть повторно использован для разных действий – логин, сброс пароля, подтверждение операций и тд. Отсутствие контекста подтверждаемого действия может привести к тому, что OTP, сгенерированный с одной целью, может быть использован для совершенно другой.
- Бывают случаи, когда уже введенный OTP остается валидным уже после его отправки. Это значительно упрощает задачу перебора, поскольку нет необходимости автоматизировать дальнейшие действия после ввода OTP – можно просто ввести его повторно после проведенного брутфорса и закончить проведение атаки вручную.
- Host Header Injection - В уязвимой конфигурации веб-сервер может воспринимать заголовок Host HTTP-запроса как целевой ресурс и злоумышленник может обмануть веб-приложение, передав дублирующийся/вредоносный домен, на который и будет отправлен код подтверждения.
- Фишинг.
- Злоумышленник может создать фейковую страницу, повторяющую процесс авторизации целевого ресурса и заманить пользователя туда – таким образом он получит не только валидную учетную запись, но и действительную сессию на целевом ресурсе.
- Социальная инженерия. Злоумышленник может убедить службу поддержки целевого ресурса сбросить MFA или привязать новый фактор.
Практический кейс
Во время проведения ручного тестирования ресурсов у одного из клиентов мы обнаружили форму авторизации с ссылкой на страницу смены пароля.

Флоу смены пароля и авторизации оказался крайне простым: вводим почту, на почту отправляется код, вводим код

Меняем пароль / получаем доступ к аккаунту в зависимости от исходного действия.

Проблема крылась в отсутствии ограничения на количество попыток ввода этого самого одноразового кода, что позволило буквально перебрать его посимвольно

И, более того, после использования код не отзывался и его можно было ввести повторно и завершить угон аккаунта вручную:


По уязвимости был составлен подробный отчет, составлены инструкции по устранению и направлены клиенту.
Заключение
Уязвимости подобного рода невозможно выявить с использованием автоматических сканеров, однако наши специалисты отдела экспертного сопровождения при проведении ручных тестирований в обязательном порядке проверяют флоу авторизации / восстановления паролей и другие формы.