Атака Activity hopping: угроза безопасности

Поговорим о том, почему атрибут exported=“true” может обернуться катастрофой, если правильно не установить его в соответствующий Activity-компонент. Углубимся в этот вопрос.

android:exported="true"

Атрибут exported="true" используется для указания того, что компонент (Activity, Service, Broadcast Receiver и т. д.) может быть запущен компонентами других приложений. Такая функция полезна, когда мы имеем дело с компонентами, предназначенными для работы с другими приложениями (например, в случае приложения обмена фото, которое позволяет другим приложениям обмениваться с ним фото).

Есть несколько причин, по которым может понадобиться exported="true".

  • Чтобы позволить другим приложениям запускать activity или service. Это может быть полезно для создания интеграций с другими приложениями или для предоставления услуг другим приложениям.
  • Чтобы разрешить другим приложениям отправлять сообщения на broadcast receiver. Это может пригодиться в целях получения уведомлений от других приложений.
  • Чтобы предоставить другим приложениям доступ к content provider (обмен данными с другими приложениями).

Однако при использовании exported="true" следует быть осторожным. Если компонент является exported (экспортируемым), то любое приложение способно запустить его или отправить ему сообщение. Это может создать угрозу безопасности, если компонент не защищен должным образом. Например, вредоносное приложение может запустить экспортируемый Activity-компонент, чтобы украсть данные из приложения или совершить другие злонамеренные действия. Далее речь пойдет о том, как можно использовать эту лазейку, запустив Activity из другого приложения. Более подробную информацию ищите здесь.

Intent-тест

Создадим простое приложение с одним Activity-компонентом, который пока ниоткуда не вызывается (и его также нельзя ниоткуда достать). Параметр activity:exported установим в true.

Приложение с Activity .hidden (целевой Activity)

Это приложение содержит еще одну Activity с именем .hidden, которую можно обнаружить в manifest (манифесте приложения).

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">

<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.Intent_test"
tools:targetApi="31">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data
android:name="android.app.lib_name"
android:value="" />
</activity>

<activity android:name=".hidden"
android:exported="true"
></activity>
</application>
</manifest>

Посмотрите, как установлен exported attribute. В реальной ситуации, если этот атрибут будет установлен таким образом, а Activity-компонент будет содержать конфиденциальные данные, можно передать auth activity или украсть данные из приложения. Но сейчас нас интересует процесс кражи этих данных из созданного нами вредоносного приложения. Этот процесс называется эксплойт (взлом программы с помощью вредоносного кода). Мы будем использовать метод intent.setComponent(new ComponentName()) для инициирования интента открыть определенную Activity, к которой нужно получить доступ.

Метод intent.setComponent(new ComponentName()) имеет два атрибута  —  package name (имя пакета) и class name (имя класса), которые будут переданы, чтобы открыть Activity. Именно это мы и сделали.

button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setComponent(new ComponentName("com.example.intent_test", "com.example.intent_test.hidden"));
startActivity(intent);
}
});
}

Мы установили event listener (слушатель событий), привязанный к кнопке, чтобы он открывал нужное нам приложение, которое называется “intent_test”, и скрытый класс с именем “.hidden”, который обрабатывает hidden activity, являющуюся нашей целью для получения доступа. Итак, запускаем.

Читайте также:

Читайте нас в Telegram, VK и Дзен


Перевод статьи Eliezer Binyam: Activity Hopping: A Security Nightmare

Предыдущая статьяПрограммист как пользователь инструментов
Следующая статьяОсновные различия между React.js и React Native