Скидання пароля - «чорний хід» в обліковий запис. Якщо він слабший за вхід, атакують саме його.
Вимоги до токена скидання:
- випадковий і довгий - криптографічно стійкий генератор (
random_bytes,Str::random()), не похідний від email, часу чи id; - одноразовий - після використання недійсний;
- короткий термін дії - хвилини чи година;
- у базі - хеш токена, а не сам токен: витік бази не дає активних посилань для скидання;
- прив'язаний до облікового запису - токен одного користувача не працює для іншого.
Процес:
- користувач вводить email - відповідь однакова незалежно від того, чи існує обліковий запис («Якщо обліковий запис існує, ми надіслали лист»);
- лист із посиланням, що містить токен; відправка - через чергу (щоб час відповіді не видавав існування облікового запису);
- перехід за посиланням - форма нового пароля; токен перевіряється порівнянням хешів у постійному часі;
- новий пароль - з тими самими правилами, що й при реєстрації (довжина, перевірка у базі витоків);
- після зміни: токен знищено, усі інші сесії й токени API користувача відкликано, лист-сповіщення «ваш пароль змінено».
Пастки:
- отруєння посилання через заголовок Host: якщо URL у листі будується з
Hostзапиту, а сервер приймає довільні хости, зловмисник ініціює скидання для жертви з підробленимHost: evil.example- жертва отримує справжній лист з посиланням на домен зловмисника. Захист - фіксованийAPP_URLдля посилань і перевірка дозволених хостів; - витік токена через
Referer: сторінка скидання завантажує сторонні ресурси (аналітику, шрифти) - токен з URL потрапляє вReferer.Referrer-Policy: no-referrerна цій сторінці; - відповідь на секретні питання замість пошти - слабкий механізм, відповіді легко знайти в соцмережах;
- автоматичний вхід після скидання без MFA - обхід другого фактора;
- необмежена кількість запитів - спам листами на чужу адресу.
У Laravel брокер паролів (Password::sendResetLink, Password::reset) зберігає хеш токена в password_reset_tokens, має термін дії й обмеження частоти (throttle у config/auth.php). Після скидання варто викликати Auth::logoutOtherDevices() чи прибрати сесії й токени Sanctum.