Обработка истечения срока действия и проверка кодов 2FA

В настоящее время я планирую реализацию 2FA, чтобы пользователи должны были предоставлять код через SMS для некоторых действий, таких как вход в систему. Я также буду использовать такие инструменты, как Google Authenticator, но я не хочу, чтобы пользователи заставляли загружать приложение, поэтому мне также нужно отправлять коды по SMS (или, возможно, по электронной почте).

Мой план пока таков:

  1. Пользователь хочет войти и запрашивает код
  2. Бэкэнд генерирует числовой код, сохраняет его в хешированном виде в БД и возвращает идентификатор (или селектор) записи базы данных во внешний интерфейс.
  3. Frontend отображает поле ввода кода рядом с адресом электронной почты и паролем пользователя.
  4. Код отправляется пользователю по SMS/электронной почте
  5. Теперь у пользователя есть 5 минут, чтобы отправить селектор + код + адрес электронной почты + пароль на серверную часть, где все они будут проверены.

2 вопроса по этому поводу:

1) Обработка истечения срока действия кода

Моя первая идея заключалась в том, чтобы хранить код в базе данных только в хешированном виде, как пароль, но мне пришлось бы реализовать 5-минутное истечение срока действия самостоятельно. Конечно, я мог бы добавить еще один столбец с отметкой времени для проверки срока действия, но я бы предпочел что-то более безопасное.

Теперь я думаю о том, чтобы сохранить код внутри объекта утверждений веб-токена json в базе данных и установить срок действия этого токена на 5 минут. Таким образом, по истечении 5 минут синтаксический анализ веб-токена для сравнения его с кодом, отправленным пользователем, завершается ошибкой. Это позволило бы мне в случае сценария атаки просто изменить секрет веб-токенов, и все существующие коды мгновенно стали бы недействительными.

Хороший ли это подход? Или вы, ребята, видите в этом какие-то проблемы, или, может быть, есть лучшие способы справиться с этим? Или, может быть, есть библиотека для хеширования паролей с датой истечения срока действия?

2) Проверка и обработка атак грубой силы

Поскольку я хочу отправить пользователю только 6- или максимум 8-значный числовой код, мне придется реализовать какую-то защиту от атак методом грубой силы (допустим, злоумышленник знает адрес электронной почты и пароль пользователя).

Что я хочу сделать:

  1. Если однажды был отправлен неверный код, увеличьте количество неудачных попыток этой конкретной записи базы данных кода += 1
  2. Если код превышает 3 неудачных попытки, аннулируйте код в базе данных и попросите пользователя запросить новый код.
  3. Когда пользователь запрашивает новый код, попросите его подождать 1 минуту, прежде чем он сможет запросить новый код, сохраните дату последней неудачной попытки в качестве метки времени в записи базы данных пользователей, а также 1-минутную задержку.
  4. Если третий код не работает, сохраните новую отметку времени и удвойте задержку до 2 минут. ... и так далее. После 3 неудачных кодов также потребуется JS Challenge (Google Recaptcha).
  5. После 5 попыток я блокировал учетную запись и ждал, пока пользователь свяжется с нами.

Это безопасный подход к проверке кодов?

Интересно, рассматривали ли вы возможность принятия одной из систем аутентификации как услуги? Onelogin, Okta, Ping, Auth0 и т. д. Вы сможете работать с ключами FIDO, SMS 2f, различными системами федерации и т. д. прямо из коробки.

O. Jones 20.12.2020 13:02

И не забывайте, что вы должны заранее проверить номер SMS, чтобы злоумышленники не подделали эту проверку.

O. Jones 20.12.2020 13:10

Эй, Джонс, конечно, пользователь должен подтвердить устройство при регистрации. И да, я рассматривал некоторые из этих сервисов, но у большинства из них есть недостатки. Некоторым требуется приложение, некоторые не могут отправлять токены по электронной почте, некоторые стоят дорого, и большинство из них хранят данные в США, где могут возникнуть проблемы с GDPR. Кроме того, я хочу понять, в чем заключаются проблемы при его создании, и посмотреть, правильный ли мой подход :)

Felix Hagspiel 20.12.2020 13:19
SQL Injection: Атаки в реальной жизни и как это вредит бизнесу
SQL Injection: Атаки в реальной жизни и как это вредит бизнесу
Один-единственный вредоносный запрос может нанести ущерб вашему бизнесу. Уязвимости вашего кода могут привести к:
0
3
469
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я думаю, что вы переусердствуете с безопасностью своих шестизначных кодов подтверждения, используя JWT.

Независимо от того, как вы ими управляете, вы должны сделать их недействительными по истечении срока их действия или при использовании. Хороший способ сделать это — дать каждому коду строку в таблице, включая отметку времени истечения срока действия. Затем УДАЛИТЕ строку для кода, когда пользователь представляет ее. Всякий раз, когда вы ищете эти коды, добавляйте WHERE expires > NOW() к запросу. И регулярно DELETE строки с истекшим сроком действия.

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

Эта схема, кстати, полезна для генерации всех видов одноразовых номеров. (Числа используются один раз.) Одноразовые числа пригодятся для многих целей, таких как сброс пароля по электронной почте.

Другие вопросы по теме