Как защищаются стандартные Intent в Android
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Защита стандартных Intent в Android
Intent — это фундаментальный механизм межкомпонентного взаимодействия (Inter-Process Communication, IPC) в Android. Поскольку через него передаются чувствительные данные и запускаются важные операции, защита Intent является критически важной. Система Android использует разрешения (permissions), фильтры Intent (Intent Filters) и ряд других механизмов для минимизации рисков.
Основные механизмы защиты
1. Система разрешений (Permissions)
Это основной механизм защиты. Приложение-отправитель (explicit Intent) или система (implicit Intent) проверяет, имеет ли приложение-получатель необходимые права.
- Защита на стороне получателя (Receiver): Компонент (Activity, Service, BroadcastReceiver) в манифесте объявляет, какое разрешение требуется для его вызова.
<activity android:name=".SecureActivity" android:permission="com.example.perm.SECURE_ACCESS" > <intent-filter> ... </intent-filter> </activity>
Отправитель должен быть наделен этим разрешением (в `uses-permission`) или подписан тем же сертификатом, иначе вызов завершится ошибкой `SecurityException`.
- Защита на стороне отправителя (Sender): При отправке Intent (чаще всего Broadcast Intent) отправитель может указать разрешение, которое должно быть у получателей.
Intent broadcast = new Intent("com.example.MY_ACTION"); sendBroadcast(broadcast, "com.example.perm.RECEIVE_BROADCAST");
В этом случае только приложения, объявившие `com.example.perm.RECEIVE_BROADCAST`, смогут принять это широковещательное сообщение.
2. Экспорт компонентов и Intent Filters
Атрибут android:exported в манифесте явно определяет, может ли компонент быть вызван извне (из других приложений).
exported="false": Компонент доступен только внутри своего приложения. Это самый безопасный вариант для внутренних компонентов.exported="true"(явно или неявно): Компонент доступен извне. Неявноexportedстановитсяtrue, если у компонента объявлен<intent-filter>. Это создает потенциальную уязвимость, если фильтр слишком широкий.
Ключевая проблема: Небезопасные Implicit Intent с широкими фильтрами. Например, Activity с фильтром на ACTION_VIEW и CATEGORY_DEFAULT может быть случайно вызвана злоумышленником.
<!-- Потенциально небезопасно, если Activity не должна быть публичной -->
<activity android:name=".InternalViewerActivity" android:exported="true">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/*" />
</intent-filter>
</activity>
Защита: Всегда явно задавайте android:exported, сужайте фильтры насколько возможно, а для внутренних компонентов используйте Explicit Intent.
3. Защита данных Intent
Данные в Intent могут быть перехвачены.
- Злонамеренные приложения, подписанные на те же Broadcast: Если Broadcast не защищен разрешением, его могут получить все.
- Приложения с разрешением
BIND_ACCESSIBILITY_SERVICEили через рутирование: Могут перехватывать UI-события.
Меры защиты:
- Не передавайте чувствительные данные (пароли, токены) через неявные Intent или публичные Broadcast.
- Используйте явные Intent для взаимодействия внутри своего приложения.
- Для межпроцессного взаимодействия используйте защищенные разрешениями Broadcast, Content Providers с гранулярными permissions или Bound Services с проверкой вызывающей стороны.
- Начиная с Android 12 (API 31), для компонентов с
intent-filterнеобходимо явно объявлятьandroid:exported.
4. Проверка вызывающей стороны (Caller Identity)
В точке получения Intent компонент может (и часто должен) проверить, кто его вызвал.
// В Activity, Service, BroadcastReceiver
public void onReceive(Context context, Intent intent) {
// 1. Проверка через разрешение (система делает это автоматически)
// 2. Дополнительная проверка пакета (для недоверенных источников)
String callerPackage = getCallingPackage();
if (callerPackage != null && !callerPackage.equals("trusted.package.name")) {
return; // Игнорируем вызов
}
// 3. Проверка подписи (для взаимодействия между своими приложениями)
if (getPackageManager().checkSignatures(callerPackage, getPackageName())
== PackageManager.SIGNATURE_MATCH) {
// Доверенный источник
}
}
Рекомендации по безопасному использованию
- Минимизируйте использование
exported="true". Компонент должен быть экспортирован, только если это функционально необходимо. - Предпочитайте Explicit Intent Implicit. Для внутренней навигации всегда используйте явные интенты.
- Защищайте Broadcast Intent. Всегда используйте параметр разрешения в
sendBroadcast()или устанавливайтеandroid:permissionв ресивере. Начиная с Android 8.0, для большинства событий используйте LocalBroadcastManager (устарел) или его аналогLiveData,FlowилиLocalBroadcastManagerиз AndroidX. - Не доверяйте данным входящего Intent. Всегда выполняйте валидацию и санацию входных данных (URI, extras).
- Используйте защищенные custom permissions. Сложные имена (
com.company.app.permission.SPECIAL) снижают риск случайных коллизий. - Для конфиденциальных данных используйте PendingIntent. Он делегирует права на выполнение операции системе, а не другому приложению.
Таким образом, защита стандартных Intent строится на комбинации декларативных правил в манифесте (permissions, exported) и программных проверок в коде. Безопасность достигается за счет принципа наименьших привилегий: компонент должен быть доступен минимально необходимому кругу вызывающих объектов и с минимально необходимыми правами.