Новые инструменты, старые методы. Проводим обратную разработку и находим фатальный недостаток 1Password.

Все любят менеджеры паролей. Они великолепны по многим причинам. Лично у меня в менеджере более 200 записей. С таким большим количеством конфиденциальных данных в одном месте важно понимать масштаб ущерба в случае компрометации вашей записи, будь то вредоносные программы, эксплоиты или просто компьютер, оставленный без присмотра на несколько минут. Washington Post недавно опубликовала статью, основанную на нашем исследовании. Эта статья помогает довести людей, что не все менеджеры паролей одинаковы.

Я свято верил, что заблокированный парольный менеджер надёжно защищён. Если кто-то получит доступ к моему компьютеру, то максимум может рассчитывать на кучку случайных байтов, поскольку информация надёжно вычищается из памяти.

Это верно для 1Password 4 (Обратите внимание, что последняя версия на сегодня седьмая). Прежде чем перейти на него несколько лет назад я проверил, что в памяти действительно нет паролей в открытом виде, когда менеджер в заблокированном состоянии. Так что в случае компрометации злоумышленнику придётся иметь дело с зашифрованным хранилищем.


Хранилище заперто!

В этом состоянии в памяти нет ни парольных записей, ни мастер-пароля. Очень разумно и правильно, и 1Password 4 прошёл эту проверку. Или нет?

Чтобы избавить от скучных деталей, скажу сразу: мы смогли восстановить мастер-пароль из заблокированного инстанса в 1Password 4, как показано ниже.


Разблокировка 1Password 4 и восстановление мастер-пароля

В анимации показано, что 1Password 4 сначала разблокируется нормальным способом, а затем запирается. После этого мы запускаем нашу утилиту multipass, которая успешно восстанавливает пароль. Утилита эксплуатирует неправильную обработку поля ввода пароля в 1Password 4, чтобы восстановить обфусцированный буфер мастер-пароля, деобфусцировать его, автоматически разблокировать 1Password 4 и, наконец, отобразить мастер-пароль в консоли.

Скучные детали


Первый шаг при оценке менеджера паролей: проверить наличие мастер-пароля в памяти в открытом виде. Это возможно в любом hex-редакторе, который способен взаимодействовать с пространством памяти процесса. Например, бесплатный редактор HxD. С его помощью можно открыть пространство памяти 1Password 4.



Мы сразу попадаем в первую читаемую область пространства памяти 1Password 4.


Пример представления памяти HxD

Пока ничего особенного. Но можно выполнить поиск. Например, как выглядит ситуация, если набрать пароль в окне разблокировки 1Password 4, но не нажать кнопку «Разблокировать»:


Запертое хранилище 1Password 4 с введённым мастер-паролем в поле

Наверняка пароль где-то в памяти?

Открываем HxD, но поиск строки с нашим мастер-паролем (“Z3Superpass#”) не даёт результатов.



Похоже, 1Password как-то шифрует или обфусцирует форму по мере её ввода. Если процедура работает правильно, то всё хорошо.

Погружаемся глубже


Чтобы узнать, почему мастер-пароль нельзя найти в памяти, когда он явно присутствует в диалоговом окне разблокировки, следует найти код, который с ним взаимодействует. Тут есть несколько способов. Можно отследить обработку событий клавиатуры и мыши путём локализации ‘GetMessage’, ‘PeekMessage’, ‘GetWindowText’ или других Windows API, которые обычно обрабатывают пользовательский ввод. Так мы найдём буфера, куда записываются нажатия клавиш, а через них выйдем на подпрограмму шифрования/обфускации. Но это долгий и подверженный ошибкам процесс, особенно с большими фреймворками, которые иногда очень странно управляют памятью, так что для отслеживания буфера придётся сделать множество копий и преобразований.

Вместо этого используем собственный инструмент Thread Imager, созданный для обратной разработки «странных» проприетарных протоколов на прикладном уровне. Он поможет определить, в каком месте памяти 1Password 4 взаимодействует с нашим мастер-паролем. Инструмент «автоматически» идентифицирует области кода в 1Password 4, которые взаимодействуют с обфусцированным паролем (он просто подсвечивает инструкции, которые взаимодействуют с интересующими данными, для дальнейшего анализа). Результат выглядит примерно так:


Thread Imager находит код 1Password 4, который взаимодействует с необфусцированным мастер-паролем

Поскольку мастер-пароль хранится в памяти в обфусцированном виде, то инструмент должен первым делом показать, в каком месте происходит обфускация.

Фрагмент из первого результата показывает, что первое появление мастер-пароля сопровождается переходом кода с адреса 0x7707A75D на 0x701CFA10.


Подробная запись в Thread Imager подсвечивает переход кода с с 0x7707A75D на 0x701CFA10, при этом на буфер с мастер-паролем ссылаются регистры EAX и ECX

Изучение этого места 0x7707A75D в отладчике (x64dbg) подтверждает нашу теорию. Действительно, впервые строка ‘Z3superpass#’ встречается при завершении работы функции декодирования ‘RtlRunDecodeUnicodeString’ из библиотеки ntdll.dll.



После небольшого анализа ясно, что для обфускации пароля используются именно эти две функции: ‘RtlRunEncodeUnicodeString’ и ‘RtlRunDecodeUnicodeString’. Так мастер-пароль прячут от примитивного копирования из памяти, вот почему раньше мы не могли найти его в hex-редакторе.

Если изучить закодированный буфер в конце работы функции RtlRunEncodeUnicodeString, то зашифрованная строка с мастер-паролем выглядит так:


Зашифрованный мастер-пароль

После RtlRunDecodeUnicodeString’ он декодируется:


Расшифрованный мастер-пароль

Интересно, что эта область сохраняется по тому же адресу 0x00DFA790 и мы буквально можем наблюдать её изменение при вводе пароля в окно разблокировки 1Password 4:



Уязвимость


‘RtlRunEncodeUnicodeString’ и ‘RtlRunDecodeUnicodeString’ — простые функции, которые изменяют строку простой операцией XOR. Это не так уж плохо: похоже, это стандартный метод маскировки всех нативных редактирующих управляющих элементов Windows при установленном флаге ‘ES_PASSWORD'.

Проблема в том, что после разблокировки 1Password 4 зашифрованный мастер-пароль не очищается из памяти.

Хуже того, он остаётся в памяти и после блокировки 1Password 4. То есть у нас есть заблокированное хранилище паролей, но с зашифрованным мастер-паролем в памяти.

И что ещё хуже, поскольку мы взаимодействуем с диалоговым окном ввода мастер-пароля, одна и та же область памяти повторно используется вместе с тем же значением XOR, что даёт нам лёгкий доступ к закодированному буферу для создания эксплоита.

Задача


Чтобы создать надёжный эксплоит для 1Password 4, нужно получить более чёткое представление, как мастер-пароль обрабатывается рабочими процессами программы. С помощью вышеупомянутых инструментов мы построили диаграмму выходных данных (рисунок ниже).



По такой диаграмме легче понять, где и какие задействуются библиотеки, чтобы надёжно идентифировать области в памяти, откуда можно извлечь мастер-пароль.

Эксплоит


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



Чтобы извлечь его, нужно вызвать процедуру в 1Password 4, которая инициирует ‘RtlRunEncodeUnicodeString’ и ‘RtlRunDecodeUnicodeString’. Таким образом она покажет расположение буфера памяти с закодированным мастер-паролем.


Область памяти с обфусцированным мастер-паролем

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

Похоже, единственный способ вызвать ‘RtlRunEncodeUnicodeString’ и ‘RtlRunDecodeUnicodeString’ — это ввести в символ в диалоговое окно ввода мастер-пароля. Так мы получаем нужный буфер. Но мы не знаем длину пароля.

Мы решили эту проблему путём перехвата кода, который обращается к первому символу нашего буфера, блокируя попытку изменения. Эта подпрограмма находится в цикле обработки сообщений управляющего элемента в comctl32, который обрабатывает управление буфером соответствующих элементов. Вызов ‘memmove’ со смещением 0x70191731 перезаписывает буфер введённым символом:


(Побочный эффект: выделенная строка (жёлтая) обновляет всю строку пароля)

Теперь мы, наконец, получили всё, что нужно для создания эксплоита. Следующие шаги позволят нам извлечь мастер-пароль:

  1. Хук ‘memmove’, чтобы предотвратить перезапись первого байта мастер-пароля.
  2. Хук ‘RtlRunEncodeUnicodeString’, чтобы получить расположение буфера обфусцированного мастер-пароля.
  3. Хук ‘RtlRunDecodeUnicodeString’ для обращения к обфусцированному буферу, полученному на предыдущем этапе.
  4. Ввод символа в поле ввода пароля и отказ от шага 1 (сохранение всего мастер-пароля), перенаправление шага 2 на шаг 3 для декодирования обфусцированного мастер-пароля.

Для выполнения всех этих действий создаём DLL с кодом обработчика всех этих хуков. Библиотека внедряется в процесс 1Password 4, отправляет один символ в диалоговое окно мастер-пароль, запуская шаги memmove, RtlRunEncodeUnicodeString и RtlRunDecodeUnicodeString, которые мы можем перехватить — и производя нашу магию по восстановлению обфусцированного мастер-пароля. Большая часть магии происходит в DetourRtlRunEncodeUnicodeString, это хук для функции ‘RtlRunEncodeUnicodeString’, показанный ниже:



Что приводит нас к окончательному результату: разблокировка запертого хранилища 1Password 4 любой версии при помощи глючной процедуры в используемых Windows API:



Резюме


Когда мы впервые углубились во внутренности 1Password 4, то ожидали встретить какую-то сложную систему защиты и ожидали, что вся секретная информация будет очищаться из памяти, как это происходит в процедурах PBKDF2 и других областях, где используется мастер-пароль. Соответствующие записи тоже очищаются. Однако по недосмотру поле ввода пароля рассматривается как стандартный элемент управления Windows API со скрытым паролем, что подрывает безопасность 1Password 4.

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


  1. Ghool
    21.02.2019 14:52

    В свежей версии-то с этим как?


    1. xeon
      21.02.2019 23:17

      Судя по полной статье, там ещё хуже. www.securityevaluators.com/casestudies/password-manager-hacking Как страшно жить, сам сижу на 1Password4

      After assessing the legacy 1Password4, we moved on to 1Password7, the current release. Surprisingly, we found that it is less secure in the running state compared to 1Password4. 1Password7 decrypted all individual passwords in our test database as soon as it is unlocked and caches them in memory, unlike 1Password4 which kept only one entry at a time in memory. Compounding this, we found that 1Password7 scrubs neither the individual passwords, the master password, nor the secret key (an extra field introduced in 1Password6 that combines with the master password to derive the encryption key) from memory when transitioning from unlocked to locked. This renders the “lock” button ineffective


  1. hex_none
    21.02.2019 15:04
    +3

    Для извлечения пароля нужно запустить код эксплоита на атакуемой машине. А можно и пустить, например, кейлоггер, который тоже украдёт пароль. От проникновения вирусни уже ничто не защитит(особенно если она залезет в ядро). А так да, для гигиены память нужно чистить. Может, забыли.


    1. site6893
      21.02.2019 15:27

      а как же Intel® SGX?


      1. hex_none
        21.02.2019 15:35

        Мне кажется, что он тут и не нужен. Имеется в виду, что есть возможность получить информацию другим путём. До попадания её в ПО. Ну, можно конечно, сделать спец.драйвера для защиты информации, но и их, скорее всего, получится обойти.


    1. deril
      21.02.2019 16:30
      +1

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


      1. dimka11
        22.02.2019 22:23

        А как получить доступ к памяти? Для входа в учётную запись после выхода из спящего режима нужно вводить пароль.


        1. dunaevai
          23.02.2019 15:13

          Если топорно, то cold boot. Это не говоря о хитрых устройствах, которые имея хот плаг умеют в DMA.


  1. amarao
    21.02.2019 15:15
    +1

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

    Вы точно не хотите менеджер паролей с открытыми исходными текстами, чтобы этот аудит был проще?


    1. vilgeforce
      21.02.2019 16:39

      Открытый исходный код, как показывает практика, панацеей не является. А лично со своей колокольни скажу, что бинарники на C/C++ зачастую проще анализировать в IDA Pro, чем в сорцах.


      1. amarao
        21.02.2019 16:49

        Панацей не является, а вот аудит всё-таки легче по сырцу делать.


        1. vilgeforce
          21.02.2019 16:51

          Действительно зависит от. Граф вызовов в/из конкретной процедуры в IDA Pro — секунды. В сорцах я не знаю как строить такие графы


      1. Duss
        21.02.2019 20:47

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

        Кол-во людей владеющих знаниями С++ больше, чем тех, кто хорошо знает ассемблер.

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


    1. Fi5t
      21.02.2019 16:40
      +1

      Хотим. Ваши предложения? Чтобы с таким же уровнем качества как у 1Password.


      1. amarao
        21.02.2019 16:49

        keepassx


        1. vooft
          21.02.2019 17:40

          1Password интегрируются с ios, браузерами и всем прочим.
          Я много лет использовал keepassx + dropbox, но в конце-концов удобство победило.


          1. Duss
            21.02.2019 20:53
            +1

            Может я параноик, но у меня победила секьюрность. Я в принципе не очень доверяю решению, которое как 2 пальца подставляет мои пароли в браузеры, в другое ПО и т.д.

            Также можно сказать, что простой JavaScript вытащит ваш пароль из 1Password, ещё до того как вы нажали кнопочку логин


            1. SergeyMax
              22.02.2019 08:23

              Также можно сказать, что простой JavaScript вытащит ваш пароль из 1Password, ещё до того как вы нажали кнопочку логин
              JavaScript «вытащит» ваш пароль и без всякого 1Password. И даже без JavaScript, ха-ха.


            1. pharrell
              22.02.2019 14:10

              Каким это таким способом JS вытащит пароль из 1Password?


          1. Dee3
            21.02.2019 21:55

            Через плагины можно прикрутить интеграцию с браузером, с iOS обещают в ближайшем апдейте


          1. Cenzo
            22.02.2019 00:50
            +1

            Про интеграцию с мобильными девайсами: пока всё что я видел, требовало включения accessibility mode, который позволяет приложению читать абсолютно все поля. А от этого как-то сильно не по себе.


            1. ilyamodder
              22.02.2019 12:45

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


        1. rostislav-zp
          21.02.2019 17:40

          Тоже им пользуюсь на win/Osx.правда не из-за надёжности, о которой мне неизвестно, а из-за бесплатности


      1. edacval
        21.02.2019 18:02

        1. mgremlin
          21.02.2019 19:10

          Он тормоз.
          В браузере открытие плагина — 10 секунд, блин. Даже LastPass был удобнее.
          и еще десяток глюков помельче…


          1. l0rda
            21.02.2019 21:58

            У меня в локалке стоит сервер bitwarden, в браузере открытие занимает чуть меньше секунды, но тоже немного раздражает задержка. Ios вроде подкрутили, стал шустро открываться. Но альтернатив нет, чтобы на всех mac/ios девайсах и хранить у себя секреты. Keychain не в счёт.


            1. mgremlin
              22.02.2019 15:17

              Спасибо за наводку, надо подумать.
              Сервер паролей на сервере, для доступа к которому нужен пароль, хранимый на сервере паролей…
              есть тут где-то какая-то колючка, не знаю где :-)

              кстати, вопрос: нет ощущения, что тормозит именно облачная часть Bitwarden? Ну, то есть, если переключить клиента на чужое облако — все тормозит, обратно на свою локаль — летает. Нет такого? А то стек десктопного клиента под линуха лично мне чемпионом скорости не кажется.


              1. l0rda
                22.02.2019 18:17

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


          1. leiocalyx
            22.02.2019 14:01

            10 секунд — это чтобы открыть и ввести пароль? =)

            На firefox 65 открывается где-то за секунду, достаточно шустро чтобы не обращать внимания.


            1. mgremlin
              22.02.2019 15:12

              На firefox чутка быстрее, согласен. Особенно на том, который Developer Edition. Но даже там на моем компе несколько секунд вынь да положь.
              LastPass работал так, что я даже не задумывался. Но — проприетарщина, нет дескотопов/линуха, etc…

              Короче, нет в мире совершенства.


          1. agendr
            22.02.2019 23:39

            Сейчас появился неплохой конкурент ему Myki.com для персонального пользования пока бесплатен, и SAASPASS ещё, но тот вообще полу энтерпрайз и faceid touch никак не прикрутят или я не нашёл


      1. terrakok
        22.02.2019 10:40
        +1

        Конечно https://bitwarden.com/! Можно хостить на своем сервере. Открытые исходники.
        Знакомый безопасник проверял, и сказал, что все ок.


  1. super-guest
    21.02.2019 23:06
    +1

    Это верно для 1Password 4 (Обратите внимание, что последняя версия на сегодня седьмая).
    А у меня при автопроверке обновлений говорит, что шестая — самая последняя… Как так?


    1. KoppeKTop
      21.02.2019 23:33

      Просто 7 можно получить только ещё раз заплатив) с 6 автоматом не обновится.


  1. ClearAirTurbulence
    21.02.2019 23:33

    1Password для меня умер, когда перелез в облако и полностью перешел на рельсы saas. Я понимаю, что им есть хочется, но регулярно выкатывать баксов по 20 или сколько они там хотят я как-то не готов. Ну а когда из плагин к хрому старой версии перестал работать, пересел на enpass, ибо keepass как-то уж слишком интерфейсно-отстал.


    1. dmitrybarabash
      22.02.2019 01:33

      1Password по-прежнему продает standalone-лицензии для 7-й версии и мобильных приложений, а базу позволяет хранить в Dropbox, например. Хранить базу в их облаке и для этого переходить на модель оплаты подписки не обязательно (хотя они, конечно, уговаривают, для них такой сценарий выгоднее).


      1. Ghool
        22.02.2019 08:50

        Забавно, что браузерные плагины для онлайн и оффлайн версий разные, хотя оба требуют наличия установленного по на компе.
        И плагин для онлайн-версии удобнее (кнопка «вставь пароль» появляется прямо в поле ввода пароля, не нужно искать её на панели браузера)


  1. rettub
    22.02.2019 02:34

    Я пользуюсь LastPass.


    1. ffs
      22.02.2019 12:55

      Я тоже, но интересно, насколько он хорош и следует ли пересесть на что-то другое.


      1. Anastasia_K
        22.02.2019 14:04

        пересела с LastPass на Bitwarden. Теперь вспоминаю LastPass как страшный сон не понимаю, как можно было пользоваться той поделкой.


  1. lorc
    22.02.2019 02:49
    +1

    Не совсем понятно зачем вообще хранить мастер-пароль хоть в каком-то виде, когда есть PBKDF2 и scrypt.


    1. lostmsu
      22.02.2019 11:02

      А расшифровывать вторичные пароли как?


      1. lorc
        22.02.2019 15:00
        +2

        Ну это ж стандартный метод. Так например шифруют файловые системы:

        1. Генерируем случайный ключ.
        2. Этим ключом шифруем данные.
        3. Из мастер-пароля через PBKDF2 порождаем ключ, которым и шифруем ключ из п.1
        4. Результаты шифрования из п.2 и п.3 сохраняем на диск.

        В результате: ключ зависит целиком от пароля. Если ввести неправильный пароль — получим мусор вместо данных. Если надо поменять пароль — просто перешифровывем ключ из п.1, сами данные перешифровывать не нужно. Хранить мастер-пароль в любом виде — тоже не нужно.

        На самом деле, учитывая что база паролей довольно маленькая, можно исключить промежуточный ключ и шифровать ее на ключе, порожденном из мастер-пароля напрямую. В случае смены пароля — перешифровываем всю базу — она небольшая.


  1. Dark_Angel
    22.02.2019 12:28

    А что скажите насчет SafeInCloud? Я пользуюсь на десктопе + анроиде. Файл синхронизирую через ownCloud (есть встроенная возможность синкать в другие облака)


  1. vagonovozhaty
    22.02.2019 12:37

    У них (1P) на форуме идет жаркая дискуссия на эту тему discussions.agilebits.com/discussion/101551/article-just-published-in-washington-post-is-saying-1password-and-others-have-security-flaws/p5
    Если коротко, то они говорят, что все в порядке.


  1. abagnale
    22.02.2019 12:42

    Там их (1Password) "Chief Defender Against the Dark Arts, Jeff Goldberg" отвечает:



    Мне на самом деле очень нравится 1Password, и хотелось бы верить (потому что экспертизы не хватает), что в нём более-менее безопасно хранить пароли, но такие вещи оставляют микротрещины в упомянутом доверии.


    Вот ещё например с версии 7.2.4 1Password на Маке стал доставать диалогом при запуске, где требует поместить себя непременно в /Applications. А зачем? Мне не нужна интеграция с браузером, и я хочу хранить приложение в ~/Applications. Поддержка так и не ответила, говорят что "Apple так требует", при этом приложение как работало нормально из ~/Applications, так и работает, только теперь этот раздращающий алерт каждый раз выскакивает.


  1. IvUs
    22.02.2019 14:39

    Если вам действительно дороги ваши пароли — не пользуйтесь никакими менеджерами.


    1. dady_KK
      22.02.2019 16:35

      Если честно, это выглядит как «если вам дороги ваши пароли — не заводите себе много доступов, а то все не запомните»


  1. vyo
    22.02.2019 15:37

    Т. е., для кражи пароля мы вставляем исполняемый код в процесс? Если я правильно понимаю, с такими правами можно тупо записывать нажатия клавиш без особой заморочки.

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


  1. Vlad_01
    23.02.2019 09:22

    А где ссылки на Thread Imager, или вся эта статья это его реклама?