Много уже написано и сказано про биометрическую аутентификацию в android приложениях. И это не прошло бесследно. Вижу много приложений где флоу аутентификации биометрия+пин-код сделан по всем канонам безопасности. Но дьявол кроется в деталях. И сегодня я покажу как всего один флаг способен умножить на 0 отлично выстроенную систему аутентификации. Речь пойдет об одном широко известном приложении 🤐
Разведка
Если в реализации биометрической аутентификации не используется CryptoObject, то разговаривать дальше не имеет смысла. Такая аутентификация не нужна. Поэтому в первую очередь я пошел искать CryptoObject
и инициализацию Cipher
-а для него.
|
|
Довольно типичный код, никаких потрясений. Даже padding отключен. Все по канонам информационной безопасности! Осталось понять как создается ключ шифрования.
|
|
Здесь тоже все прекрасно, ключ создается в AndroidKeyStore и не смотря на отсутствие StrongBox-a, реализация все еще достойная. Но флаг setUserAuthenticationRequired все портит.
When generating or importing a key into the AndroidKeyStore you can specify that the key is only authorized to be used if the user has been authenticated. The user is authenticated using a subset of their secure lock screen credentials (pattern/PIN/password, biometric credentials).
This is an advanced security feature which is generally useful only if your requirements are that a compromise of your application process after key generation/import (but not before or during) cannot bypass the requirement for the user to be authenticated to use the key. Подробнее
Далее по коду приложения были найдены операции шифрования с использованием этого ключа, а значит разработчик исходил из того, что эти операции станут возможны только после прохождения биометрической аутентификации. Но в данном случае эта система не работает из-за неправильно созданного ключа, что дает возможность обойти биометрическую аутентификацию и попасть в приложение. Также это дает возможность осуществлять операции дешифровки данных находясь уже в контексте приложения.
Эксплуатация
Для обхода биометрической аутентификации я буду использовать Frida и такой скрипт:
|
|
Все, что он делает - перехватывает вызов метода authenticate() и говорит приложению, что аутентификация прошла успешно. Магия заключается в том, что в момент запуска приложения, ключ, который должен стать доступен после успешного предъявления биометрии - уже находится в памяти. А значит все, что нужно сделать - убрать надоедливый диалог. После чего приложение само расшифрует все данные и будет работать по обычному сценарию.
Ссылки
- Authenticate me. If you can… - аутентификация по пин-коду и биометрии
- PINkman - библиотека для реализации пин-кода в приложении
- Видео-урок по реализации биометрической аутентификации в приложении
- Цикл статей от Google по биометрической аутентификации: