Долгое время Android имел славу медленной, небезопасной и в целом убогой ОС, предназначенной для тех, кто не смог накопить на iPhone. Но так ли это сейчас и был ли Android на самом деле так плох? В этой статье мы не будем касаться плавности работы интерфейса и возможностей ОС, но проследим за историей едва ли не самой больной части Android — системы безопасности.
 

Начало времен

Понять смысл и назначение защитных механизмов Android проще всего в ретроспективе. А именно — изучив, как была реализована защита (или ее отсутствие) в первых версиях ОС и как и зачем она менялась впоследствии.

Итак, Android 1.0 — платформа, выпущенная осенью 2008 года вместе со смартфоном HTC Dream (T-Mobile G1). Безопасность обеспечивается пятью ключевыми подсистемами.

1. PIN-код экрана блокировки для защиты от несанкционированного физического доступа.

2. Песочницы (изолированная среда исполнения) для приложений. Каждое приложение запускается от имени созданного специально для него пользователя Linux. Приложение имеет полный контроль над файлами своей песочницы (/data/data/имя.пакета), но не может получить доступ к системным файлам и файлам других приложений. Единственный способ покинуть песочницу — получить права root.

3. Каждое приложение обязано указывать список нужных для его работы полномочий в манифесте. Полномочия позволяют использовать те или иные системные API (доступ к камере, микрофону, сети и так далее). Хотя соблюдение полномочий контролируется на нескольких уровнях, включая ядро Linux, явно запрашивать их у пользователя не нужно; приложение автоматически получает все перечисленные в манифесте полномочия, и пользователю остается либо установить приложение, предоставив ему все полномочия, либо не устанавливать его вовсе.

Контроль доступа на основе полномочий не распространяется на карты памяти и USB-накопители. Они используют файловую систему FAT, которая не позволяет назначить права доступа к файлам. Любое приложение может читать содержимое всей карты памяти.

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

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

В то же время значительная часть операционной системы, включая системные сервисы, виртуальную машину, мультимедийные библиотеки, систему рендеринга графики, а также все сетевые подсистемы, написана на тех самых небезопасных C и C++ и работает с правами root. Уязвимость в одном из этих компонентов может быть использована для получения полного контроля над ОС или выполнения DoS-атаки. HTC Dream был «взломан» благодаря тому, что сервис Telnet, предустановленный на смартфон, работал с правами root. Все, что нужно было сделать, — это найти способ его запустить, а затем к смартфону можно было подключиться по сети и получить шелл-доступ с правами суперпользователя.

Если же говорить о стандартных приложениях, то они хоть и не имели прав root и работали под защитой виртуальной машины в собственной песочнице, так или иначе обладали очень широкими возможностями, свойственными десктопным операционным системам. При наличии нужных прав стороннее приложение могло сделать очень многое: прочитать списки СМС и звонков, прочитать любые файлы на карте памяти, получить список установленных приложений, работать в фоне неограниченное время, выводить графику поверх окон других приложений, получать информацию практически обо всех системных событиях (установка приложения, включение-выключение экрана, звонок, подключение зарядного устройства и многое другое).

Строго говоря, все эти API не были уязвимостями в прямом смысле слова. Наоборот, они открывали широкие возможности для программистов и, как следствие, пользователей. Но если в 2008-м эти возможности не создавали особых проблем, поскольку рынок смартфонов был ориентирован на энтузиастов и бизнесменов, то уже через несколько лет, когда смартфоны получили распространение среди всех групп населения, стало понятно, что приложения необходимо ограничивать в возможностях.

 

Полномочия

Есть два способа ограничить приложения в правах и не дать им влиять на систему и пользовательские данные:

  1. Урезать возможности всех приложений до минимума, как это было сделано в J2ME.
  2. Позволить пользователю контролировать доступные приложению возможности (путь iOS).

Android, несмотря на мощную систему разделения полномочий внутри ОС, не позволял ни того, ни другого. Первые намеки на систему гранулярного контроля полномочий появились только в Android 4.3 вместе со скрытым разделом настроек App Ops.

Скрытое меню App Ops в Android 4.3
Скрытое меню App Ops в Android 4.3

С помощью этих настроек пользователь мог отозвать у приложения любые доступные ему полномочия по отдельности. Однако назвать эту систему удобной и дружелюбной пользователю нельзя: управление разрешениями было чересчур гранулярным, приходилось ориентироваться среди десятков разрешений, смысл которых часто оставался непонятен. При этом отзыв любого разрешения мог привести (и часто приводил) к падению приложения, так как в Android просто не было API, который бы позволил программисту понять, имеет его приложение разрешение на выполнение того или иного действия или нет. В итоге систему App Ops удалили из Android уже в версии 4.4.2, и только в Android 6 ей на смену пришла существующая до сих пор система полномочий.

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

Побочным эффектом такого подхода стала... бесполезность новой системы. Дело в том, что она работала исключительно для приложений, собранных под Android 6.0 и выше. Разработчик приложения мог указать в правилах сборки директиву targetSdkVersion 22 (то есть Android 5.1), и его приложение продолжило бы получать все полномочия в автоматическом режиме.

Google была вынуждена реализовать систему именно таким образом, чтобы сохранить совместимость со старым софтом. По-настоящему система начала действовать только спустя два года, когда Google ввела требование минимального SDK в Google Play, то есть просто запретила публиковать приложения, собранные для устаревших версий ОС. Окончательно решили вопрос только в Android 10: стало возможно отзывать полномочия у софта, собранного для Android 5.1 и ниже.

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

Одноразовые разрешения в Android 11
Одноразовые разрешения в Android 11
 

Ограничения

Система управления разрешениями — только часть решения проблемы. Вторая часть — запреты на использование опасных API. Можно долго спорить, стоит ли позволять сторонним приложениям получать IMEI телефона с помощью разрешений, или необходимо запретить делать это вовсе. Для Google, входящей в эпоху тотального помешательства на прайваси, ответ был очевиден.

Несмотря на то что компания и раньше вводила запреты на использование тех или иных API (можно вспомнить, например, запрет на включение режима полета и подтверждение отправки СМС на короткие номера в Android 4.2), активные боевые действия начались только в 2017 году.

Начиная с восьмой версии Android скрывает многие идентификаторы устройства от приложений и других устройств. Android ID (Settings.Secure.ANDROID_ID) — уникальный идентификатор Android теперь различен для каждого установленного приложения. Серийный номер устройства (android.os.Build.SERIAL) недоступен приложениям, собранным для Android 8 и выше. Содержимое переменной net.hostname пусто, а DHCP-клиент никогда не посылает хостнейм DHCP-серверу. Стали недоступны некоторые системные переменные, например ro.runtime.firstboot (время последней загрузки).

С Android 9 приложения больше не могут прочитать серийный номер устройства без полномочия READ_PHONE_STATE. В Android 10 появилось ограничение на доступ к IMEI и IMSI. Чтобы прочитать эту информацию, теперь требуется разрешение READ_PRIVILEGED_PHONE_STATE, недоступное сторонним приложениям.

Для получения MAC-адреса Bluetooth в Android 8 и выше требуется разрешение LOCAL_MAC_ADDRESS, а MAC-адрес Wi-Fi рандомизируется при проверке доступных сетей (чтобы избежать трекинга пользователей, например покупателей в торговых центрах).

В Android 9 Google пошла намного дальше и запретила использовать камеру, микрофон и любые сенсоры, пока приложение находится в фоне (оставив возможность использовать камеру и микрофон «видимым сервисам» — foreground service). В Android 10 к этим ограничениям добавился запрет на доступ к местоположению в фоне (теперь для этого нужно разрешение ACCESS_BACKGROUND_LOCATION) и запрет на чтение буфера обмена в фоне (нужно разрешение READ_CLIPBOARD_IN_BACKGROUND).

Еще одно важное нововведение Android 9 — полный запрет на использование HTTP без TLS (то есть без шифрования) для всех приложений, собранных для новой версии Android. Это ограничение тем не менее можно обойти, если указать в файле настроек безопасности сети (network_security_config.xml) список разрешенных доменов.

Android 10 ввел запрет на запуск активностей (по сути — запуск приложений) фоновыми приложениями. Исключения сделаны для bound-сервисов, таких как Accessibility и сервисы автозаполнения. Приложения, использующие разрешение SYSTEM_ALERT_WINDOW, и приложения, получающие имя активности в системном PendingIntent, тоже могут запускать активности в фоне. Также приложения теперь не могут запускать бинарные файлы из собственного приватного каталога. Это уже привело к проблемам в работе популярного приложения Termux.

С Android 11 приложения больше не могут получить прямой доступ к карте памяти (внутренней или внешней) с помощью разрешений READ_EXTERNAL_STORAGE и WRITE_EXTERNAL_STORAGE. Вместо этого следует использовать либо личный каталог приложения внутри /sdcard/Android (он создается автоматически и не требует разрешений), либо Storage Access Framework, не допускающий доступ к данным других приложений.

Интересно, что Google ограничивает сторонние приложения не только средствами операционной системы. В конце 2018 года в Google Play появилось требование, гласящее, что все приложения, использующие разрешения на чтение СМС и журнала звонков, должны относиться к одному из разрешенных типов приложений и в обязательном порядке проходить ручную премодерацию. В результате из маркета удалили многие полезные инструменты, авторы которых просто не смогли обосновать перед Google необходимость использовать те или иные разрешения.

Продолжение доступно только участникам

Вариант 1. Присоединись к сообществу «Xakep.ru», чтобы читать все материалы на сайте

Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», позволит скачивать выпуски в PDF, отключит рекламу на сайте и увеличит личную накопительную скидку! Подробнее

Вариант 2. Открой один материал

Заинтересовала статья, но нет возможности стать членом клуба «Xakep.ru»? Тогда этот вариант для тебя! Обрати внимание: этот способ подходит только для статей, опубликованных более двух месяцев назад.


  • Подпишись на наc в Telegram!

    Только важные новости и лучшие статьи

    Подписаться

  • Подписаться
    Уведомить о
    4 комментариев
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии