Безопасность Android. От первой до одиннадцатой версии

Долгое время 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

С помощью этих настроек пользователь мог отозвать у приложения любые доступные ему полномочия по отдельности. Однако назвать эту систему удобной и дружелюбной пользователю нельзя: управление разрешениями было чересчур гранулярным, приходилось ориентироваться среди десятков разрешений, смысл которых часто оставался непонятен. При этом отзыв любого разрешения мог привести (и часто приводил) к падению приложения, так как в 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

Ограничения

Система управления разрешениями — только часть решения проблемы. Вторая часть — запреты на использование опасных 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 необходимость использовать те или иные разрешения.

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

Материалы из последних выпусков становятся доступны по отдельности только через два месяца после публикации. Чтобы продолжить чтение, необходимо стать участником сообщества «Xakep.ru».

Присоединяйся к сообществу «Xakep.ru»!

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

Евгений Зобнин: Редактор рубрики X-Mobile. По совместительству сисадмин. Большой фанат Linux, Plan 9, гаджетов и древних видеоигр.

Комментарии (4)

  • С вашего позволения немного дополню :) В первых версиях андройд безопасность как понятие нигде не упоминалось. Android использовал все что досталось по наследству от Linux. И это скорее система разграничения прав чем безопасность. Sanbox до 5.0 был без selinux и скорее был просто discretionary access control на основе UID. Я думаю что какая то внятность началась с KeyChain в 4.0, а идея полностью сформировалась к 7.0 c четким verify-boot. Но на две версии раньше. в 5.1 Самсунг уже предлагал своим бизнес клиентам KNOX как систему безопасности корпоративного уровня. Samsung S5 открыл Android для корпоратов. SafetyNet серьезен, многоуровневый от cts тестов до сетевого соединения, и когда гугл выпустит свои процессоры с аппаратным ключом как у iphone в анклав, теоретически будет не пробивной. Но на практике реализацию в приложение клиент должен сделать сам. Например Cбербанк не справился :) И на текущий момент в safety net много спорных дыр. Типа реализации метода проверки своими силами на своем сервере на случай если не отвечают сервера гугла. Взлом сводится к созданию условий когда клиент вынуждено отправляется по пути упрощенной проверки, где все так же подменяются ответы устройства, поскольку CTS check может сделать только гугл. И тот же Knox, сам гугл признает более доверенной системой. Поскольку администраторы Knox могут отключать проверку safetynet со стороны устройства. И для приложений API всегда будет давать зеленый свет. И что интересно. Google и Apple использовали разные тактики что бы прийти к тому что мы имеем сегодня. Google на пол корпуса впереди. Но обе системы оказались уязвимы к одной и той же проблеме. Загрузчик модема. Кто находит POC для загрузки своего модема ломает и Android и iOS :)

    • С точки зрения именно сандбокса, да, первые версии Android действительно использовали тупое разграничение прав на основе прав пользователя, так что порой случались и протечки. Но если говорить о системе межпроцессного взаимодействия (Binder), то здесь все намного интереснее. В Android Binder используется буквально для всего, включая API. И система всегда использовала его как единую точку управления правами приложений на те или иные действия. Другое дело что пользователю контроль над правами дали только в Android 6 :)

  • получается что Blackberry OS10 остается самой безопасной мобильной ОС на сегодняшнее время !!!??

  • Я репортал в Android security проблему того, что права суперпользователя можно получить без разблокировки экрана на одной из последних.

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

    Суть проблемы такая.

    1. Установить Android на VirtualBox
    2. Добавить физическую клавиатуру
    3. Нажать Alt+F1
    Открылся терминал
    Поле ввода логина и пароля не спрашивает, не смотря на то что экран заблочен (! какого черта)
    4. Тайпаем sudo
    Все проходит.
    Привет суперадмин.
    5. Теперь можно перемонтировать систему для чтения на режим чтения записи и сделать все что угодно.

    Нажимаем Alt+F7 - видим экран как был заблочен так и остался.

Похожие материалы