Данная статья является переводом соответствующей статьи Aditya Agrawal. Оригинал доступен по ссылке.

В предыдущем посте я познакомил вас с архитектурой Android, а также объяснил назначение различных её слоёв, но не рассказал о самом верхнем уровне, т.е. Приложения. Так что в этом посте я расскажу об уровне Приложений Android и функционировании его компонент, не забывая о безопасности.

Приложения для Android написаны на языке программирования Java. Инструменты, входящие в SDK для Android, компилируют ваш код — вместе со всеми файлами данных и ресурсов — в APK (Android PacKage), который является архивом с окончанием .apk. Один APK включает в себя всё содержимое приложения для Android и является файлом, который используют устройства на базе Android, чтобы установить приложение.

3_part_1

APK-файл является архивом, который обычно содержит следующие файлы и папки:

  • AndroidManifest.xml: файл AndroidManifest.xml является контролирующим файлом, который сообщает системе, что делать со всеми компонентами верхних уровней (а конкретно: Activity (активность), Services (службы), Broadcast Receivers (обработчики широковещательных сообщений) и Content providers (поставщики услуг), описанные ниже) в приложении. Он также указывает, какие требуются привилегии. Этот файл может быть представлен в виде двоичного XML-файла Android, который может быть преобразован в удобочитаемый XML с помощью таких инструментов, как android-apktool или Androguard, которые будут рассмотрены в предстоящем посте.
  • Папка META-INF:
    • MANIFEST.MF: файл Manifest
    • CERT.RSA: сертификат приложения
    • CERT.SF: список ресурсов и подписи SHA-1 соответствующих строк файла MANIFEST.MF.
  • lib: папка, содержащая скомпилированный код, специфичный для уровня программного обеспечения процессора. Папка разбита на несколько подпапок:
    • armeabi: скомпилированный код только для процессоров на базе ARM
    • armeabi-v7a: компилированный код только для всех процессоров на базе ARMv7 и выше
    • x86: компилированный код только для процессоров x86
    • mips: компилированный код только для процессоров MIPS
  • res: папка, содержащая ресурсы, не скомпилированные в файл resources.arsc (см. ниже).
  • assets: папка, содержащая активы приложения, которые могут быть извлечены с помощью AssetManager.
  • classes.dex: классы, скомпилированные в файл формата .dex, который понимает виртуальная машина Dalvik
  • resources.arsc: файл, содержащий предварительно скомпилированные ресурсы, такие как, например, двоичные XML-файлы.

Компоненты приложения — основные строительные блоки приложения для Android. Каждый компонент является отдельной точкой, через которую система может входить в приложение. Не все компоненты являются действительными точками входа для пользователя, а некоторые зависят друг от друга, но каждый существует как самостоятельная сущность и играет определённую роль — каждый из них является уникальным строительным блоком, который помогает определить поведение приложения в общем. Вы можете пропустить материал ниже, если вы уже знакомы с ним. Существует четыре следующих компонента приложения:

Content Provider

  • Компонент «Content Provider» поставляет данные от одного приложения к другим по запросу;
  • Можно хранить данные в файловой системе, базе данных SQLite, в Интернете, или любом другом постоянном хронилище в области, к которой у приложения есть доступ;
  • Через Content Provider другие приложения могут запрашивать или даже модифицировать данные (если Content Provider это позволяет);
  • Content Provider полезен в случаях, когда приложению нужно обмениваться данными с другим приложением;
  • Он очень схож с базами данных и имеет четыре метода:
    • insert()
    • update()
    • delete()
    • query()

Activity
Если сказать попроще, то Activity представляет собой экран с пользовательским интерфейсом. Например, действия для входа в систему (login) и другие действия после успешного входа. Что-то наподобие каждого нового экрана. Я ещё расскажу об этом позже.

Services

  • Service является компонентом, который работает в фоновом режиме для выполнения операций, рассчитанных на продолжительную работу или для выполнения задач для удалённых процессов.
  • Service не предоставляет ни пользовательского интерфейса, ни компонента, как, например, [] может запустить его или привязаться к нему для взаимодействия.
  • Например, Service может воспроизводить музыку в фоновом режиме, в то время, как пользователь работает в другом приложении, или может получать данные через сеть без блокирования взаимодействия пользователя с Activity.

Broadcast Receiver

  • Broadcast Receiver — это компонент, который отвечает за общесистемные широковещательные оповещения;
  • Многие широковещательные сообщения исходят от системы, например, сообщения об отключении экрана, низком заряде батареи, или о том, что было захвачено изображение;
  • Сообщения могут генерировать и приложения, например, чтобы передать другим приложениям информацию о том, что на устройство были загружены какие-либо данные, которые теперь доступны для них;
  • Хотя Broadcast Receiver’ы и не [], они могут создавать уведомления на панели статуса, чтобы уведомить пользователя, что произошло какое-либо событие;
  • Но чаще всего Broadcast Receiver’ы являются простым «шлюзом» к другим компонентам и предназначены для выполнения очень малого объёма работы. Например, при возникновении какого-либо события он может запустить службу для выполнения определённых действий;
  • Приложение может получить сообщение о низком заряде батареи и соответственно изменить своё поведение.

Активирующие компоненты

  • Три из четырёх типов компонентов, перечисленные выше, запускаются асинхронными сообщениями, которые называются intents (намерениями);
  • intent’ы связывают друг с другом отдельные компоненты в рантайме (как посыльные, которые запрашивают действия от других компонентов), причём вне зависимости, принадлежат эти компоненты вашему приложению или любому другому;
  • В следущем посте мы будем пользоваться Drozer’ом, который использует intent’ы, чтобы продемонстрировать уязвимости.

Особенности безопасности приложений в ОС Android

Модель доступа Android

По умолчанию в Android существуют несколько защищённых API, доступ к которым возможен только системой. В них входят:

  • Управление камерой;
  • Позиционирование (GPS);
  • Управление Bluetooth;
  • Управление телефоном (звонки);
  • Управление SMS/MMS;
  • Управление передачей данных (сеть/кабель).

Если какому-либо приложению требуется доступ к какому-либо из этих API, следует указать это разрешение в файле AndroidManifest.xml. Устанавливая какое-либо приложение из Google Play, вы наверняка видели, что оно запрашивает некоторые требуемые для его работы разрешения. Причём если вы не дадите разрешения, приложение не будет установлено. Если же пользователь даёт разрешение, то приложение получает доступ к требуемому защищённому API.

Ниже приведён пример запроса прав доступа при установке приложения.
3_part_2

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

  • Android требует, чтобы перед установкой все приложения были подписаны цифровой подписью, содержащейся в сертификате, с помощью которого Android может идентифицировать создателя приложения.
  • Чтобы запустить приложение на устройстве, оно также должно быть подписано. После установки приложения на устройство менеджер пакетов проверяет, верна ли подпись, используя сертификат в файле *.apk.
  • Приложение может быть подписано с использованием как самозаверенного (self-signed) сертификата, так и с помощью Центра Сертификации (CA — Certificate Authority).
  • Подпись приложений гарантирует, что приложение не сможет получить доступ к какому-либо другому приложению, кроме как через строго определённое IPC, а также то, что оно дошло до устройства неизменным.

Проверка приложений

  • Android 4.2 и поздние поддерживают проверку приложений. Пользователь может выбрать «Проверка приложений» («Verify Apps»), и тогда верификатором приложений будет производиться проврка приложения перед его установкой
  • Проверка приложений может уведомить пользователя, если он попытается установить приложение, которое может быть вредоносным; если же оно явно вредоносное, оно может заблокировать процесс установки.

Песочница Android

Установленное на устройство приложение Android «живёт» в своей изолированной программной среде («песочнице»). Android — многопользовательская Linux-система, в которой каждое приложение привязано к отдельному пользователю.

  • По умолчанию система присваивает каждому приложению Android уникальный UID Linux’а (который используется только системой и неизвестен приложению). Система устанавливает права доступа для всех файлов приложения таким образом, что доступ к ним может получить только пользователь с UID, привязанным к этому приложению.
  • Каждый процесс запускается в собственной виртуальной машине, таким образом, код приложения исполняется изолированно от других приложений.
  • По умолчанию каждое приложение работает в своём собственном процессе Linux. Android запускает процесс, когда требуется запустить какой-либо из компонентов приложения, и завершает процесс, когда он больше не требуется или когда системе необходимо получить память для других приложений.

Таким образом, система Android реализует принцип наименьших привилегий, в котором каждое приложение по-умолчанию имеет доступ к компонентам, которые ему нужны для работы, и не более. Это создаёт очень защищённое окружение, в котором приложение не может получить доступ к тем частям системы, на которые у него нет прав доступа. Поскольку каждое приложение Android запускается в своей собственной песочнице, по-умолчанию оно не может не может влиять на другие приложения. Однако два приложения могут иметь одинаковый ID пользователя Linux (Linux User ID, UID), а также работать в одной виртуальной машине Dalvik, если они подписаны одним и тем же сертификатом.