Одноразові коди можуть бути цілком правильними на вашому телефоні, і все ж сервер відхилить їх тієї ж секунди. Обидві сторони обчислюють ту саму функцію зі спільного секрету й поточного кроку часу, тому розбіжність у часі дає розбіжність у коді. Через це дрейф годинника стає не просто незручністю, а несправністю, значущою для безпеки.

Тут важливі два годинники, і виправлення видимого — це те, що люди роблять першим. Той, який зазвичай потребує уваги, — інший.

Код — це функція часу, а не пароль

TOTP бере спільний секрет і лічильник, похідний від поточного часу, пропускає обидва через хеш із ключем і обрізає результат до короткого десяткового рядка, як визначено в RFC 6238. Лічильник просувається на кожному кроці часу, зазвичай на тридцять секунд, тому той самий секрет дає нове значення, коли крок змінюється. Перевіряльник перераховує очікуване значення для поточного кроку й порівнює, що потребує того самого секрету й того самого уявлення про теперішнє. Пароль залишається придатним для повторного використання, доки його не змінять, а це значення спливає на межі, якої клієнт не бачить.

Тому один код працює, а наступний зазнає невдачі за мить. Це також пояснює, чому копіювання коду з повідомлення в чаті — така ненадійна звичка.

Два годинники мають збігатися, а не один

Матеріал реєстрації — це перше спільне, а час — друге. Якщо секрет правильний, а годинники розходяться більше за дозволене вікно, кожне згенероване значення потрапляє в неправильний крок і відхиляється. Якщо годинники збігаються, а секрет неправильний, кожне значення також відхиляється, і обидві невдачі виглядають однаково на екрані входу. Розділити їх означає перевірити запис облікового запису й час окремо, саме в такому порядку.

Годинник перевіряльника заслуговує такої ж перевірки, як і годинник пристрою. Сервер із несправним джерелом часу відхиляє правильні коди всіх користувачів одразу, і звіти описуватимуть раптову аварію, а не дрейф. Цей зразок варто розпізнавати, бо його виправлення належить серверу, а не сотні телефонів.

Скільки коштує розширення вікна

Реалізації можуть приймати код із сусіднього кроку, щоб поглинути невеликі відмінності, і ця терпимість — проєктне рішення, а не безкоштовне налаштування. Кожен додатковий крок множить кількість значень, чинних у будь-який момент, а саме цього й хоче атакувальник, який вгадує. Правило проти повторів важливе з тієї ж причини, адже код, прийнятий двічі, — це код, що корисно витік. Адміністратор, який розширює вікно, щоб заглушити скарги, міняє реальну властивість на косметичне поліпшення.

Виправлення годинника — це ремонт, а розширення вікна — заспокійливе. Перше усуває причину, друге її приховує.

Перевірте обидва годинники, перш ніж повторити спробу

Прочитайте час на пристрої та на сервері й порівняйте зсуви, а не показаний місцевий час. Наведені нижче команди показують стан синхронізації й необроблений момент UTC на хості або сервері Linux. Виконайте їх на обох кінцях, перш ніж змінювати будь-яке налаштування автентифікації.

timedatectl
date -u +'%Y-%m-%dT%H:%M:%SZ'
chronyc tracking
timedatectl timesync-status

Зсув, виміряний у секундах, нешкідливий, виміряний у хвилинах пояснює відмову, а система, яка не повідомляє жодного джерела синхронізації, є кандидатом на обидва. Порівняйте дві позначки часу UTC безпосередньо, оскільки місцевий час містить часовий пояс, якого алгоритм ніколи не бачить. Якщо зсуви малі, а коди все ще не працюють, припиніть налаштовувати годинники й натомість огляньте запис реєстрації. Повторні спроби проти заблокованого облікового запису ускладнюють спостереження початкової несправності.

Запишіть час відмови, зсув і текст помилки, а спільний секрет залиште поза цим. Підтримка може працювати з першими трьома й ніколи не повинна бачити четверте.

Схожі статті