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

Уязвимость Account Manager в Android, о которой необходимо знать

Приветствую тебя, дорогой читатель!
Многие приложения используют возможности Account Manager(AM) в своих приложениях. Да и с одной стороны правильно делают, ведь этот инструмент позволяет упростить некоторые вещи. Он позволяет хранить пароль, токен, да и в принципе любые строковые данные юзера. Так же позволяет автоматически обновлять токен, если тот протухает, да и много других вещей. Но у этого удобства есть и другая сторона — безопасность. Из-за этого собственно я и написал данный текст.

Раз AM позволяет хранить такие важные данные как пароль и токен, то наверно он просто обязан это делать безопасно, ведь если они утекут, то ничего хорошего не получится. Вы можете сказать, что на рутованых андроид девайсах ничто не хранится безопасно, и я тут соглашусь. Однако если бы все ограничивалось только рутом, то не читать бы вам сие «произведение». Чтобы рассказать, ради чего мы тут собрались, я начну с самого начала.

Вообще для работы с AM в приложении нужно сделать несколько телодвижений и создать два компонента — наследника AbstractAccountAuthenticator и Service (подробней тут [1]). Последний придется зарегистрировать в манифесте приложения таким образом

        <service
            android:name=".account.AuthenticatorService"
            android:exported="false">
            <intent-filter>
                <action android:name="android.accounts.AccountAuthenticator" />
            </intent-filter>

            <meta-data
                android:name="android.accounts.AccountAuthenticator"
                android:resource="@xml/authenticator" />
        </service>

А еще, если вы заметили, то нам надо создать в ресурсах некий xml файл с именем authenticator.xml. Хотя название тут не важно, а важно содержимое. Оно то и играет ключевую роль рассказа. Выглядит файл внутри вот так

<account-authenticator 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:accountType="@string/account_type"
    android:label="@string/app_name" />

Параметр label — отвечает за название в списке аккаунтов в настройках девайса, а самое интересно несет в себе accountType. Без него приложение не сможет добавлять и получать аккаунты. А еще с помощью этого параметра можно перехватить аккаунты другого приложения даже на девайсах без рута. Давайте посмотрим, как это может произойти.
На устройстве существует приложение А с accountType = «someType», это приложение создает акаунт, добавляет в него токен, пароль и прочую информацию. В один прекрасный момент на устройство устанавливается приложение B с таким же accountType = «someType». И вот если удалить приложение A, то все созданные аккаунты перейдут во власть приложения B с полным доступом. Обратное тоже верно, аккаунты приложения B передадутся приложению A, если удалить B.

пример на видео

Опережая вопросы про подписи apk, это не зависит от того, каким ключем было подписано приложение, релизным или дебажным, передача произойдет в любом случае. Ужасно, правда?
Все это можно проделать в плоть до API версии 23. Исправлено только с выходом андроид 7.0(API 24). Печалит в этой ситуации ничтожно малый процент устройств с этой версией андроида. Кстати, узнал я об этой проблеме из доклада по безопасности в андроид [2]. К сожалению в тексте, пересказе презентации, об этом ничего нет вообще, а вот в видео об этом упомянули вскользь, не придав особого значения.

Так же что же ты предлагаешь? — можете спросить вы. А я предлагаю вам два варианта решения проблемы. Первый — продолжать пользоваться AM, но хранить в нем все важные данные в зашифрованном виде. Если вы перестали доверять AM, можно продолжать им пользоваться, но не хранить в нем важные данные и воспользоваться AM в связке со вторым вариантом. Второй — вообще отказаться от AM и пользоваться хранилищем, которое можно шифровать. Например SQLite в связке с sqlcipher [3] или Realm [4], который поддерживает шифрование из коробки. Я выбрал последний. Тут пример [5]для realm, где показано, как генерировать и хранить ключ шифрования.

Примеры кода в статье приводить не стал, так как в этом нет смысла. С исходниками жертвы [6] и перехватчика [7] вы сможете ознакомиться на гитхабе.
Спасибо за внимание!

Автор: andreich

Источник [8]


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

Путь до страницы источника: http://www.pvsm.ru/android/206393

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

[1] подробней тут: https://habrahabr.ru/company/e-Legion/blog/206210/

[2] доклада по безопасности в андроид: https://habrahabr.ru/company/yandex/blog/310926/

[3] sqlcipher : https://www.zetetic.net/sqlcipher/

[4] Realm: https://realm.io/docs/java/latest/#encryption

[5] Тут пример : https://github.com/realm/realm-java/tree/feature/example/store_password/examples/StoreEncryptionPassword

[6] жертвы: https://github.com/rovkinmax/AccountInterceptorVictim

[7] перехватчика: https://github.com/rovkinmax/AccountInterceptor

[8] Источник: https://habrahabr.ru/post/314414/?utm_source=habrahabr&utm_medium=rss&utm_campaign=best