Содержание статьи
Почитать
PendingIntent и безопасность
Re-route Your Intent for Privilege Escalation — презентация с Black Hat Europe 2021, посвященная уязвимостям, связанным с использованием так называемых PendingIntent в приложениях для Android.
Интенты (intent) — одна из ключевых идей Android. Интенты позволяют пересылать сообщения между компонентами приложений и системных сервисов с целью вызвать определенное действие. Запускаются приложения, открываются ссылки, инициируются звонки и многое другое в Android делается с помощью интентов.
Поверх интентов построен другой механизм — отложенные интенты (PendingIntent). Он позволяет передать интент другому приложению или компоненту системы, чтобы то могло отправить интент от имени передавшего его приложения.
Проблема отложенных интентов только в том, что в ряде случаев можно изменить записанный в них интент (это можно сделать, если не установлен флаг FLAG_IMMUTABLE
) и в итоге выполнить произвольное действие от имени передавшего PendingIntent приложения.
Отложенные интенты чаще всего используются в следующих компонентах:
- Уведомления. Чтобы перехватить их, мы можем создать
NotificationListenerService
, который будет слушать все уведомления приложений и извлекать из них отложенные интенты. - SliceProvider. Этот механизм используется для встраивания частей приложения в другие приложения, например встраивания переключателя быстрых настроек в окно ассистента. Мы можем получить слайс с помощью класса
SliceViewManager
илиContentResolver
и затем получить PendingIntent всех слайсов. - MediaBrowserService. Механизм, позволяющий приложению дать доступ к своей медиатеке с возможностью включить проигрывание медиафайлов. Получить PendingIntent можно, подключившись к приложению с помощью класса
MediaBrowser
. - Виджеты рабочего стола используют отложенные интенты в качестве действий при нажатии на свои элементы. Класс
AppWidgetHost
позволяет приложению прикинуться лаунчером и получить доступ к виджетам приложений. Далее PendingIntent можно извлечь из самого виджета.
В качестве примера уязвимости в одном из этих компонентов приведем CVE-2020-0188. Это уязвимость в SliceProvider’е стандартных настроек Android. Благодаря тому что PendingIntent был открыт для изменения, его можно было вытащить с помощью ContentResolver
, а затем изменить так, чтобы прочитать приватные файлы приложения «Настройки»:
Intent hijackIntent = new Intent();hijackIntent.setPackage(getPackageName());hijackIntent.setDataAndType(Uri.parse("content://com.android.settings.files/my_cache/NOTICE.html"), "txt/html");hijackIntent.setFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);pi.send(getApplicationContext(), 0, hijackIntent, null, null);
По сути, этот код заставляет приложение «Настройки» передать ссылку на свой внутренний файл с правами на чтение и запись приложению‑эксплоиту. Остается только принять интент, и можно делать с файлом все, что угодно.
Рекомендации разработчикам:
- По возможности указывай флаг
FLAG_IMMUTABLE
при создании PendingIntent. - При необходимости использовать модифицируемый PendingIntent применяй явный интент и заполняй поле
ComponetName
. В этом случае злоумышленник не сможет перенаправить интент. - Используй утилиту PendingIntentScan для сканирования приложения на наличие модифицируемых PendingIntent.
Анализ использования трекинговых библиотек в приложениях
Are iPhones Really Better for Privacy? Comparative Study of iOS and Android Apps — исследование использования трекинговых библиотек в приложениях для Android и iOS. Авторы работы взяли 12 тысяч приложений для каждой платформы, проанализировали их код и сетевые подключения и пришли к следующим выводам:
- В среднем приложения используют около трех различных трекинговых библиотек.
- 3,73% приложений для Android и 3,13% приложений для iOS используют больше десяти трекинговых библиотек.
- 88,73% приложений для Android и 79,35% приложений для iOS содержат хотя бы одну трекинговую библиотеку.
- Самые популярные трекинговые библиотеки на Android — Google Play Services (87,3%), Google AdMob (61,7%), Google Firebase (57,6%).
- Самые популярные трекинговые библиотеки на iOS — SKAdNetwork (69,6%), Google Firebase (53,9%), Facebook (25,5%).
- Самые используемые разрешения в приложениях для Android (исключая те, что даются без запроса пользователя) — доступ к карте памяти, местоположению и камере.
- Самые используемые разрешения в приложениях для iOS — хранилище фотографий, камера, местоположение.
- Самые популярные домены для отправки статистики — googleads.g.doubleclick.net (Android) и app-measurement.com (iOS).
- Большая часть трекинговых компаний принадлежит Alphabet (Google) и Facebook.
Разработчику
Синхронизация корутин
Coroutines and Java Synchronization Don’t Mix — небольшая заметка о неочевидной для некоторых программистов особенности взаимодействия корутин Kotlin и блокировок.
Все мы знаем об аннотации @Synchronized
(или блоке synchronized
), которая говорит о том, что код функции может выполняться только в одном потоке одновременно:
repeat(2) { thread { criticalSection() }}@Synchronized
fun criticalSection() { println("Starting!") Thread.sleep(10) println("Ending!")}
Два потока в этом примере выполнят код функции последовательно, один за другим:
Starting!
Ending!
Starting!
Ending!
Однако если мы заменим потоки корутинами, то все изменится:
val scope = CoroutineScope(Job())repeat(2) { scope.launch { criticalSectionSuspending() }}@Synchronized
suspend fun criticalSectionSuspending() { println("Starting!") delay(10) println("Ending!")}
Вывод будет таким:
Starting!
Starting!
Ending!
Ending!
Другими словами, аннотация @Synchronized
будто бы не работает в случае корутин.
На самом деле объяснение в том, что обе корутины в данном примере работают в одном потоке. А это влечет за собой два следствия:
- Компилятор, поняв, что в synchronized-блок входит только один поток, может полностью удалить синхронизацию.
- Блок synchronized обладает свойством reentrace, когда один и тот же поток может заходить в synchronized-блок, не снимая блокировку.
Другими словами, @Synchronized
просто не имеет смысла для корутин, работающих в одном потоке. И вместо нее следует использовать класс Mutex
.
Продолжение доступно только участникам
Вариант 1. Присоединись к сообществу «Xakep.ru», чтобы читать все материалы на сайте
Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», позволит скачивать выпуски в PDF, отключит рекламу на сайте и увеличит личную накопительную скидку! Подробнее
Вариант 2. Открой один материал
Заинтересовала статья, но нет возможности стать членом клуба «Xakep.ru»? Тогда этот вариант для тебя! Обрати внимание: этот способ подходит только для статей, опубликованных более двух месяцев назад.
Я уже участник «Xakep.ru»