Oparta na uprawnieniach kontrola dostępu do wyeksportowanych komponentów

Kategoria OWASP: MASVS-PLATFORM: Platform Interaction

Omówienie

Uprawnienie Androida to identyfikator ciągu znaków zadeklarowany w manifeście aplikacji w celu żądania dostępu do ograniczonych danych lub działań, wymuszany w czasie wykonywania przez platformę Android.

Poziomy uprawnień Androida wskazują na potencjalne ryzyko związane z uprawnieniami:

  • Normalne: uprawnienia o niskim ryzyku, które są automatycznie przyznawane w momencie instalacji.
  • Niebezpieczne: uprawnienia wysokiego ryzyka, które mogą umożliwiać dostęp do wrażliwych danych użytkownika. Wymagają one wyraźnej zgody użytkownika w czasie działania aplikacji.
  • Podpis: przyznawany tylko aplikacjom podpisanym tym samym certyfikatem co aplikacja deklarująca uprawnienie. Zwykle używany w przypadku aplikacji systemowych lub interakcji między aplikacjami tego samego dewelopera.

W przypadku kontroli dostępu na podstawie uprawnień występują luki związane z komponentami aplikacji (takich jak aktywność, odbiorca, dostawca treści lub usługa), które spełniają wszystkie te kryteria:

  • komponent nie jest powiązany z żadnym android:permission w Manifest;
  • komponent wykonuje zadanie związane z danymi wrażliwymi, do których dostęp wymaga uprawnienia, które użytkownik już zatwierdził;
  • Komponent jest eksportowany;
  • komponent nie wykonuje żadnych ręcznych kontroli uprawnień (na poziomie pliku manifestu lub kodu);

W takim przypadku złośliwa aplikacja może wykonywać działania związane z danymi newralgicznymi, wykorzystując uprawnienia podatnego na ataki komponentu, a następnie przekazując uprawnienia podatnej na ataki aplikacji złośliwej aplikacji.

Wpływ

Eksportowanie podatnych komponentów może służyć do uzyskiwania dostępu do zasobów poufnych lub wykonywania działań związanych z danymi poufnymi. Skutki tego niepożądanego zachowania zależą od kontekstu podatnego na atak komponentu i jego uprawnień.

Środki zaradcze

Wymagaj uprawnień do zadań związanych z danymi poufnymi

Podczas eksportowania komponentu z uprawnieniami dostępu do danych wrażliwych wymagaj tych samych uprawnień dla wszystkich przychodzących żądań. IDE Android Studio zawiera mechanizmy kontroli lint dla odbiorcówusług, które wykrywają tę lukę w zabezpieczeniach i zalecają wymaganie odpowiednich uprawnień.

Programiści mogą wymagać uprawnień do przychodzących żądań, deklarując je w pliku Manifest lub na poziomie kodu podczas implementacji usługi, jak w przypadku przykładów poniżej.

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

    }
}

Nie eksportuj komponentu

Unikaj eksportowania komponentów z dostępem do zasobów poufnych, chyba że jest to absolutnie konieczne. Aby to zrobić, ustaw wartość android:exported w pliku Manifest na false. Od poziomu interfejsu API 31 w górę ten atrybut jest domyślnie ustawiony na false.

Xml

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

Stosowanie uprawnień na podstawie podpisu

Udostępniając dane 2 aplikacjom, które są pod Twoją kontrolą lub należą do Ciebie, używaj uprawnień opartych na sygnaturze. Te uprawnienia nie wymagają potwierdzenia przez użytkownika, a zamiast tego sprawdzają, czy aplikacje uzyskujące dostęp do danych są podpisane tym samym kluczem podpisywania. Takie rozwiązanie zapewnia większą wygodę i bezpieczeństwo użytkowników. Jeśli deklarujesz uprawnienia niestandardowe, zapoznaj się z odpowiednimi wskazówkami dotyczącymi bezpieczeństwa.

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" />

Punkty końcowe pojedynczego zadania

Wdrożyć aplikację zgodnie z zasadą oddzielania funkcji. Każdy punkt końcowy powinien wykonywać tylko pewien zestaw określonych zadań z określonymi uprawnieniami. Ta dobra praktyka projektowania umożliwia też deweloperowi stosowanie szczegółowych uprawnień do poszczególnych punktów końcowych. Nie należy na przykład tworzyć pojedynczego punktu końcowego, który obsługuje zarówno kalendarz, jak i kontakty.

Materiały