Aktivitätssicherheit

Android schützt Nutzer vor schädlichen Apps und bietet eine vertrauenswürdige UI-Erfahrung. Das Activity Security Framework umfasst Regeln und Plattformbeschränkungen. Diese Regeln und Beschränkungen verhindern unerwünschte UI-Unterbrechungen, Task-Hijacking und andere Sicherheitsbedrohungen. Diese Bedrohungen beziehen sich darauf, wann und wie App-Komponenten auf dem Bildschirm angezeigt werden. Eine Schlüsselkomponente dieses Frameworks beschränkt das Starten von Aktivitäten im Hintergrund.

Beschränkungen für das Starten von Hintergrundaktivitäten

Ein Start von Hintergrundaktivitäten (Background Activity Launch, BAL) erfolgt, wenn eine App, die nicht im Vordergrund ist, keine sichtbaren Aktivitäten hat oder ein PendingIntent, das von einer anderen App empfangen wurde, versucht, eine neue Aktivität zu starten. Dies ist ein Start von Hintergrundaktivitäten (BAL). Es gibt zwar legitime Anwendungsfälle, z. B. wenn eine Wecker-App gestartet wird, aber uneingeschränkte BALs führen zu einer schlechten Nutzererfahrung und schaffen Sicherheitslücken.

Warum sind sie eingeschränkt?

Seit Android 10 (API-Level 29) hat die Plattform Beschränkungen eingeführt, wann Apps Aktivitäten im Hintergrund starten können. Diese Schutzmaßnahmen helfen, schädliches App-Verhalten zu verhindern und die Nutzererfahrung zu verbessern, indem sie häufige Missbrauchsfälle reduzieren, darunter:

  • UI-Hijacking und Pop-up-Anzeigen: Eine Hintergrund-App startet unerwartet eine Aktivität (oft eine Anzeige) über der App, mit der der Nutzer gerade interagiert, und übernimmt so die Sitzung.
  • Phishing und Identitätsdiebstahl: Eine Hintergrund-App startet eine Aktivität, die eine andere App imitiert (z. B. ein gefälschter Anmeldebildschirm für eine legitime App), um Anmeldedaten von Nutzern zu stehlen. Dies geschieht häufig über einen „Activity Sandwich“-Angriff, bei dem eine schädliche Aktivität in den Task-Stack einer legitimen App eingefügt wird.
  • Tapjacking: Eine Hintergrund-App zeigt eine transparente oder verdeckte Aktivität über einer anderen App an, um die Eingaben des Nutzers abzufangen und ihn zu unbeabsichtigten Aktionen zu verleiten.
  • App-Aktivierung: Eine Hintergrundkomponente einer App aktiviert die Vordergrundkomponenten einer anderen App, um die Messwerte für täglich aktive Nutzer unrechtmäßig zu erhöhen.

Dienste im Vordergrund (für laufende Aufgaben)

Wenn Ihre App eine lang andauernde Aufgabe im Hintergrund ausführen muss, über die der Nutzer informiert werden muss, z. B. Musik abspielen oder ein Training aufzeichnen, sollten Sie einen Dienst im Vordergrund verwenden. Ein Dienst im Vordergrund muss eine dauerhafte Benachrichtigung anzeigen, die der Nutzer nicht schließen kann. Diese Benachrichtigung kann interaktive Steuerelemente enthalten (z. B. Schaltflächen zum Abspielen/Pausieren für eine Musik-App). So bleibt der Nutzer informiert und hat die Kontrolle, wird aber nicht durch eine Vollbildaktivität unterbrochen.

Wenn Sie diese Hierarchie einhalten – beginnend mit Standardbenachrichtigungen und nur bei Bedarf auf aufdringlichere Optionen umsteigen – schaffen Sie eine bessere und vorhersehbarere Nutzererfahrung.

Wann Starts von Hintergrundaktivitäten zulässig sind (Ausnahmen)

Eine App kann eine Aktivität im Hintergrund starten, wenn eine der folgenden Bedingungen erfüllt ist:

  • Die App hat ein sichtbares Fenster, z. B. eine Aktivität im Vordergrund.
  • Die App ist der aktuelle Eingabemethoden-Editor (Input Method Editor, IME).
  • Die Aktivität wird über ein PendingIntent gestartet, das vom System gesendet wurde (z. B. durch Tippen auf eine Benachrichtigung).
  • Der App wurde die Berechtigung SYSTEM_ALERT_WINDOW vom Nutzer erteilt.
  • Der App wurde die Berechtigung START_ACTIVITIES_FROM_BACKGROUND erteilt.
  • Die App ist an einen Dienst gebunden, dem die Berechtigung zum Starten von Hintergrundaktivitäten erteilt wurde.
  • Der Start wird von der Launcher-App des Geräts initiiert, z. B. wenn ein Nutzer auf ein App-Symbol tippt oder mit einem Widget interagiert.
  • Der Start erfolgt von einem Kernbestandteil des Betriebssystems, der immer ausgeführt werden muss, z. B. wenn der Telefondienst den Bildschirm für eingehende Anrufe startet.

Neue Härtung und erforderliche Aktivierungen

Um die Sicherheit weiter zu verbessern, hat Android strengere Regeln eingeführt, die explizite Aktivierungen für Apps erfordern, die PendingIntent und IntentSender verwenden, um Aktivitäten zu starten. Ein Start ist nur zulässig, wenn entweder die App, die das PendingIntent erstellt hat, oder die App, die es sendet, ihre Berechtigungen für den Start im Hintergrund aktiviert.

In den meisten Fällen sollte die App, die das PendingIntent sendet , die Aktivierung vornehmen, da sie in der Regel die App ist, mit der der Nutzer direkt interagiert (z. B. durch Tippen auf eine Schaltfläche).

Absender müssen PendingIntent aktivieren

Wenn Ihre App auf Android 14 (API-Level 34) oder höher ausgerichtet ist, werden ihre Berechtigungen für das Starten von Hintergrundaktivitäten beim Senden eines PendingIntent nicht mehr standardmäßig erteilt. Wenn Sie die Aktivierung nicht explizit vornehmen, wird der Start der Aktivität möglicherweise blockiert, es sei denn, der Ersteller des PendingIntent hat seine eigenen Berechtigungen bereits erteilt.

Damit ein Start erfolgreich ist, sollte der Absender seine Berechtigungen aktivieren, indem er ActivityOptions.setPendingIntentBackgroundActivityStartMode() aufruft. Der empfohlene Modus ist ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOW_IF_VISIBLE (hinzugefügt in SDK 36).

Dies ist ein strengerer und sichererer Modus. Die Berechtigung wird nur erteilt, wenn die sendende App auf dem Bildschirm sichtbar ist, wenn das PendingIntent gesendet wird. So wird besser sichergestellt, dass der Start der Aktivität eine direkte Folge der Interaktion eines Nutzers mit Ihrer App ist.

Tabelle mit ausstehenden Intents
Abbildung 1: Entscheidungsablauf für Starts von Hintergrundaktivitäten

Verwenden Sie ActivityOptions.setPendingIntentBackgroundActivityStartMode(), um Berechtigungen zu erteilen.

// Sender Side
ActivityOptions options = ActivityOptions.makeBasic()
    .setPendingIntentBackgroundActivityStartMode(
        ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOW_IF_VISIBLE);

try {
    myPendingIntent.send(options.toBundle());
} catch (PendingIntent.CanceledException e) {
    Log.e(TAG, "The PendingIntent was canceled", e);
}
// Sender Side
val options = ActivityOptions.makeBasic().apply {
    pendingIntentBackgroundActivityStartMode = ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOW_IF_VISIBLE
}

try {
    myPendingIntent.send(options.toBundle())
} catch (e: PendingIntent.CanceledException) {
    Log.e(TAG, "The PendingIntent was canceled", e)
}

Ersteller müssen PendingIntent aktivieren

Wenn Ihre App auf Android 15 (API-Level 35) oder höher ausgerichtet ist, erteilt eine App, die ein PendingIntent erstellt , ihre Berechtigungen für den Start im Hintergrund nicht mehr standardmäßig. Damit der Absender die Berechtigungen für das Starten von Hintergrundaktivitäten Ihrer App verwenden kann, müssen Sie die Aktivierung explizit vornehmen.

Verwenden Sie ActivityOptions.setPendingIntentCreatorBackgroundActivityStartMode(), um Berechtigungen zu erteilen.

// Creator Side
Intent intent = new Intent(context, MyActivity.class);
ActivityOptions options = ActivityOptions.makeBasic().setPendingIntentCreatorBackgroundActivityStartMode(ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED);

PendingIntent pendingIntent = PendingIntent.getActivity(context, REQUEST_CODE, intent, PendingIntent.FLAG_IMMUTABLE, options.toBundle());
// Creator Side
val intent = Intent(context, MyActivity::class.java)
val options = ActivityOptions.makeBasic().apply {
    pendingIntentCreatorBackgroundActivityStartMode = ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED
}

val pendingIntent = PendingIntent.getActivity(context, REQUEST_CODE, intent,
        PendingIntent.FLAG_IMMUTABLE, options.toBundle())

Starten mit IntentSender

Dieselben Beschränkungen für das Starten von Hintergrundaktivitäten gelten auch, wenn Aktivitäten mit einem IntentSender gestartet werden. Da ein IntentSender über PendingIntent.getIntentSender abgerufen wird, gelten ähnliche Aktivierungs anforderungen.

  • Ab Android 14 (API 34) ist für die Verwendung von Context.startIntentSender() eine Aktivierung auf Absenderseite erforderlich. Sie müssen hier auch das ActivityOptions-Bundle angeben.
ActivityOptions options = ActivityOptions.makeBasic()
        .setPendingIntentBackgroundActivityStartMode(
            ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED);

context.startIntentSender(myIntentSender, fillInIntent, flagsMask,
        flagsValues, extraFlags, options.toBundle());
val options = ActivityOptions.makeBasic().apply {
    pendingIntentBackgroundActivityStartMode = ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED
}

context.startIntentSender(myIntentSender, fillInIntent, flagsMask,
        flagsValues, extraFlags, options.toBundle())
  • Ab Android 17 (API 37+) ist für die Verwendung von IntentSender.sendIntent() eine Aktivierung auf Absenderseite erforderlich.
ActivityOptions options = ActivityOptions.makeBasic()
        .setPendingIntentBackgroundActivityStartMode(
            ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED);

myIntentSender.sendIntent(context, code, intent, onFinished, handler,
        requiredPermission, options.toBundle());
val options = ActivityOptions.makeBasic().apply {
    pendingIntentBackgroundActivityStartMode = ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED
}

myIntentSender.sendIntent(context, code, intent, onFinished, handler,
        requiredPermission, options.toBundle())

Sequenzdiagramm: Beschränkungen für das Starten von Hintergrundaktivitäten

Tabelle mit ausstehenden Intents
Abbildung 2: Sicheres Starten einer Aktivität mit einem PendingIntent

Dieses Diagramm veranschaulicht den Prozess des sicheren Startens einer Aktivität mit einem PendingIntent. Ein erfolgreicher Start hängt von einer gültigen Berechtigungskette ab, bei der mindestens eine der beteiligten Apps sowohl ihre Berechtigungen erteilt als auch eine Aktivität im Hintergrund starten kann.

  1. Erstellung und Delegierung (App A – der Ersteller)
    1. Die Ersteller-App erstellt das PendingIntent.
    2. Wenn SDK 35 oder höher verwendet wird, muss der Ersteller seine Berechtigungen für das Starten von Hintergrundaktivitäten explizit delegieren, indem er setPendingIntentCreatorBackgroundActivityStartMode() verwendet, wenn seine Berechtigungen verwendet werden sollen. Standardmäßig werden keine Berechtigungen delegiert.
    3. Das PendingIntent wird dann an eine andere App (App B) gesendet.
  2. Start und Beitrag (App B – der Absender)
    1. Später initiiert die Absender-App den Start, indem sie PendingIntent.send() aufruft.
    2. Wenn SDK 34 oder höher verwendet wird, muss der Absender seine eigenen Berechtigungen explizit beitragen, indem er setPendingIntentBackgroundActivityStartMode() verwendet, wenn seine Berechtigungen verwendet werden sollen. Standardmäßig werden keine Berechtigungen delegiert.
  3. Sicherheitsüberprüfung des Android-Systems
    1. Das Android-System fängt die Startanfrage ab und führt eine Sicherheitsüberprüfung durch.
    2. Dabei werden zwei Bedingungen geprüft:
    3. Hat der Ersteller seine Berechtigungen delegiert UND erfüllt die Ersteller-App derzeit eine der allgemeinen Ausnahmen für das Starten von Hintergrundaktivitäten?
    4. Hat der Absender seine Berechtigungen beigetragen UND erfüllt die Absender-App derzeit eine der allgemeinen Ausnahmen für das Starten von Hintergrundaktivitäten?
  4. Ergebnis
    1. ZULÄSSIG: Wenn mindestens eine der beiden Bedingungen in Schritt 3 erfüllt ist, wird die Berechtigungskette validiert. Das Android-System startet die Zielaktivität und der Absender erhält ein Erfolgsergebnis.
    2. BLOCKIERT: Wenn keine der beiden Bedingungen erfüllt ist, blockiert das System den Start. Die Absender-App erhält keinen direkten Rückgabewert oder keine Ausnahme, die auf den Fehler hinweist. Stattdessen protokolliert das Android-System intern die "Background activity launch blocked!" Meldung in Logcat, die Entwickler zur Fehlerbehebung prüfen müssen.

Verhinderung von Task-Hijacking

Um Angriffe auf Task-Hijacking (z. B. „Activity Sandwich“) zu verhindern, führt Android 15 neue Regeln für Apps ein, die auf API-Level 37 oder höher ausgerichtet sind.

  • Regel 1: Innerhalb einer einzelnen Aufgabe kann eine Aktivität nur von einer anderen Aktivität gestartet werden, die zur selben Anwendung gehört (d. h. dieselbe UID hat) wie die aktuelle oberste Aktivität in der Aufgabe.
  • Regel 2: Nur eine Aktivität in einer Vordergrundaufgabe, die mit der UID von der obersten Aktivität übereinstimmt, darf eine neue Aufgabe erstellen oder eine andere, vorhandene Aufgabe in den Vordergrund bringen.

Aktivierung durch Entwickler für Schutzmaßnahmen innerhalb von Aufgaben

Dieses Verhalten kann ab SDK 37 aktiviert werden. Sie müssen die Aktivierung explizit vornehmen. Es soll Task-Hijacking (oder Activity Sandwiching) verhindern, bei dem eine schädliche App eine Aktivität in die Aufgabe Ihrer App starten könnte, um sie zu imitieren und Nutzerdaten zu stehlen.

Schutzmaßnahmen aktivieren

Wenn Sie ASM für Ihre Anwendung aktivieren möchten, setzen Sie das Attribut android:allowCrossUidActivitySwitchFromBelow in der Datei AndroidManifest.xml auf „false“. Dies ist eine Einstellung auf Anwendungsebene, die standardmäßig alle Aktivitäten in Ihrer App schützt.

Ausnahmen für bestimmte Aktivitäten erstellen

Wenn Sie die Funktion für Ihre App aktiviert haben, aber zulassen müssen, dass eine bestimmte vertrauenswürdige Aktivität von anderen Apps gestartet wird, können Sie eine gezielte Ausnahme erstellen. Wenn Sie eine einzelne Aktivität von dieser Schutzmaßnahme ausnehmen möchten, rufen Sie setAllowCrossUidActivitySwitchFromBelow(true) in der Methode onCreate() dieser Aktivität auf. So kann diese eine Aktivität gestartet werden, während der Rest Ihrer App geschützt bleibt.

Fehlerbehebung

Filtern Sie Logcat, um relevante Nachrichten mit einem regulären Ausdruck zu finden. Das Tag ActivityTaskManager wird häufig verwendet. Wenn Sie nach ActivityTaskManager filtern, können Sie die Logs isolieren.

Wichtige Logmeldungen

Blocked Launch (Error) (Blockierter Start (Fehler)): Diese Meldung gibt an, dass ein Aktivitätsstart blockiert wurde.

  • Bedeutung: Ein Aktivitätsstart wurde abgelehnt, weil die erforderliche Aktivierung von PendingIntent entweder beim Absender (SDK 34 oder höher) oder beim Ersteller (SDK 35 oder höher) fehlte.
  • Aktion: Sie müssen Ihren Code aktualisieren, um die korrekte ActivityOptions Aktivierung einzufügen.

Prüfen Sie beim Analysieren der Logs die folgenden Felder:

  • realCallingPackage: Die App, die das PendingIntent gesendet hat. Das ist der Absender.
  • callingPackage: Die App, die das PendingIntent erstellt hat. Das ist der Ersteller.

Strikter Modus

Ab Android 16 kann der App-Entwickler den strikten Modus aktivieren, um benachrichtigt zu werden, wenn ein Aktivitätsstart blockiert wird (oder blockiert zu werden droht, wenn das Ziel-SDK der App erhöht wird).

Beispielcode zum Aktivieren des strikten Modus in der Methode Application.onCreate() Ihrer Anwendung, Aktivität oder einer anderen Anwendungskomponente:

override fun onCreate(savedInstanceState: Bundle?) {
     super.onCreate(savedInstanceState)
     StrictMode.setVmPolicy(
         StrictMode.VmPolicy.Builder()
         .detectBlockedBackgroundActivityLaunch()
         .penaltyLog()
         .build());
     )
 }