Здравствуйте, меня зовут Виталий. Мне 25 лет, закончил магистратуру СПБГЭТУ «ЛЭТИ» в своем родном городе. Уже 10 лет занимаюсь программированием, из которых 4 пишу под Android. Автор многих Homebrew программ, известный под ником VITTACH, для Sony PlayStation Portable (PSP). Сегодня я бы хотел обсудить с вами проблему безопасности мобильных приложений. Разработчики из Google постоянно улучшают Android, находя и исправляя уязвимости не без помощи обширного сообщества, собранного благодаря программе Android Security Rewards, о которой мы поговорим позже. Тем не менее, проблемы все еще остаются, и наша общая задача как коммьюнити сообщать о них, чтобы их своевременно исправляли. Уязвимость о которой я буду говорить, относится к классу с Priority:​ P2 и Severity:​ S2, что согласно таблице в широком смысле означает: Проблему, которую необходимо решить в разумные сроки; Проблему, которая важна для большого процента пользователей и связана с основными функциями. Речь в статье пойдет о такой известной всем разработчикам вещи как Runtime permission, а именно – о возможности введения в заблуждение конечного пользователя путем демонстрации диалогового окна выдачи разрешения со своим текстом и иконкой поверх системного. Нетрудно догадаться, что подобный подход позволил бы разработчикам запрашивать у пользователя разрешение, скажем, к файловой системе, а по факту – к выдаче доступа к геопозиционированию, камере или чему-то еще. Не один раз задавался подобный вопрос на специализированных форумах, в частности на StackOverflow. Единственным правильным ответом было то, что это невозможно. И это действительно так: невозможно подменить текст в самом системном диалоге, но возможно его перекрыть своим. Runtime Permission впервые появились в Android 6.0 в ответ на потребность повышенного внимания в области выдачи dangerous-разрешений. Фактически основная идея состоит в том, чтобы взаимодействовать с пользователем при запросе разрешений через всплывающее окно. Поэтому теперь разрешения из списка dangerous необходимо запрашивать у пользователя как только они понадобятся приложению. android.permission_group.CALENDAR android.permission.READ_CALENDAR android.permission.WRITE_CALENDAR android.permission_group.CAMERA android.permission.CAMERA android.permission_group.CONTACTS android.permission.READ_CONTACTS android.permission.WRITE_CONTACTS android.permission.GET_ACCOUNTS android.permission_group.LOCATION android.permission.ACCESSFINELOCATION android.permission.ACCESSCOARSELOCATION android.permission_group.MICROPHONE android.permission.RECORD_AUDIO android.permission_group.PHONE android.permission.READPHONESTATE android.permission.CALL_PHONE android.permission.READCALLLOG android.permission.WRITECALLLOG android.permission.ADD_VOICEMAIL android.permission.USE_SIP android.permission.PROCESSOUTGOINGCALLS android.permission_group.SENSORS android.permission.BODY_SENSORS android.permission_group.SMS android.permission.SEND_SMS android.permission.RECEIVE_SMS android.permission.READ_SMS android.permission.RECEIVEWAPPUSH android.permission.RECEIVE_MMS android.permission.READCELLBROADCASTS android.permission_group.STORAGE android.permission.READEXTERNALSTORAGE android.permission.WRITEEXTERNALSTORAGE   Для отображения системного диалога в Android есть GrantPermissionsActivity, который запускается после запроса на выдачу разрешений и отображает нам диалог со знакомым интерфейсом. А раз это Activity, которая перекрывает UI нашего приложения, значит можно попробовать пойти тем же путем и создать свою Activity, которая уже будет перекрывать системную. Теперь давайте посмотрим на пример: Пусть есть Activity с флагом android:windowIsTranslucent=true (чтобы сделать Activity с прозрачным фоном, позволяющим видеть, что за ним стоит) и оно запускается другим Activity , который я назову фоновым. Визуально вы все еще можете видеть некоторую часть фонового Activity через прозрачные пиксели в Activity переднего плана. Синий – это активное Activity с полупрозрачным окном, а фиолетовый – Activity прямо под ним. Что произойдет с Activity, если вы поместите приложение в фоновый режим? Фоновая активность, несомненно, будет убита, а передний план деятельности может выжить, пока вы не переключитесь на другое приложение. И вот что произойдет, когда вы вернете свое приложение на передний план: Фоновая Activity создается, а затем onResume и onPause вызываются по порядку. Затем оживает передний план Activity. Идея заключается в том, чтобы перекрыть эту Activity в стеке своей собственной с кастомным диалогом, но так чтобы оставить возможность взаимодействовать с кнопками системного диалога. И вот это уже – возможно! Для демонстрации использован язык программирования Kotlin Создать стиль К сожалению, невозможно настроить эти параметры иначе как из стилей Прописать в манифесте Activity со стилем Создать PermissionActivity со своим layout В методе onCreate написать код: Здесь мы используем трюк с использованием следующих флагов: FLAG_NOT_FOCUSABLE: window, в которой установлен параметр FLAG_NOT_FOCUSABLE, не может взаимодействовать с методом ввода; FLAG_NOT_TOUCH_MODAL: разрешит отправку любых событий за пределы окна в окна позади него, в противном случае он сам будет использовать все события указателя, независимо от того, находятся ли они внутри окна; FLAG_NOT_TOUCHABLE: это окно никогда не может получать события касания. В MainActivity вызвать запрос  И сразу после этого из MainActivity запустить другую активити: PermissionActivity.  PermissionActivity с прозрачным фоном и отсутствием фокуса и прокидыванием событий на Activity позади себя запустится и позволит добиться перекрытия системного диалога с сохранением полного взаимодействия с ним. Результат достигнут! Хотя Runtime Permission появились в версии Android 6.0, но до версии 7.1.1 эту уязвимость использовать не получится, т.к. ранние версии Android ругаются на обнаружение перекрытия при попытке нажатия на кнопку Разрешить. Если вы попробуете запустить мой код на версии Android 6.0, то получите это предупреждение. По неизвестной мне причине, Google отказался от этих ограничений в новых версиях. Я подал заявку и приложил все объяснительные и демонстрационные документы по данной уязвимости. В данный момент заявка находится в стадии рассмотрения, поэтому я не могу разглашать подробности, потому что подписал соответствующее соглашение. Для удобства эксплуатации уязвимости мною была написана библиотека     Android developer