Собесов

Security Engineering Яндекса — безопасная аутентификация веб-сервиса

Кейсы и метрикиApplication securityСредняяMiddle

Условие

Друг хочет написать веб-сервис с регистрацией и входом. Какие рекомендации вы дадите ему по безопасной реализации аутентификации? Перечислите несколько предложений.

Решение

1. Хранение паролей

  • Никогда не хранить в открытом виде. И не «MD5», и не «SHA-256». Только современные slow KDF: bcrypt, scrypt, argon2id.
  • Пароли + соль (salt), уникальная для каждого пользователя, длиной ≥ 16 байт. Соль хранится рядом с хешем.
  • Cost-параметры подбираются так, чтобы один хеш считался ~100 мс на текущем железе. Для argon2idm=64MiB, t=3, p=1 как стартовая точка (OWASP).

2. Политика паролей

  • Минимум 8–12 символов (NIST 800-63B), без обязательных «спец-символов и Big/small» — это снижает энтропию.
  • Проверять по базе утечек (HaveIBeenPwned k-anonymity API: посылаем первые 5 символов SHA1, получаем список суффиксов).
  • Запрет «топ-100 распространённых паролей».
  • Не требовать смену пароля периодически без причины (NIST ушёл от этого).

3. Защита от перебора

  • Rate-limiting на эндпоинт логина: например, не более 5 попыток / 5 минут / IP, плюс на аккаунт независимо от IP.
  • Captcha после нескольких неудач.
  • Account lockout с экспоненциальной задержкой (или вместо лока — задержка ответа). Полный лок открывает DoS-вектор.
  • Login-функции отвечают одинаково при «нет такого пользователя» и «неверный пароль» — иначе утечка существующих логинов.

4. Многофакторная аутентификация (MFA)

  • TOTP (Google Authenticator, RFC 6238) — обязателен как опция.
  • WebAuthn / FIDO2 — gold standard, защищает от фишинга.
  • SMS-OTP — допустим, но не основной: SIM-swap.
  • При установке MFA — печатать «recovery codes», 8–10 одноразовых.

5. Сессии

  • Сессионный токен — криптографически случайный (≥ 128 бит энтропии), на сервере мапится на user_id.
  • В HttpOnly + Secure + SameSite=Lax/Strict cookie. JS не должен иметь доступ к токену.
  • Идemпотентный logout — обязательно инвалидирует токен на сервере.
  • Регенерация ID после логина (защита от Session Fixation).
  • Истечение по неактивности (idle timeout, ~30 мин) и абсолютное (~12-24 часа).

6. JWT — аккуратно

Если используется JWT:

  • Только подписанные RS256/EdDSA, не HS256 с шаренным секретом на клиенте.
  • Не хранить в localStorage (XSS-риск). Только HttpOnly cookie.
  • Короткий TTL (15 мин) + refresh-token rotation.
  • Запретить алгоритм none (CVE-2015-2951).

7. Защита от CSRF

  • Если используете cookie-based сессии — CSRF-токены для всех state-changing запросов.
  • Либо SameSite=Strict + double-submit cookie + проверка Origin/Referer.

8. Восстановление пароля

  • Ссылка с одноразовым криптослучайным токеном, TTL ≤ 1 час, single-use.
  • Не отправлять текущий пароль на почту (это значит — он был восстановим из БД, что плохо).
  • После сброса — инвалидировать все активные сессии пользователя.
  • Generic-ответ: «Если такая почта зарегистрирована — мы отправили ссылку».

9. Регистрация и валидация email

  • Подтверждение email через одноразовую ссылку (TTL).
  • Не отдавать «такая почта уже зарегистрирована» — это user enumeration. Лучше: «инструкция отправлена на почту».

10. HTTPS, HSTS, secure-headers

  • Только TLS 1.2+, обязательный Strict-Transport-Security: max-age=31536000; includeSubDomains; preload.
  • Content-Security-Policy для защиты от XSS (особенно если токен в localStorage / любой рендеринг user-input).
  • X-Frame-Options: DENY или CSP frame-ancestors 'none' против clickjacking.

11. Логирование и алертинг

  • Логи логинов (успех/провал) — без паролей, с IP/User-Agent.
  • Алерт на «новое устройство» / «новая страна».
  • SIEM-правила на массовый brute-force.

Подводные камни

  1. MD5/SHA — это хеши, не KDF. Они рассчитываются миллионами в секунду на GPU. Только bcrypt/argon2/scrypt.
  2. Сложные требования к паролю, как 1 заглавная + 1 цифра + 1 спецсимвол, дают пользователям предсказуемые паттерны (Password1!). Лучше длина + проверка по утечкам.
  3. JWT в localStorage = XSS-крах. Все думают, что localStorage «удобнее», но любой XSS = слив токена.
  4. PUT /reset-password?token=... без проверки одноразовости даёт атаку повторного использования при перехвате ссылки.
  5. Email-validation без подтверждения: regex проверяет формат, но не реальность. Без confirm-email возможны фейковые регистрации.
  6. Брутфорс не только пароля. Атакуют username (enumeration), сессионные токены (если короткие), reset-token (если предсказуем).
  7. «Запомнить меня» на год = огромное окно компрометации. Делать «remember me» через долгоживущий refresh-token с возможностью отозвать.

Эталонный ответ

Argon2id для паролей; rate-limiting + одинаковые ответы на login; обязательный TOTP/WebAuthn; HttpOnly+Secure+SameSite сессии; CSRF-токены; HSTS+TLS 1.2+; secure-headers; одноразовые reset-токены с TTL и инвалидацией всех сессий.

Хочешь увидеть разбор?

Зарегистрируйся бесплатно — откроется развёрнутое решение этой задачи и ещё 4 на выбор.

Зарегистрироваться и увидеть разбор
Уже есть аккаунт? Войти