Aktivitätssicherheit

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

Beschränkungen beim Starten von Hintergrundaktivitäten

Ein Start einer Hintergrundaktivität (Background Activity Launch, BAL) erfolgt, wenn eine App, die nicht im Vordergrund ist, keine sichtbaren Aktivitäten hat oder eine PendingIntent von einer anderen App empfangen hat, versucht, eine neue Aktivität zu starten. Dies ist ein Start einer Hintergrundaktivität (Background Activity Launch, 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) gibt es Einschränkungen dafür, wann Apps Aktivitäten im Hintergrund starten können. Diese Schutzmaßnahmen tragen dazu bei, schädliches App-Verhalten zu verhindern und die Nutzerfreundlichkeit zu verbessern, indem sie häufige Missbrauchsfälle wie die folgenden eindämmen:

  • 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 oft durch 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 steigern.

Vordergrunddienste (für laufende Aufgaben)

Wenn Ihre App eine zeitaufwendige 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 vom Nutzer nicht geschlossen werden kann. Diese Benachrichtigung kann interaktive Steuerelemente enthalten, z. B. Schaltflächen zum Abspielen/Pausieren für eine Musik-App. So wird der Nutzer informiert und behält die Kontrolle, wird aber nicht durch eine Vollbildaktivität unterbrochen.

Wenn Sie diese Hierarchie einhalten und erst bei Bedarf auf aufdringlichere Optionen zurückgreifen, schaffen Sie eine bessere und vorhersehbarere Nutzererfahrung.

Wann sind Starts von Hintergrundaktivitäten zulässig (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 (IME).
  • Die Aktivität wird über ein PendingIntent gestartet, das vom System gesendet wurde (z. B. durch Tippen auf eine Benachrichtigung).
  • Der Nutzer hat der App die Berechtigung SYSTEM_ALERT_WINDOW 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 über einen Kernbestandteil des Betriebssystems, der jederzeit ausgeführt werden muss, z. B. über den Telefondienst, der den Bildschirm für eingehende Anrufe startet.

Neue Härtung und erforderliche Opt-ins

Um die Sicherheit weiter zu verbessern, hat Android strengere Regeln eingeführt, die eine explizite Einwilligung für Apps erfordern, die PendingIntent und IntentSender zum Starten von Aktivitäten verwenden. Ein Start ist nur zulässig, wenn entweder die App, die PendingIntent erstellt hat, oder die App, die sie sendet, die Berechtigung für den Hintergrundstart gewährt.

In den meisten Fällen sollte die App, die die PendingIntent sendet, die Einwilligung einholen, da der Nutzer in der Regel direkt mit dieser App interagiert (z. B. durch Tippen auf einen Button).

Absender müssen PendingIntent aktivieren

Wenn Ihre App auf Android 14 (API‑Level 34) oder höher ausgerichtet ist, werden ihr beim Senden eines PendingIntent nicht mehr standardmäßig BAL-Berechtigungen gewährt. Wenn Sie nicht ausdrücklich zustimmen, wird der Start der Aktivität möglicherweise blockiert, es sei denn, der Creator von PendingIntent hat bereits eigene Berechtigungen erteilt.

Damit der Start erfolgreich ist, muss der Absender seine Berechtigungen durch Aufrufen von ActivityOptions.setPendingIntentBackgroundActivityStartMode() gewähren. 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 die PendingIntent gesendet wird. So wird besser sichergestellt, dass der Start einer Aktivität eine direkte Folge der Interaktion eines Nutzers mit Ihrer App ist.

Tabelle mit ausstehenden Intents
Abbildung 1: Entscheidungsablauf für das Starten 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)
}

Creator müssen PendingIntent aktivieren.

Wenn Ihre App auf Android 15 (API‑Level 35) oder höher ausgerichtet ist, werden die Berechtigungen für den Start im Hintergrund für eine App, die eine PendingIntent erstellt, nicht mehr standardmäßig gewährt. Damit der Absender die BAL-Berechtigungen Ihrer App verwenden kann, müssen Sie dies explizit aktivieren.

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())

Mit IntentSender starten

Dieselben BAL-Einschränkungen gelten auch, wenn Aktivitäten über einen IntentSender gestartet werden. Da ein IntentSender über PendingIntent.getIntentSender abgerufen wird, unterliegt es ähnlichen Opt-in-Anforderungen.

  • Ab Android 14 (API 34) ist für die Verwendung von Context.startIntentSender() eine Einwilligung des Absenders 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 Einwilligung des Absenders 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: BAL-Einschränkungen

Tabelle mit ausstehenden Intents
Abbildung 2: Der Prozess zum sicheren Starten einer Aktivität mit einem PendingIntent

Dieses Diagramm veranschaulicht, wie eine Aktivität sicher mit einem PendingIntent gestartet wird. Eine erfolgreiche Einführung hängt von einer gültigen Berechtigungskette ab, in der mindestens eine der beteiligten Apps ihre Berechtigungen erteilt und eine Aktivität im Hintergrund starten kann.

  1. Erstellung und Delegation (App A – Der Ersteller)
    1. Die Creator-App erstellt die PendingIntent
    2. Wenn das Targeting auf SDK 35 oder höher erfolgt, muss der Ersteller seine BAL-Berechtigungen explizit mit setPendingIntentCreatorBackgroundActivityStartMode() delegieren, damit sie verwendet werden können. Standardmäßig werden keine Berechtigungen delegiert.
    3. Die PendingIntent wird dann an eine andere App (App B) gesendet.
  2. Start und Beitrag (App B – der Absender)
    1. Später initiiert die Sender-App den Start durch Aufrufen von PendingIntent.send().
    2. Wenn das SDK auf SDK 34 oder höher ausgerichtet ist, muss der Absender seine eigenen Berechtigungen explizit mit setPendingIntentBackgroundActivityStartMode() beitragen, wenn er möchte, dass seine Berechtigungen verwendet werden. Standardmäßig werden keine Berechtigungen delegiert.
  3. Validierung der Android-Systemsicherheit
    1. Das Android-System fängt die Startanfrage ab und führt eine Sicherheitsprüfung durch.
    2. Es werden zwei Bedingungen ausgewertet:
    3. Hat der Creator seine Berechtigungen delegiert UND erfüllt die Creator-App derzeit eine der allgemeinen Ausnahmen für die Abrechnung über den Nutzer?
    4. Hat der Sender seine Berechtigungen beigetragen UND erfüllt die Sender-App derzeit eine der allgemeinen Ausnahmen für die BAL?
  4. Ergebnis
    1. ALLOWED: Wenn mindestens eine der beiden Bedingungen in Schritt 3 erfüllt ist, wird die Berechtigungskette validiert. Das Android-System startet die Ziel-Activity und der Absender erhält ein Erfolgsresultat.
    2. BLOCKED: Wenn keine der Bedingungen erfüllt ist, blockiert das System den Start. Die Sender-App erhält keinen direkten Rückgabewert oder keine Ausnahme, die auf den Fehler hinweist. Stattdessen protokolliert das Android-System intern die Meldung Background activity launch blocked! in Logcat, die Entwickler zur Fehlerbehebung prüfen müssen.

Schutz vor Task-Hijacking

Um In-Task-Hijacking-Angriffe (z. B. das „Activity Sandwich“) zu verhindern, werden in Android 15 neue Regeln für Apps eingeführt, 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 einem Vordergrund-Task, die der UID der obersten Aktivität entspricht, darf einen neuen Task erstellen oder einen anderen, vorhandenen Task in den Vordergrund bringen.

Aktivierung von Schutzmaßnahmen für Aufgaben durch Entwickler

Dieses Verhalten kann ab dem Target SDK 37 aktiviert werden. Sie müssen es explizit aktivieren. Sie soll In-Task-Hijacking (oder Activity-Sandwiching) verhindern. Dabei könnte eine schädliche App eine Aktivität im Task Ihrer App starten, um sich als Ihre App auszugeben und Nutzerdaten zu stehlen.

Schutz aktivieren

Wenn Sie ASM für Ihre Anwendung aktivieren möchten, setzen Sie das Attribut android:allowCrossUidActivitySwitchFromBelow in Ihrer AndroidManifest.xml-Datei 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öchten, 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 diesem Schutz ausnehmen möchten, rufen Sie setAllowCrossUidActivitySwitchFromBelow(true) in der Methode onCreate() dieser Aktivität auf. So kann eine Aktivität gestartet werden, während der Rest Ihrer App geschützt bleibt.

Fehlerbehebung

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

Wichtige Log-Meldungen

Blockierter Start (Fehler): Diese Meldung weist darauf hin, dass der Start einer Aktivität blockiert wurde.

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

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

Strikter Modus

Ab Android 16 kann der App-Entwickler den strikten Modus aktivieren, um benachrichtigt zu werden, wenn ein Aktivitätsstart blockiert wird oder das Risiko besteht, dass er blockiert wird, wenn das Ziel-SDK der App angehoben wird.

Beispielcode zum Aktivieren 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());
     )
 }