Доброго времени суток.
Я хотел бы рассказать вам о проблемах 2FA аутентификации на устройствах Android 4.4.2 KitKat и о решении, которое в нашем случае прекратило долгие поиски.

Некоторое время назад мы с коллегами решили добавить Двухэтапную аутентификацию (Two factor authentication или для краткости 2FA) для нашего маленького офисного сервера на базе Ubuntu Server.

2FA это дополнительный уровень безопасности и приятное дополнение к уже существующему механизму аутентификации. Кроме обычной пары логин + пароль от пользователя, выполняющего авторизацию, требуется цифровой ключ, который динамически изменяется каждые 30 секунд и генерируется устройством, находящимся во владении пользователя. Для генерации ключа мы использовали Приложение Google authenticator и мобильный телефон на платформе Android. После разовой настройки приложение генерирует коды, имеющие срок жизни в 30 секунд, точно такие же коды генерирует сервер. При аутентификации коды сравниваются.

Так как данные не передаются от сервера и хранятся только на устройстве — этот механизм является более безопасным, чем отправка кодов подтверждения (например, как 3D-secure SMS подтверждение в банковских системах).


Пошаговых инструкций о настройках сервера в сети оказалось неожиданно много. В них все очень просто и доходчиво. Я руководствовался этой статьей.

После настроек сервера установили на телефон Lenovo p780 приложение Google Authenticator, «прочитали» телефоном с монитора QR-code и получили заветные циферки для авторизации. Перед тем как перезагрузить SSH не забывайте сохранить резервные ключи для восстановления доступа.

И вот, все готово к использованию! Перезагружаем SSH, заходим на сервер, указываем пароль, после пароля нас просят предъявить Verification code, переписываем его с телефона и… снова просят указать пароль?!!! Выглядит это так:
ssh user@server.ru
Password: <вводим пароль>
Verification code: <вводим код с телефона>
Password: <?!!, вводим пароль еще раз>
Verification code: <вводим код с телефона>
Password: <еще раз вводим пароль>
Verification code: <еще раз вводим код>
user@server.ru's password: <еще раз пароль>
Permission denied, please try again.
user@server.ru's password: <снова вводим пароль>
Received disconnect from xx.xxx.xx.xx: 2: Too many authentication failures for user


Вначале думали, что ошибка допущена в настройках, но испробовав несколько мобильных устройств стало очевидно, что коды генерируемые на Android 4.4.2 KitKat приложением Google Authenticator всегда ошибочны.

«Решения», которые удалось найти и их результаты:


  1. Если откатить версию Android, начинает работать корректно. (с этим «решением» работали какое то время, но решили двигаться дальше)
  2. Так как проблема сводится к некорректным часовым поясам — многие решения направлены именно на их исправление. Приложение TimeZone Fixer действительно может помочь с этой проблемой, однако часть приложений после его использования начинает отображать ошибочное время и потребуется чинить их вручную. (решение имеет свои минусы и риски. вся информация о приложении доступна на сайте 4pda)
  3. Подгонять время вручную. Если честно этот способ у нас так и не заработал. Перевести часы вручную и тем самым синхронизировать время на телефоне и сервере. Увы, все попытки ничего не дали, хотя были люди утверждающие, что у них заработало. В любом случае перспектива потерять функцию часов в телефоне не самая приятная...
  4. Синхронизация часов внутри настроек приложения Google authenticator (в нашем случае без результатов, однако были комментарии, что кому то помогло)


Финальное решение проблемы: FreeOTP


За время поиска решения в сети я уже натыкался на GitHub приложения Google Authenticator, в трекинге ошибок есть наша, и в качестве решения предложено:
«You can used FreeOTP Authenticator(by Red Hat) instead of Google Authenticator until someone fix it.»


Долгое время мне казалось, что рекомендуется использовать другой механизм-аутентификатор, который нужно ставить на сервер вместо Google, поэтому я усердно искал другие решения. Хотелось заставить работать именно Google authenticator, но на самом же деле рекомендуют использовать другое приложение для Android, а серверная часть остается без изменений.

Приложение FreeOTP Authenticator от компании Red Hat. После настройки по тому же QR-коду все начало работать без необходимости что то корректировать.

К сожалению я не могу указать вам причину возникновения ошибки в приложении Google authenticator, но надеюсь, что мой печальный опыт поможет сэкономить чье-то время.

Буду рад вашим комментариям! Спасибо за внимание.

Комментарии (42)


  1. mifki
    04.05.2015 03:35
    +3

    > Долгое время мне казалось, что рекомендуется использовать другой механизм-аутентификатор, который нужно ставить на сервер вместо Google, поэтому я усердно искал другие решения. Хотелось заставить работать именно Google authenticator

    Странная мысль — сам протокол никакого отношения к Гуглу не имеет, какое приложение генерирует коды, всё равно. И таких приложений довольно много, причем, по крайней мере на iOS, родное Гугловское из плохих. После того, как при восстановлении из бекапа оно потеряло все коды, никому его не рекомендую.


    1. ssh4
      04.05.2015 09:02
      -7

      Ну и глупо. Вероятность бага одинакова как в коде от Гугла так и в коде от Васи Пупкина.
      Вася Пупкин может оттестировать обновление на 10 девайсах, Гугл на 1000е другой. Да и фикс выкатить быстрее. А один раз наступив на такие грабли, думаю надолго запомнят, что надо обновления такой важной утилиты тестировать тщательнее.
      Ну и не говоря о том, что рентабельность «воровать» данные для Гугла близка к нулю, а вот Вася Пупкин, фиг знает, что там решил улучшить для повышения профита.


      1. mifki
        04.05.2015 09:12
        +3

        Ерунда какая-то, по-вашему приложения от Гугла или другой крупной компании всегда лучше и стабильнее?


        1. ssh4
          04.05.2015 09:39

          Я говорю о том, что такому приложению от крупной компании уровня Гугл больше доверия по той причине, что встраивать бэкдоры в подобное приложение им нерентабельно.
          Допустить ошибку в коде одинаково могут как неизвестный разработчик так и крупная компания.

          И есть шанс, что раз допустив такую ошибку, в дальнейшем они приложат больше усилий для проверки всех возможных вариантов до выпуска релиза. Благо у Гугл на это ресурсов больше.


          1. mifki
            04.05.2015 10:13

            Оставив в стороне вопрос бэкдоров (я не из парноиков), есть еще такое дело, как побочные и заброшенные проекты/приложения, и у крупных контор с этим дело даже хуже. Google Authenticator для iOS не обновлялся больше года с октября 2013 до декабря 2014, и до этого больше двух лет с июля 2011 до октября 2013. Причем и это обновления в основном для поддержки новых версий системы и устройств, но ни о каких багфиксах речи не идет. И проверять, не пропадут ли у меня коды опять и с новой версий, у меня никакого желания нет.


            1. ssh4
              04.05.2015 10:44
              +2

              Почему заброшенное?
              Если приложение работает, в нем нет критических багов, и свою функцию оно выполняет на 100%, нужно ли гнаться за ежемесячными апдейтами?
              Или вам надо чтобы Google Auth в конечном итоге превратился в тяжеловесного монстра с кучей никому ненужных функций?

              А вероятность словить баг при новом обновлении есть у любого приложения.
              По уму конечно, стоит иметь резервный вариант на случай сбоя. Но уж лучше на десктопе, а не два идентичных по функциям приложениях на смартфоне. Тем более что можно тупо утопить смартфон в туалете. Даже не дожидаясь граблей от кодеров ;)


              1. mifki
                04.05.2015 15:30

                Угу, видимо, они посчитали, что даже защита пин-кодом тоже никому не нужная функция.


                1. ssh4
                  04.05.2015 15:42
                  -1

                  Я согласен с тем, что оно не идеальное.
                  С появлением Touch ID проблема непинкодности приложения конечно сильно уменьшилась.
                  Так как трубка по дефолту залочена и доступ к ней могут иметь только доверенный круг лиц.

                  Я бы честно после того бага, какой то «внешний» бекап добавил, чтоб точно быть спокойным,
                  что если что, бекап настроек имеется.
                  Но тут уже да, включается неповоротливость корпорации. Да и платформа неприоритетная ;)


    1. Kichee Автор
      04.05.2015 12:05

      Странная мысль — сам протокол никакого отношения к Гуглу не имеет, какое приложение генерирует коды, всё равно. И таких приложений довольно много, причем, по крайней мере на iOS, родное Гугловское из плохих. После того, как при восстановлении из бекапа оно потеряло все коды, никому его не рекомендую.

      Когда знаете об этом — это действительно логично, а вот когда сталкиваешься с этим в первый раз, а при этом и на сервере и на мобильном устройстве приложение называется одинаково, чувствуется нерушимая связь и четкая зависимость одного от другого.

      Спасибо за ваш комментарий. Проблемы, возникающие при восстановлении из бекапа явились для меня новостью. На всякий случай попробую испытать восстановление заранее пока не сталкнулся с проблемой в боевой ситуации.


      1. khim
        04.05.2015 20:10

        Не уточняется какие именно проблемы возникают при восстановлении из бекапа. Как известно одноразовые пароли можно генерировать на основе времени (каждые XX секунд — новый OTP), а можно — на основе счётчика (каждое обращение просто «рождает» новый OTP, но они все должны быть использованы, пропуск более 2-3 штук приводит к рассинхронизации клиента и сервера и необходимости сброса всей системы).

        Понятно, что во втором случае никакое «восстановление из бекапа» невозмножно — и это не баг, а фича. В самом Гугле Google Authenticator используется, разумеется, только в таком режиме (так как он безопаснее), так что, возможно, о проблемах с восстановлением для «временной» генерации просто никто не подумал.


  1. mikhaelkh
    04.05.2015 05:49
    +2

    Ну почему сразу всегда ошибочны? В 1/1000000 случаев может и совпасть)


    1. toxicdream
      04.05.2015 06:35
      +2

      Автору надо было сказать «не рабочий».
      По аналогии со сломанными часами — они два раза в сутки показывают точное время.


  1. institor
    04.05.2015 09:59
    +3

    Использовал это приложение начиная с Android 4.0.4, никогда не было никаких проблем. Странно. Может вы с часовыми поясами напутали?


    1. sergey_dobrodey
      04.05.2015 11:38
      +1

      Аналогично, 4.4.2 и даже смартфон тот же, lenovo p780. С проблемами в работе приложения не сталкивался.


    1. Kichee Автор
      04.05.2015 12:18
      -2

      Использовал это приложение начиная с Android 4.0.4, никогда не было никаких проблем. Странно. Может вы с часовыми поясами напутали?

      Это маловероятно. Первоначально с ошибкой я сталкнулся, когда устройство работало на своей «заводской» прошивке. Никаких кустомизаций на тот момент не применялось.


      1. bormotov
        04.05.2015 15:10

        timezone info в андроидеах отдельно не обновляется, в отличии от реальной жизни.

        Я с такой ошибкой как вы не сталкивался, но версию про «что-то с часами», проверил бы детальнее


        1. Vendict
          04.05.2015 20:15
          +2

          Я пытался на сходном аппарате на MTK6589 на 4.4.2 экспериментировать. Как только часовые пояса не менял — не подходит код и всё, сегодня же FreeOTP Authenticator сразу сработало.


        1. Kichee Автор
          04.05.2015 21:03

          Я с такой ошибкой как вы не сталкивался, но версию про «что-то с часами», проверил бы детальнее


          С изменением времени и часовых поясов предпринималось несколько попыток. В частности на 4pda рекомендуют для этих целей приложение ClockSynk (в той же ветке про timezone fixer). Выставив корректное время без смещения пробывали менять часовые пояса в большую и меньшую сторону. То же самое проделовали с временем на устройстве, но ни одна из комбинаций не дала рабочие коды.

          Кстати интересное наблюдение — при «правильном» времени и часовом поясе первые 2 цифры кода всегда совпадают с корректным кодом (открытым в этот момент на FreeOTP).


          1. astlock
            04.05.2015 22:36

            Аналогичные опыты делал на Lenovo S860. Ничего не помогло, ни руты, ни клоксинки, ни пояса. И да, первые цифры иногда совпадали с корретными кодами из афйона:) FreeOTP сегодня поставил — как в аптеке.


  1. gurinderu
    04.05.2015 10:15
    -2

    У меня была аналогичная проблема из-за лага до сервера гугла. Нужно правильно задавать величину смещения в секундах.


    1. GAS_85
      04.05.2015 14:08

      Не понимаю, как тогда это исправляет FreeOTP? Вносит свой «компенсирующий» лаг?


  1. darkdimius
    04.05.2015 10:24

    Вы пробовали Authy? Я использую его, тк он поддерживает больше типов 2FA.


    1. grossws
      04.05.2015 17:51
      +1

      И бонусом хранит ваши ключи для 2fa на своих серверах. Это, конечно, упрощает перенос на другое устройство, но является серьезным фактором риска, который стоит учитывать.


      1. darkdimius
        04.05.2015 17:53

        С любыми другими приложениями, у вас также нет никакой гарантии.
        Если нужна безопасность повыше — можно использовать YubiKey NEO, он тоже умеет TOTP. И из него ключи не вытянуть никак.


        1. grossws
          04.05.2015 18:20

          google-authenticator (для андроида живёт в отдельном репозитории) — это open source, что позволяет посмотреть на его потроха и убедиться, что всё нормально.

          Кстати, в версии для андроида они сделали подстройку времени по серверам гугла (т. е. считают разницу времени между их серверами и устройством, и учитывают её при генерации кодов).

          Yibikey neo мне более интересен тем, что на нём есть openpgp-апплет (у меня хранятся на нём три rsa2048 ключа: для подписи, расшифровки и ssh). Правда, проблемы с gpg-agent'ом периодически возникают: иногда после очередного отключения/подключения ключа он его не видит (хотя pcsc_scan видит прекрасно).

          gpg
          -> % gpg --card-status
          
          Application ID ...: D27600012401020000060350xxxx0000
          Version ..........: 2.0
          Manufacturer .....: Yubico
          Serial number ....: 0350xxxx
          Name of cardholder: Konstantin Gribov
          Language prefs ...: en
          Sex ..............: мужской
          URL of public key : http://...
          Login data .......: xxx
          Signature PIN ....: принудительный
          Key attributes ...: 2048R 2048R 2048R
          Max. PIN lengths .: 127 127 127
          PIN retry counter : 3 3 3
          Signature counter : xxx
          Signature key ....: D18B CC7F BA42 15F9 7EE9  FA26 E128 84E1 7319 D40C
                created ....: 2015-01-09 00:29:29
          Encryption key....: 3541 7899 380F 6D25 FA44  56E9 518F C0EA F2C2 628E
                created ....: 2015-01-09 00:30:05
          Authentication key: 131F 0381 D136 B020 5B75  B06F 639A B38B 307F F7C5
                created ....: 2015-04-24 13:50:31
          General key info..: pub  rsa2048/E12884E17319D40C 2015-01-09 Konstantin Gribov <.......@gmail.com>
          sec#  rsa4096/xxxxxxxxxxxxxxxx       создан: 2015-01-09     годен до: никогда   
          ssb   rsa2048/E12884E17319D40C       создан: 2015-01-09     годен до: никогда   
          ssb   rsa2048/518FC0EAF2C2628E       создан: 2015-01-09     годен до: никогда   
          ssb   rsa2048/639AB38B307FF7C5       создан: 2015-04-24     годен до: никогда
          


          1. darkdimius
            04.05.2015 18:26

            google-authenticator (для андроида живёт в отдельном репозитории) — это open source, что позволяет посмотреть на его потроха и убедиться, что всё нормально.

            У вас нет гарантии что он собран из того исходника без патчей.

            Yibikey neo мне более интересен тем, что на нём есть openpgp-апплет

            Надеюсь вы в курсе developers.yubico.com/ykneo-openpgp/SecurityAdvisory%202015-04-14.html По сути ключи там не защищены PIN-ом.

            «Поддержка» totp была и на старых (простых yubikey)

            Новые Neo тоже не знают про время и требуют приложение на хосте: github.com/Yubico/yubioath-desktop


            1. grossws
              04.05.2015 18:49

              У вас нет гарантии что он собран из того исходника без патчей.
              У большого количества людей есть возможность вытащить соответствующих apk, распаковать и пройтись jad'ом (хз как он для dex называется, но не суть важно). Или собрать из исходников на гитхабе и сравнить получившийся apk (за исключением подписей).

              Наличие такой возможности (сравнить) сродни фальсифицируемости в научном познании. В случае отсутствия исходников остаётся только реверс-инжиниринг, который требует существенно больших затрат.

              Надеюсь вы в курсе developers.yubico.com/ykneo-openpgp/SecurityAdvisory%202015-04-14.html По сути ключи там не защищены PIN-ом.
              В курсе. Печаль для всех, кто наследует эту проблему от javacardopenpgp. Для эксплуатации, правда, требует физического доступа к машине (который точно также позволяет перехватить ввод pin или passphrase для обычного), так что для меня не добавляет и не убавляет ничего в рисках при использовании. В любом случае, токен несколько увеличивает безопасность, т. к. ключ присутствует не всё время, а только при аутентификации/подписи/расшифровке против обычных ключей, доступных всё время.


              1. mickvav
                04.05.2015 19:37

                Да и никто не мешает таки пересобрать apk ручками, собсно.


          1. isden
            04.05.2015 22:47

            > google-authenticator (для андроида живёт в отдельном репозитории) — это open source, что позволяет посмотреть на его потроха и убедиться, что всё нормально.

            Не совсем:

            This open source project allows you to download the code that powered version 2.21 of the application. Subsequent versions contain Google-specific workflows that are not part of the project


            1. grossws
              04.05.2015 23:00

              Понятно. Эта информация и сейчас есть, только чуток запрятана в wiki проекта на github.


      1. mifki
        05.05.2015 06:29

        Это необязательная функция.


  1. usefree
    04.05.2015 10:38

    А еще можно просто на любом компьютере с python сгенерировать этот OTP как вот тут описано.


  1. ibKpoxa
    04.05.2015 11:28
    +1

    Хочу OPT приложение, чтобы при запуске спрашивало дополнительный PIN/пароль, вы не знаете такого?


    1. EminH
      04.05.2015 11:42

      Знаем :)
      Token2 Mobile OTP
      (пна некоторых андроид-устройствах глюки с расширением, под iphone можете комфортно пользоваться)


  1. astlock
    04.05.2015 11:36

    Ох, черт побери, Спасибо! Я уже и iphone надумал покупать, т.к. по иронии судьбы там все работает.


  1. EminH
    04.05.2015 11:44

    Вполне можете свое приложение сваять: habrahabr.ru/company/token2/blog/249921


  1. Andrii_Z
    04.05.2015 12:54
    -1

    Только вот для Faceboox, Gmail, Dropbox, Live.com (Microsoft), Lastpass Google Authenticator генерирует правильные коды на Kitkat 4.4.2 на Samsung s3
    Может, проблема в Lenovo?


    1. Vendict
      04.05.2015 20:13

      Нет, проблема в ветке 4.4.2 для MTK видимо. Почитайте отзывы на Google Authenticator на маркете, и видимо Гуглу на эти отзывы плевать.


      1. khim
        05.05.2015 01:15

        Если проблема не воспроизводится ни на одном Nexus-устройстве, то шансов на то, что её починят, катастрофически мало, да.


  1. stavinsky
    04.05.2015 14:09
    +5

    Полагаю проблема связана именно с часовыми поясами. У меня например стоит часовой пояс минск и все прекрасно работает.
    То есть, если я правильно понимаю, время должно совпадать с часовым поясом. Например если вы ставите Москву и потом корректируете руками время — будет фигня. А если вы правильно подбираете часовой пояс — все будет хорошо


    1. EminH
      04.05.2015 14:14
      +1

      все верно, по стандарту TOTP используется timestamp привязанный к UTC


  1. Denai
    04.05.2015 14:59

    т.е. проблема вызвана другой проблемой (часовые пояса), которая решается вайпом или рутованием? А 4.4.2 чем выделается?