Контроль доступа на основе разрешений к экспортированным компонентам

Категория OWASP: MASVS-PLATFORM: взаимодействие с платформой.

Обзор

Разрешение Android – это строковый идентификатор, объявленный в манифесте приложения для запроса доступа к ограниченным данным или действиям, который применяется во время выполнения фреймворком Android.

Уровни разрешений Android указывают на потенциальный риск, связанный с разрешением:

  • Обычные. Разрешения с низким уровнем риска, которые предоставляются автоматически при установке.
  • Опасные. Разрешения с высоким уровнем риска, которые могут предоставлять доступ к конфиденциальным пользовательским данным и требуют явного одобрения пользователя во время выполнения.
  • Signature. Предоставляется только приложениям, подписанным тем же сертификатом, что и приложение, запрашивающее разрешение. Обычно используется для системных приложений или взаимодействия между приложениями одного разработчика.

Уязвимости, связанные с контролем доступа на основе разрешений, возникают, когда компонент приложения (например, действие, получатель, поставщик контента или сервис) соответствует всем следующим критериям:

  • Компонент не связан ни с одним объектом android:permission в Manifest.
  • Компонент выполняет конфиденциальную задачу, для которой существует разрешение, уже одобренное пользователем.
  • Компонент экспортирован.
  • Компонент не выполняет никаких проверок разрешений вручную (на уровне манифеста или кода).

В таком случае вредоносное приложение может выполнять действия, связанные с безопасностью, используя привилегии уязвимого компонента.

Влияние

Экспорт уязвимых компонентов может использоваться для получения доступа к конфиденциальным ресурсам или для выполнения действий, связанных с безопасностью. Последствия такого нежелательного поведения зависят от контекста уязвимого компонента и его прав.

Предотвращение атак

Требовать разрешения для конфиденциальных задач

При экспорте компонента с разрешениями на доступ к конфиденциальной информации требуйте те же разрешения для любого входящего запроса. В Android Studio IDE есть проверки lint для получателей и сервисов, которые позволяют выявить эту уязвимость и рекомендуют запрашивать соответствующие разрешения.

Разработчики могут запрашивать разрешения для входящих запросов, объявляя их в файле Manifest или на уровне кода при реализации сервиса, как показано в примерах ниже.

XML

<manifest ...>
    <uses-permission android:name="android.permission.READ_CONTACTS" />

    <application ...>
        <service android:name=".MyExportService"
                 android:exported="true"
                 android:permission="android.permission.READ_CONTACTS" />

        </application>
</manifest>

Kotlin

class MyExportService : Service() {

    private val binder = MyExportBinder()

    override fun onBind(intent: Intent): IBinder? {
        // Enforce calling app has the required permission
        enforceCallingPermission(Manifest.permission.READ_CONTACTS, "Calling app doesn't have READ_CONTACTS permission.")
        // Permission is enforced, proceed with export logic
        return binder
    }

    // Inner class for your Binder implementation
    private inner class MyExportBinder : Binder() {
        // Permission is enforced, proceed with export logic
    }
}

Java

public class MyExportService extends Service {

    @Override
    public IBinder onBind(Intent intent) {
        // Enforce calling app has the required permission
        enforceCallingPermission(Manifest.permission.READ_CONTACTS, "Calling app doesn't have READ_CONTACTS permission.");

        return binder;

    }

    // Inner class for your Binder implementation
    private class MyExportBinder extends Binder {
        // Permission is enforced, proceed with export logic

    }
}

Не экспортировать компонент

Не экспортируйте компоненты с доступом к конфиденциальным ресурсам без крайней необходимости. Для этого задайте для свойства android:exported в файле Manifest значение false. Начиная с уровня API 31, этот атрибут по умолчанию имеет значение false.

XML

<activity
    android:name=".MyActivity"
    android:exported="false"/>

Применить разрешения на основе подписи

Для обмена данными между двумя приложениями, которыми вы управляете или владеете, используйте разрешения на основе подписи. Эти разрешения не требуют подтверждения пользователя. Вместо этого проверяется, что приложения, запрашивающие доступ к данным, подписаны одним и тем же ключом. Это делает работу с сервисом более удобной и безопасной. Если вы объявляете собственные разрешения, ознакомьтесь с соответствующими рекомендациями по безопасности.

XML

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.myapp">
    <permission android:name="my_custom_permission_name"
                android:protectionLevel="signature" />

Конечные точки для одной задачи

При разработке приложения следуйте принципу разделения ответственности. Каждая конечная точка должна выполнять только небольшой набор определенных задач с определенными привилегиями. Такой подход также позволяет разработчику применять детализированные разрешения для каждой конечной точки. Например, не создавайте одну конечную точку, которая обслуживает и календарь, и контакты.

Ресурсы