TOTP (одноразовый пароль по времени)
TOTP (Time-based One-Time Password, одноразовый пароль по времени) это алгоритм из RFC 6238, который превращает общий секрет и текущее время в короткий числовой код, по умолчанию меняющийся каждые 30 секунд. Он расширяет счётчиковый HOTP из RFC 4226 и именно его генерируют приложения-аутентификаторы, когда одноразовый код используется как второй фактор.
Как работает TOTP
TOTP построен на HOTP. RFC 4226 определяет HOTP(K,C) как усечённый HMAC-SHA-1 от общего секрета K и 8-байтового счётчика C. Он требует кодов не короче шести цифр и общего секрета не короче 128 бит, а рекомендует 160 бит. RFC 6238 заменяет счётчик временем: TOTP = HOTP(K, T), где T = (текущее время Unix - T0) / X с округлением вниз. По умолчанию шаг времени X равен 30 секундам, а T0 равно 0, то есть эпохе Unix, и вместо SHA-1 можно использовать HMAC-SHA-256 или HMAC-SHA-512.
У обеих сторон один и тот же секрет, обычно его один раз копируют из QR-кода, и каждая сторона вычисляет код самостоятельно. При входе на телефон ничего не отправляется. Сервер сравнивает введённое со своим результатом и допускает небольшое расхождение часов: RFC 6238 рекомендует учитывать не более одного шага времени на задержку сети. Там же сказано, что проверяющий не должен принимать повторную попытку уже подтверждённого одноразового кода.
Настройка TOTP для SSH через PAM
В Debian и Ubuntu модуль pam_google_authenticator.so входит в пакет libpam-google-authenticator. Каждый пользователь один раз создаёт секрет. По документации модуля, он сохраняется в ~/.google_authenticator:
google-authenticator -t -d -r 3 -R 30 -e 10
Эти ключи выбирают коды по времени, запрещают повторное использование кода, допускают не более 3 входов за 30 секунд и создают 10 аварийных кодов (это максимум). Затем подключите модуль к PAM и sshd:
# /etc/pam.d/sshd
auth required pam_google_authenticator.so
# /etc/ssh/sshd_config
UsePAM yes
KbdInteractiveAuthentication yes
AuthenticationMethods publickey,keyboard-interactive
Опция nullok позволяет входить без кода тем, у кого ещё нет секрета: на время внедрения это удобно, но потом её нужно убрать. Проверьте конфигурацию через sudo sshd -t, убедитесь, что timedatectl показывает синхронизированные часы, и тестируйте в новой сессии, не закрывая старую. Полный порядок действий описан в руководстве по двухфакторной аутентификации SSH по ссылке ниже.
Пределы, расхождение часов и типичные ошибки
- Фишинг. В NIST SP 800-63B-4 сказано, что аутентификация одноразовым кодом не устойчива к фишингу: введённый вручную код не привязан к сессии, и поддельный сайт может передать его настоящему, пока код действует.
- Повторное использование. Опция
-dреализует правило одного использования. Она ограничивает вход примерно одним разом в 30 секунд, зато проще заметить атаку «человек посередине». - Расхождение часов. По умолчанию окно модуля 3 кода (предыдущий, текущий и следующий), поэтому допускается около 30 секунд сдвига. Более широкое окно, предупреждает RFC 6238, расширяет и окно для атаки. Без
noskewadjмодуль может узнать ваш сдвиг после трёх входов подряд. - Подбор. Короткому числовому коду нужен лимит попыток, его задают
-rи-R. - Секрет на сервере. Первая строка
~/.google_authenticatorэто секрет в base32, а модуль по умолчанию требует права 0600. Кто может прочитать файл, тот сгенерирует верные коды, поэтому TOTP не защищает от скомпрометированной учётной записи на сервере. - Аварийные коды. Это одноразовые восьмизначные коды. Храните их офлайн.
Место TOTP в защите сервера
TOTP добавляет то, что у вас есть, к ключу, который вы уже используете для SSH, так что одного скопированного закрытого ключа для входа больше недостаточно. Это разумный второй фактор для учётных записей администраторов, и он бесплатен, но слабее аппаратного: CISA называет FIDO/WebAuthn широко доступным методом, устойчивым к фишингу, поэтому при возможности выбирайте аппаратный ключ, как описано в статье о FIDO2 и WebAuthn.
Внедряйте в таком порядке:
- Сначала завершите защиту SSH и настройте вход по ключам.
- Для изменений PAM и sshd следуйте руководству по двухфакторной аутентификации SSH.
- Сначала подключите администраторов, а автоматизации выдайте отдельные ограниченные ключи, ведь задание не умеет вводить код.
- Храните аварийные коды офлайн, держите под рукой консоль провайдера и знайте шаги из руководства по восстановлению доступа после блокировки SSH.
Статья о PAM объясняет стек модулей, который выполняет проверку кода.
Связанные термины: Двухфакторная аутентификация, PAM, FIDO2 и WebAuthn, Вход по ключам, SSH.
Часто задаваемые вопросы
Что означает TOTP и как он работает?
TOTP расшифровывается как Time-based One-Time Password, одноразовый пароль по времени. Сервер и приложение-аутентификатор знают общий секрет и независимо вычисляют код из этого секрета и текущего времени, который по умолчанию меняется каждые 30 секунд.
Почему мой код TOTP не подходит?
Чаще всего причина в расхождении часов устройства и сервера. Модуль Google Authenticator для PAM по умолчанию допускает около 30 секунд и может подстроиться под больший сдвиг после трёх входов подряд, поэтому проверьте синхронизацию часов обеих сторон.
Чем TOTP отличается от HOTP?
HOTP из RFC 4226 получает код из счётчика, который растёт при каждом использовании. TOTP из RFC 6238 заменяет счётчик текущим временем, поделённым на шаги, поэтому коды истекают сами.
Устойчив ли TOTP к фишингу?
Нет. В NIST SP 800-63B сказано, что аутентификация одноразовым кодом не устойчива к фишингу, потому что введённый код не привязан к сессии и его можно передать настоящему сервису. У аппаратного ключа FIDO2 такой слабости нет.
Что делать, если я потерял телефон с приложением?
Используйте один из аварийных кодов, созданных google-authenticator: до 10 одноразовых кодов, которые нужно хранить офлайн. Если их нет, понадобится другой путь, например консоль провайдера или режим восстановления, после чего можно создать новый секрет.
Хотите увидеть, в каком состоянии ваш сервер?
Запустите бесплатную read-only проверку сервера или откройте Security Lab и посмотрите цикл обнаружение, сдерживание, восстановление, проверка в действии.
Получить бесплатную проверку сервераОткрыть Security Lab