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

Kategoria OWASP: MASVS-PLATFORM: Platform Interaction

Przegląd

Uprawnienie Androida to identyfikator w postaci ciągu znaków zadeklarowany w manifeście aplikacji, który służy do żądania dostępu do danych lub działań o ograniczonym dostępie. Jest on egzekwowany w czasie działania przez platformę Androida.

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

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

Luki w zabezpieczeniach związane z kontrolą dostępu opartą na uprawnieniach występują, gdy komponent aplikacji (np. aktywność, odbiornik, dostawca treści lub usługa) spełnia wszystkie te kryteria:

  • komponent nie jest powiązany z żadnym elementem android:permissionManifest;
  • komponent wykonuje zadanie związane z poufnymi danymi, do którego istnieje uprawnienie, które użytkownik już zatwierdził;
  • Komponent jest eksportowany.
  • Komponent nie przeprowadza żadnych ręcznych kontroli uprawnień (na poziomie pliku manifestu ani kodu);

W takim przypadku złośliwa aplikacja może wykonywać działania wymagające dostępu do informacji poufnych, wykorzystując uprawnienia podatnego na ataki komponentu i przekazując je do złośliwej aplikacji.

Wpływ

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

Środki ograniczające ryzyko

Wymaganie uprawnień do wykonywania działań związanych z danymi poufnymi

Podczas eksportowania komponentu z uprawnieniami dostępu do informacji poufnych wymagaj tych samych uprawnień w przypadku każdego przychodzącego żądania. Środowisko IDE Android Studio ma testy lint dla odbiornikówusług, które pozwalają wykryć tę lukę w zabezpieczeniach i zalecają wymaganie odpowiednich uprawnień.

Programiści mogą wymagać uprawnień w przypadku przychodzących żądań, deklarując je w pliku Manifest lub na poziomie kodu podczas wdrażania usługi, jak w poniższych przykładach.

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 wrażliwych, chyba że jest to absolutnie konieczne. Aby to zrobić, ustaw wartość android:exported w pliku Manifest na false w przypadku komponentu. Od poziomu API 31 ten atrybut jest domyślnie ustawiony na wartość false.

XML

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

Stosowanie uprawnień na podstawie podpisu

Podczas udostępniania danych między 2 aplikacjami, które kontrolujesz lub których jesteś właścicielem, używaj uprawnień opartych na sygnaturze. Te uprawnienia nie wymagają potwierdzenia przez użytkownika, ale sprawdzają, czy aplikacje uzyskujące dostęp do danych są podpisane tym samym kluczem podpisu. Ta konfiguracja zapewnia bardziej uproszczone i bezpieczne korzystanie z usługi. Jeśli deklarujesz uprawnienia niestandardowe, zapoznaj się z odpowiednimi wytycznymi 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

Zaimplementuj aplikację zgodnie z zasadą projektowania Separation of Concerns. Każdy punkt końcowy powinien wykonywać tylko niewielki zestaw określonych zadań z określonymi uprawnieniami. Ta dobra praktyka projektowania umożliwia też programiście stosowanie szczegółowych uprawnień do każdego punktu końcowego. Nie należy na przykład tworzyć jednego punktu końcowego, który obsługuje zarówno kalendarz, jak i kontakty.

Zasoby