Перейти к содержанию

Передача sensitive-информации в Private BroadcastReceiver

Критичность: ИНФО
Способ обнаружения: DAST, SENSITIVE INFO

Описание

Приложение включает чувствительную информацию в Intent для запуска приватного BroadcastReceiver.

Межпроцессное взаимодействие (IPC) в Android осуществляется при помощи специальных объектов — Intent. Параметры обработчиков Intent задаются в основном файле манифеста приложения — AndroidManifest.xml либо, в случае с динамическими BroadcastReceivers — в коде приложения. Если используются неявные Intent (адресат сообщения не указан явно либо применяется механизм широковещательных сообщений — Broadcast), данные, содержащиеся в таких сообщениях, могут быть скомпрометированы. Кроме того, вредоносными приложениями могут использоваться механизмы делегирования управления процесса, такие как неявные вызовы компонентов приложений или объекты типа PendingIntent для перехвата потока управления и фишинговых атак.

Опасность представляют объекты типов Activity, Service, BroadcastReceiver и ContentProvider, открытые для взаимодействия с другими приложениями и не относящиеся к системным Android-вызовам (таким как android.intent.action.MAIN). По умолчанию BroadcastReceiver открыт для взаимодействия с другими приложениями, в этом случае возможен перехват Intent с конфиденциальной информацией или перехват управления.

Рекомендации

При отправке Broadcast с чувствительной информацией во внутренний BroadcastReceiver должен использоваться явный Intent, Private BroadcastReceiver или LocalBroadcastManager. Также следует помнить, что приложение не должно включать чувствительную информацию в Public Broadcast.

Для получения Broadcast необходимо создать BroadcastReceiver. Риски при использовании BroadcastReceiver и соответствующие им защитные меры различаются в зависимости от типа Broadcast.

Для определения типа BroadcastReceiver, который планируется создавать, можно воспользоваться таблицей и диаграммой, представленными ниже. У приложения, получающего Broadcast, нет возможности проверить имя пакета, из которого произошла его отправка, поэтому невозможно создать Partner BroadcastReceiver по аналогии с Activity.

Тип BroadcastReceiver Описание
Private BroadcastReceiver BroadcastReceiver, который не может получать Broadcast из других приложений, и поэтому является наиболее защищённым
Public BroadcastReceiver BroadcastReceiver, который может получать Broadcast из любых приложений
In-house BroadcastReceiver BroadcastReceiver, который может получать Broadcast только из приложений того же разработчика

Также в зависимости от способа объявления BroadcastReceiver может быть статическим или динамическим.

Способ объявления Характеристики
Статический BroadcastReceiver С помощью элементов \<receiver> в файле AndroidManifest.xml – не может получать некоторые системные Broadcast'ы (например, ACTION_BATTERY_CHANGE);
– будет получать Broadcast'ы, начиная с момента установки приложения и до его удаления
Динамический BroadcastReceiver С помощью вызова метода registerReceiver() – может получать все Broadcast'ы, которые не может получать статический BroadcastReceiver;
– период получения Broadcast'ов определяется логикой программы;
– не может быть создан Private BroadcastReceiver

Пример создания Private BroadcastReceiver

Private BroadcastReceiver является наиболее безопасным, т. к. он получит Broadcast только из того же самого приложения, в котором был объявлен. Private BroadcastReceiver может быть объявлен только статически.

Правила (получение Broadcast):

  1. Явно указывайте атрибут exported="false".
  2. Проводите проверку и безопасную обработку полученного Intent, несмотря на то, что он был получен из того же самого приложения.
  3. В Intent результата можно включать конфиденциальную информацию, т.к. его отправка и получение происходят внутри приложения.

Объявление компонента в AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.appsec.android.broadcast.privatereceiver" >
    <application
            android:icon="@drawable/ic_launcher"
            android:label="@string/app_name"
            android:allowBackup="false" >

            <!-- Private Broadcast Receiver -->
            <!-- *** 1 *** Явно указывайте атрибут exported="false" -->
            <receiver
                android:name=".PrivateReceiver"
                android:exported="false" />

            <activity
                android:name=".PrivateSenderActivity"
                android:label="@string/app_name"
                android:exported="true" >
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
        </application>
    </manifest>

Получение Broadcast

package com.appsec.android.broadcast.privatereceiver;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;
public class PrivateReceiver extends BroadcastReceiver {     @Override
    public void onReceive(Context context, Intent intent) {

        // *** 2 *** Проводите проверку и безопасную обработку полученного Intent, несмотря на то, что он был получен из того же самого приложения         String param = intent.getStringExtra("PARAM");
        Toast.makeText(context,
                String.format("Received param: \"%s\"", param),
                Toast.LENGTH_SHORT).show();

        // *** 3 *** В Intent результата можно включать конфиденциальную информацию, т.к. его отправка и получение происходит внутри приложения
        setResultCode(Activity.RESULT_OK);
        setResultData("Чувствительная информация");
        abortBroadcast();
    }
}

Правила (отправка Broadcast):

  1. Используйте явный Intent с указанием имени класса BroadcastReceiver внутри приложения.
  2. Можно отправлять чувствительную информацию.
  3. Проводите проверку и безопасную обработку полученных данных результата, несмотря на то, что они были получены из BroadcastReceiver того же самого приложения.
    package com.appsec.android.broadcast.privatereceiver;
        import android.app.Activity;
        import android.content.BroadcastReceiver;
        import android.content.Context;
        import android.content.Intent;
        import android.os.Bundle;
        import android.view.View;
        import android.widget.TextView;
        public class PrivateSenderActivity extends Activity {
        public void onSendNormalClick(View view) {
                // *** 1 *** Используйте явный Intent с указанием имени класса BroadcastReceiver внутри приложения
                Intent intent = new Intent(this, PrivateReceiver.class);
            // *** 2 *** Можно отправлять чувствительную информацию
                intent.putExtra("PARAM", "Чувствительная информация от отправителя");
                sendBroadcast(intent);
            }
    
            public void onSendOrderedClick(View view) {
                // *** 1 *** Используйте явный Intent с указанием имени класса BroadcastReceiver внутри приложения
                Intent intent = new Intent(this, PrivateReceiver.class);
            // *** 2 *** Можно отправлять чувствительную информацию
                intent.putExtra("PARAM", "Чувствительная информация от отправителя");
                sendOrderedBroadcast(intent, null, mResultReceiver, null, 0, null, null);
            }
    
            private BroadcastReceiver mResultReceiver = new BroadcastReceiver() {
                @Override
                public void onReceive(Context context, Intent intent) {
    
                    // *** 3 *** Проводите проверку и безопасную обработку полученных данных результата, несмотря на то, что они были получены из BroadcastReceiver того же самого приложения
                    // См.п. "Безопасная обработка входных данных"
    
                    String data = getResultData();
                    PrivateSenderActivity.this.logLine(
                            String.format("Received result: \"%s\"", data));
                }
            };
    
            private TextView mLogView;
    
            @Override
            public void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.main);
                mLogView = (TextView)findViewById(R.id.logview);
            }
    
            private void logLine(String line) {
                mLogView.append(line);
                mLogView.append("\n");
            }
        }
    

Ссылки

  1. Intents and Intent Filters | Android Developers
  2. Interacting with Other Apps | Android Developers
  3. CWE—CWE-927: Use of Implicit Intent for Sensitive Communication (4.6)
  4. owasp-mstg/0x05h-Testing-Platform-Interaction.md at master · OWASP/owasp-mstg
К началу