- PVSM.RU - https://www.pvsm.ru -

Достаём мастер-пароль из заблокированного менеджера паролей 1Password 4

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

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

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

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

Достаём мастер-пароль из заблокированного менеджера паролей 1Password 4 - 1

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

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

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

Достаём мастер-пароль из заблокированного менеджера паролей 1Password 4 - 2
Разблокировка 1Password 4 и восстановление мастер-пароля

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

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

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

Достаём мастер-пароль из заблокированного менеджера паролей 1Password 4 - 3

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

Достаём мастер-пароль из заблокированного менеджера паролей 1Password 4 - 4

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

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

Достаём мастер-пароль из заблокированного менеджера паролей 1Password 4 - 5

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

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

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

Достаём мастер-пароль из заблокированного менеджера паролей 1Password 4 - 6

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

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

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

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

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

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

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

Достаём мастер-пароль из заблокированного менеджера паролей 1Password 4 - 8

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

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

Достаём мастер-пароль из заблокированного менеджера паролей 1Password 4 - 9

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

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

Достаём мастер-пароль из заблокированного менеджера паролей 1Password 4 - 10

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

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

Достаём мастер-пароль из заблокированного менеджера паролей 1Password 4 - 11

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

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

Достаём мастер-пароль из заблокированного менеджера паролей 1Password 4 - 12

Уязвимость

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

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

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

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

Задача

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

Достаём мастер-пароль из заблокированного менеджера паролей 1Password 4 - 13

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

Эксплоит

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

Достаём мастер-пароль из заблокированного менеджера паролей 1Password 4 - 14

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

Достаём мастер-пароль из заблокированного менеджера паролей 1Password 4 - 15

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

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

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

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

Достаём мастер-пароль из заблокированного менеджера паролей 1Password 4 - 16

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

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

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

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

Достаём мастер-пароль из заблокированного менеджера паролей 1Password 4 - 17

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

Достаём мастер-пароль из заблокированного менеджера паролей 1Password 4 - 18

Резюме

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

Автор: m1rko

Источник [5]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/informatsionnaya-bezopasnost/309512

Ссылки в тексте:

[1] Washington Post: https://www.washingtonpost.com/technology/2019/02/19/password-managers-have-security-flaw-you-should-still-use-one/

[2] исследовании: https://www.securityevaluators.com/casestudies/password-manager-hacking/

[3] multipass: https://github.com/abednarek/Multipass

[4] HxD: https://mh-nexus.de/en/hxd/

[5] Источник: https://habr.com/ru/post/441166/?utm_source=habrahabr&utm_medium=rss&utm_campaign=441166