Все снапшоты попадают в рай

image altСейчас все мы используем банковские приложения. Это удобно, быстро и, как нам кажется, безопасно. Банки даже ввели дополнительные pin-коды для того чтобы даже если вы потеряете свой телефон или если он попадет в руки постороннего человека ваши средства и конфиденциальные данные были защищены. И это так классно! Банки заботятся о нашей безопасности!

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

Для примера я заскринила абстрактные банки, на абстрактных страницах. И сейчас сразу же задам вам вопрос: вы собрались перевести деньги своей маме/подруге/собаке, вы уже находитесь на странице перевода и вышли из приложения, чтобы скопировать код из sms (если вы в порыве паранойи запретили банковскому приложению доступ), или посмотреть какую-нибудь информацию. Но когда вы вновь решите вернуться в ваше банковское приложение, какой экран вы выберите?

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

И дело не только в том абстрактном банке, я просмотрела несколько наиболее популярных банков и все они страдают такой проблемой.

image alt


Интересно, но на стороне iOS содержимое экрана в таск менеджере скрыто.

image alt


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

Давайте для начала разберемся как вообще работает экранный менеджер (Recents screen)


image alt


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

Что происходит на самом деле (кратко):


  • Приложение перешло в фоновый режим
  • Диспетчер окон помещает снапшот приложения в GraphicBuffer
  • GraphicBuffer отправляется в SystemUI через Binder для предварительного просмотра приложения


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

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

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

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

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

Как запретить системе делать снапшоты


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

Вы можете установить параметр для activity:

android:excludeFromRecents = "true"


Однако этот способ нарушит логику взаимодействия пользователя с приложением, так как приложение вообще не будет показываться в Recents Screen.

if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB) {
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE);
}
setContentView()


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

Помимо этого есть способ отслеживания onPause (). Но тут придется постоянно держать заготовленное view в состоянии View.GONE, чтобы когда приложение уходит в фон можно было сделать View.VISIBLE. Но это также будет работать не очень надежно, так как, к сожалению, невозможно контролировать время снятия снапшота.

К слову, а телега смогла, ну кто бы сомневался:) На скрине секретный чат, в данном случае используется именно FLAG_SECURE.

image alt


Так почему же банки скрывают содержимое приложения на платформе iOS, которая итак считается безопаснее (что есть заблуждение), и оставляют как есть для платформы Android? Скорее всего, им просто не нравится как приложение будет выглядеть в Recents Screen. То есть просто белое полотно. В iOS же реализация позволяет делать красиво. В итоге мы получаем ущерб безопасности в угоду красоты. Возможно вам все равно, пока ваши деньги лежат там, где вы хотели бы, а конфиденциальность данных непоколебима. Но готовы ли вы платить?…

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

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

Я решила сделать себе вызов и писать что-нибудь полезное на регулярной основе. Буду публиковать зарисовки в своем канале @miproblema в телеграмм, а потом уже собирать в полноценные посты. Всем пока-пока.

© Habrahabr.ru