Android bietet integrierte Sicherheitsfunktionen, die die Häufigkeit und Auswirkungen von Problemen mit der Anwendungssicherheit erheblich reduzieren. Das System ist so konzipiert, dass Sie Ihre Apps in der Regel mit den Standardsystem- und Dateiberechtigungen erstellen und schwierige Entscheidungen in Bezug auf die Sicherheit vermeiden können.
Die folgenden grundlegenden Sicherheitsfunktionen helfen Ihnen, sichere Apps zu entwickeln:
- Die Android-Anwendungs-Sandbox, die Ihre App-Daten und die Codeausführung von anderen Apps isoliert.
- Ein Anwendungsframework mit robusten Implementierungen gängiger Sicherheitsfunktionen wie Kryptografie, Berechtigungen und sicherer Interprozesskommunikation (IPC).
- Technologien wie Address Space Layout Randomization (ASLR), No-Execute (NX), ProPolice, safe_iop, OpenBSD
dlmalloc
undcalloc
sowie Linuxmmap_min_addr
zur Minimierung von Risiken, die mit häufigen Fehlern bei der Speicherverwaltung verbunden sind. - Vom Nutzer gewährte Berechtigungen, um den Zugriff auf Systemfunktionen und Nutzerdaten einzuschränken.
- Anwendungsdefinierte Berechtigungen zur App-spezifischen Steuerung von Anwendungsdaten.
Sie sollten sich mit den Best Practices für die Android-Sicherheit auf dieser Seite vertraut machen. Wenn Sie diese Praktiken als allgemeine Programmiergewohnheiten befolgen, können Sie unbeabsichtigte Sicherheitsprobleme vermeiden, die sich negativ auf Ihre Nutzer auswirken.
Authentifizierung
Die Authentifizierung ist eine Voraussetzung für viele wichtige Sicherheitsvorgänge. Wenn Sie den Zugriff auf geschützte Assets wie Nutzerdaten, App-Funktionen und andere Ressourcen steuern möchten, müssen Sie Ihrer Android-App eine Authentifizierung hinzufügen.
Sie können die Authentifizierung für Ihre Nutzer verbessern, indem Sie Ihre App in den Credential Manager einbinden. Der Anmeldedaten-Manager ist eine Android Jetpack-Bibliothek, die die API-Unterstützung für die meisten gängigen Authentifizierungsmethoden vereint, einschließlich Passkeys, Passwörtern und Lösungen für die föderierte Anmeldung wie Über Google anmelden.
Um die Sicherheit Ihrer App weiter zu erhöhen, sollten Sie biometrische Authentifizierungsmethoden wie Fingerabdruck- oder Gesichtserkennung hinzufügen. Apps für Finanzen, Gesundheitswesen oder Identitätsverwaltung eignen sich gut für die biometrische Authentifizierung.
Das Autofill-Framework von Android kann die Registrierung und Anmeldung erleichtern und so Fehlerraten und Nutzeraufwand reduzieren. Autofill lässt sich in Passwortmanager einbinden, sodass Nutzer komplexe, zufällige Passwörter auswählen können, die einfach und sicher gespeichert und abgerufen werden können.
App-Integrität
Mit der Play Integrity API können Sie prüfen, ob Interaktionen und Serveranfragen von Ihrem echten App-Binärprogramm stammen, das auf einem echten Android-Gerät ausgeführt wird. Wenn potenziell riskante und betrügerische Interaktionen erkannt werden, z. B. von manipulierten App-Versionen und nicht vertrauenswürdigen Umgebungen, kann der Backend-Server Ihrer App mit geeigneten Maßnahmen reagieren, um Angriffe zu verhindern und Missbrauch zu reduzieren.
Datenspeicherung
Das häufigste Sicherheitsrisiko für eine Android-Anwendung besteht darin, ob andere Apps auf die auf dem Gerät gespeicherten Daten zugreifen können. Es gibt drei grundlegende Möglichkeiten, Daten auf dem Gerät zu speichern:
- Interner Speicher
- Externer Speicher
- Contentanbieter
In den folgenden Abschnitten werden die mit den einzelnen Ansätzen verbundenen Sicherheitsprobleme beschrieben.
Interner Speicher
Standardmäßig ist der Zugriff auf Dateien, die Sie im internen Speicher erstellen, nur für Ihre App möglich. Android implementiert diesen Schutz, der für die meisten Anwendungen ausreicht.
Verwenden Sie die nicht mehr unterstützten Modi MODE_WORLD_WRITEABLE
und MODE_WORLD_READABLE
für IPC-Dateien nicht. Sie bieten keine Möglichkeit, den Datenzugriff auf bestimmte Anwendungen zu beschränken, und es gibt keine Kontrolle über das Datenformat. Wenn Sie Ihre Daten für andere App-Prozesse freigeben möchten, sollten Sie stattdessen einen Inhaltsanbieter verwenden. Dieser bietet anderen Apps Lese- und Schreibberechtigungen und kann dynamisch Berechtigungen erteilen.
Externer Speicher
Dateien, die auf externen Speichermedien wie SD-Karten erstellt werden, sind global lesbar und beschreibbar. Da externer Speicher vom Nutzer entfernt und von jeder Anwendung geändert werden kann, sollten Sie nur nicht vertrauliche Daten extern speichern.
Führen Sie bei der Verarbeitung von Daten aus externen Speichern eine Eingabevalidierung durch, wie Sie es bei Daten aus einer nicht vertrauenswürdigen Quelle tun würden. Speichern Sie ausführbare Dateien oder Klassendateien nicht vor dem dynamischen Laden im externen Speicher. Wenn Ihre App ausführbare Dateien aus dem externen Speicher abruft, müssen die Dateien vor dem dynamischen Laden signiert und kryptografisch verifiziert werden.
Contentanbieter
Contentanbieter bieten einen strukturierten Speichermechanismus, der auf Ihre eigene Anwendung beschränkt oder exportiert werden kann, um den Zugriff durch andere Anwendungen zu ermöglichen. Wenn Sie anderen Apps keinen Zugriff auf Ihre ContentProvider
gewähren möchten, kennzeichnen Sie sie im App-Manifest als android:exported=false
. Andernfalls legen Sie das Attribut android:exported
auf true
fest, damit andere Apps auf die gespeicherten Daten zugreifen können.
Wenn Sie eine ContentProvider
erstellen, die für die Verwendung in anderen Anwendungen exportiert wird, können Sie eine einzelne Berechtigung für das Lesen und Schreiben angeben oder unterschiedliche Berechtigungen für das Lesen und Schreiben. Beschränken Sie die Berechtigungen auf die, die für die jeweilige Aufgabe erforderlich sind. Denken Sie daran, dass es in der Regel einfacher ist, Berechtigungen später hinzuzufügen, um neue Funktionen freizugeben, als sie zu entfernen und Auswirkungen auf bestehende Nutzer zu haben.
Wenn Sie einen Contentanbieter verwenden, um Daten nur zwischen Ihren eigenen Apps auszutauschen, empfehlen wir, das Attribut android:protectionLevel
auf signature
-Schutz festzulegen. Für Signaturberechtigungen ist keine Nutzerbestätigung erforderlich. Sie bieten eine bessere Nutzerfreundlichkeit und einen kontrollierteren Zugriff auf die Daten des Inhaltsanbieters, wenn die Apps, die auf die Daten zugreifen, mit demselben Schlüssel signiert sind.
Contentanbieter können auch einen detaillierteren Zugriff gewähren, indem sie das Attribut android:grantUriPermissions
deklarieren und die Flags FLAG_GRANT_READ_URI_PERMISSION
und FLAG_GRANT_WRITE_URI_PERMISSION
im Objekt Intent
verwenden, das die Komponente aktiviert. Der Umfang dieser Berechtigungen kann durch das Element <grant-uri-permission>
weiter eingeschränkt werden.
Verwenden Sie beim Zugriff auf einen Contentanbieter parametrisierte Abfragemethoden wie query
, update
und delete()
, um potenzielle SQL-Injections von nicht vertrauenswürdigen Quellen zu vermeiden. Die Verwendung parametrisierter Methoden reicht nicht aus, wenn das selection
-Argument durch Zusammenführen von Nutzerdaten erstellt wird, bevor es an die Methode gesendet wird.
Die Schreibberechtigung ist kein Garant für Sicherheit. Mit der Schreibberechtigung können SQL-Anweisungen verwendet werden, mit denen einige Daten mithilfe von Creative-WHERE
-Klauseln bestätigt und die Ergebnisse analysiert werden können. Ein Angreifer könnte beispielsweise prüfen, ob eine bestimmte Telefonnummer in einem Anrufprotokoll vorhanden ist, indem er nur eine Zeile ändert, wenn diese Telefonnummer bereits vorhanden ist. Wenn die Daten des Inhaltsanbieters eine vorhersehbare Struktur haben, entspricht die Schreibberechtigung möglicherweise sowohl dem Lesen als auch dem Schreiben.
Berechtigungen
Da Android-Apps in einer Sandbox voneinander getrennt sind, müssen sie Ressourcen und Daten ausdrücklich freigeben. Dazu deklarieren sie die Berechtigungen, die sie für zusätzliche Funktionen benötigen, die von der einfachen Sandbox nicht bereitgestellt werden, einschließlich des Zugriffs auf Gerätefunktionen wie die Kamera.
Berechtigungsanfragen
Minimieren Sie die Anzahl der Berechtigungen, die von Ihrer App angefordert werden. Wenn Sie den Zugriff auf sensible Berechtigungen einschränken, verringern Sie das Risiko eines versehentlichen Missbrauchs dieser Berechtigungen, verbessern die Akzeptanz bei den Nutzern und machen Ihre App weniger anfällig für Angreifer. Wenn eine Berechtigung für die Funktion Ihrer App nicht erforderlich ist, sollten Sie sie in der Regel nicht anfordern. Weitere Informationen finden Sie in der Anleitung Bestimmen, ob für Ihre App Berechtigungen erklärt werden müssen.
Gestalten Sie Ihre Anwendung nach Möglichkeit so, dass keine Berechtigungen erforderlich sind. Anstatt beispielsweise Zugriff auf Geräteinformationen anzufordern, um eine eindeutige Kennung zu erstellen, können Sie eine UUID für Ihre Anwendung erstellen. Weitere Informationen finden Sie im Abschnitt zu Nutzerdaten. Sie können auch statt des externen Speichers (für den eine Berechtigung erforderlich ist) den internen Speicher verwenden.
Neben dem Anfordern von Berechtigungen kann Ihre Anwendung das Element <permission>
verwenden, um IPC zu schützen, das sicherheitsrelevant ist und für andere Anwendungen freigegeben ist, z. B. ein ContentProvider
. Im Allgemeinen empfehlen wir, nach Möglichkeit andere Zugriffssteuerungen als vom Nutzer bestätigte Berechtigungen zu verwenden, da Berechtigungen für Nutzer verwirrend sein können. Sie können beispielsweise die Signaturschutzebene für Berechtigungen für die IPC-Kommunikation zwischen Anwendungen verwenden, die von einem einzelnen Entwickler bereitgestellt werden.
Sie dürfen keine berechtigungsgeschützten Daten weitergeben. Das passiert, wenn Ihre App Daten über IPC freigibt, die nur verfügbar sind, weil Ihre App die Berechtigung zum Zugriff auf diese Daten hat. Die Clients der IPC-Schnittstelle Ihrer App haben möglicherweise nicht dieselbe Berechtigung für den Datenzugriff. Weitere Informationen zur Häufigkeit und den potenziellen Auswirkungen dieses Problems finden Sie in der Forschungsarbeit Permission Re-Delegation: Attacks and Defenses, die bei USENIX veröffentlicht wurde.
Berechtigungsdefinitionen
Definieren Sie die kleinstmögliche Anzahl von Berechtigungen, die Ihren Sicherheitsanforderungen entspricht. Das Erstellen einer neuen Berechtigung ist für die meisten Anwendungen relativ selten, da die systemdefinierten Berechtigungen viele Situationen abdecken. Führen Sie gegebenenfalls Zugriffsüberprüfungen mithilfe vorhandener Berechtigungen durch.
Wenn Sie eine neue Berechtigung benötigen, überlegen Sie, ob Sie Ihre Aufgabe mit einer Signaturschutzebene erledigen können. Signaturberechtigungen sind für den Nutzer transparent und ermöglichen den Zugriff nur durch Anwendungen, die vom selben Entwickler signiert wurden wie die Anwendung, die die Berechtigungsprüfung durchführt.
Wenn Sie trotzdem eine neue Berechtigung erstellen müssen, deklarieren Sie sie im App-Manifest mit dem Element <permission>
. Apps, die die neue Berechtigung verwenden, können darauf verweisen, indem sie in ihren Manifestdateien ein <uses-permission>
-Element hinzufügen. Sie können Berechtigungen auch dynamisch mithilfe der Methode addPermission()
hinzufügen.
Wenn Sie eine Berechtigung mit dem Schutzniveau „gefährlich“ erstellen, müssen Sie eine Reihe von Aspekten berücksichtigen:
- Die Berechtigung muss einen String enthalten, der dem Nutzer die Sicherheitsentscheidung, die er treffen muss, prägnant vermittelt.
- Der Berechtigungsstring muss in viele verschiedene Sprachen lokalisiert werden.
- Nutzer entscheiden sich möglicherweise gegen die Installation einer App, weil eine Berechtigung verwirrend ist oder als riskant wahrgenommen wird.
- Anwendungen können die Berechtigung anfordern, wenn der Ersteller der Berechtigung nicht installiert wurde.
Jede dieser Optionen stellt eine erhebliche nicht technische Herausforderung für Sie als Entwickler dar und verwirrt Ihre Nutzer. Daher raten wir von der Verwendung der gefährlichen Berechtigungsstufe ab.
Netzwerke
Netzwerktransaktionen sind von Natur aus ein Sicherheitsrisiko, da sie die Übertragung von Daten umfassen, die für den Nutzer potenziell privat sind. Nutzer sind sich zunehmend der Datenschutzrisiken von Mobilgeräten bewusst, insbesondere wenn das Gerät Netzwerktransaktionen ausführt. Daher ist es sehr wichtig, dass Ihre App alle Best Practices implementiert, um die Daten der Nutzer jederzeit zu schützen.
IP-Netzwerk
Die Netzwerkfunktionen unter Android unterscheiden sich nicht wesentlich von denen anderer Linux-Umgebungen. Es ist wichtig, dass für sensible Daten geeignete Protokolle verwendet werden, z. B. HttpsURLConnection
für sicheren Webtraffic. Verwenden Sie HTTPS an allen Stellen, an denen HTTPS auf dem Server unterstützt wird, anstelle von HTTP. Da mobile Geräte häufig mit nicht gesicherten Netzwerken wie öffentlichen WLAN-Hotspots verbunden sind.
Authentifizierte, verschlüsselte Kommunikation auf Socketebene kann mit der Klasse SSLSocket
ganz einfach implementiert werden. Angesichts der Häufigkeit, mit der Android-Geräte über WLAN mit ungesicherten drahtlosen Netzwerken verbunden werden, wird die Verwendung sicherer Netzwerke für alle Anwendungen, die über das Netzwerk kommunizieren, dringend empfohlen.
Einige Anwendungen verwenden localhost-Netzwerkports für die Verarbeitung vertraulicher IPCs. Verwenden Sie diesen Ansatz nicht, da auf diese Schnittstellen auch andere Anwendungen auf dem Gerät zugreifen können. Verwenden Sie stattdessen einen Android-IPC-Mechanismus, bei dem eine Authentifizierung möglich ist, z. B. mit einem Service
. Die Bindung an die nicht spezifische IP-Adresse INADDR_ANY
ist schlechter als die Verwendung von Loopback, da Ihre Anwendung so Anfragen von jeder IP-Adresse empfangen kann.
Daten, die über HTTP oder andere unsichere Protokolle heruntergeladen wurden, sind nicht vertrauenswürdig. Dazu gehört auch die Validierung von Eingaben in WebView
und alle Antworten auf HTTP-Intents.
Telefonnetzwerk
Das SMS-Protokoll (Short Message Service) wurde hauptsächlich für die Kommunikation zwischen Nutzern entwickelt und eignet sich nicht gut für Apps, die Daten übertragen möchten. Aufgrund der Einschränkungen von SMS empfehlen wir, Firebase Cloud Messaging (FCM) und IP-Netzwerke zum Senden von Datennachrichten von einem Webserver an Ihre App auf einem Nutzergerät zu verwenden.
SMS werden weder im Netzwerk noch auf dem Gerät verschlüsselt oder stark authentifiziert. Insbesondere sollten alle SMS-Empfänger damit rechnen, dass ein böswilliger Nutzer die SMS an Ihre Anwendung gesendet hat. Verwende keine nicht authentifizierten SMS-Daten, um sensible Befehle auszuführen. Beachten Sie außerdem, dass SMS im Netzwerk gefälscht und/oder abgefangen werden können. Auf dem Android-Gerät selbst werden SMS als Broadcast-Intents übertragen, sodass sie von anderen Anwendungen mit der Berechtigung READ_SMS
gelesen oder erfasst werden können.
Eingabevalidierung
Eine unzureichende Eingabevalidierung ist eines der häufigsten Sicherheitsprobleme bei Anwendungen, unabhängig davon, auf welcher Plattform sie ausgeführt werden. Android bietet Gegenmaßnahmen auf Plattformebene, die das Risiko von Eingabevalidierungsproblemen für Anwendungen verringern. Wir empfehlen, diese Funktionen nach Möglichkeit zu verwenden. Außerdem empfehlen wir die Verwendung typsicherer Sprachen, um die Wahrscheinlichkeit von Problemen bei der Eingabevalidierung zu verringern.
Wenn Sie nativen Code verwenden, können alle Daten, die aus Dateien gelesen, über das Netzwerk empfangen oder von einem IPC empfangen werden, ein Sicherheitsrisiko darstellen. Die häufigsten Probleme sind Überläufe des Zwischenspeichers, Use-After-Free-Fehler und Off-by-One-Fehler. Android bietet eine Reihe von Technologien wie ASLR und Data Execution Prevention (DEP), die die Ausnutzung dieser Fehler verringern, aber das zugrunde liegende Problem nicht lösen. Sie können diese Sicherheitslücken vermeiden, indem Sie mit Zeiger und Puffern sorgfältig umgehen.
Bei dynamischen, stringbasierten Sprachen wie JavaScript und SQL können aufgrund von Escape-Zeichen und Script-Injection Probleme bei der Eingabevalidierung auftreten.
Wenn Sie Daten in Abfragen verwenden, die an eine SQL-Datenbank oder einen Contentanbieter gesendet werden, kann SQL-Injection ein Problem darstellen. Der beste Schutz besteht darin, parametrisierte Abfragen zu verwenden, wie im Abschnitt zu Inhaltsanbietern beschrieben. Wenn Sie Berechtigungen auf Lesezugriff oder Schreibzugriff beschränken, können Sie das Risiko von Schäden durch SQL-Injection verringern.
Wenn Sie die in diesem Abschnitt beschriebenen Sicherheitsfunktionen nicht verwenden können, achten Sie darauf, gut strukturierte Datenformate zu verwenden und prüfen Sie, ob die Daten dem erwarteten Format entsprechen. Das Blockieren bestimmter Zeichen oder das Ersetzen von Zeichen kann eine effektive Strategie sein. Diese Methoden sind in der Praxis jedoch fehleranfällig und wir empfehlen, sie nach Möglichkeit zu vermeiden.
Nutzerdaten
Die Sicherheit von Nutzerdaten lässt sich am besten dadurch erhöhen, dass du so selten wie möglich APIs verwendest, die auf vertrauliche oder personenbezogene Daten zugreifen. Wenn du Zugriff auf Nutzerdaten hast, solltest du sie nach Möglichkeit nicht speichern oder übertragen. Überlegen Sie, ob Ihre Anwendungslogik so implementiert werden kann, dass die Daten dabei als Hash-Werte oder in einem nicht umkehrbaren Format vorliegen. Wenn du z. B. den Hash-Wert einer E-Mail-Adresse als primären Schlüssel verwendest, muss die Adresse nicht übertragen oder gespeichert werden. Dadurch sinkt das Risiko, dass Daten ungewollt offengelegt werden. Außerdem wird es für Angreifer schwerer, deine App zu missbrauchen.
Authentifizieren Sie Ihre Nutzer immer, wenn Zugriff auf private Daten erforderlich ist, und verwenden Sie moderne Authentifizierungsmethoden wie Passkeys und Anmeldedaten-Manager. Wenn Ihre App auf personenbezogene Daten zugreifen muss, beachten Sie, dass Sie in einigen Gerichtsbarkeiten möglicherweise eine Datenschutzerklärung zur Verwendung und Speicherung dieser Daten vorlegen müssen. Befolgen Sie die Best Practice für Sicherheit, den Zugriff auf Nutzerdaten zu minimieren, um die Compliance zu vereinfachen.
Überlegen Sie auch, ob Ihre App personenbezogene Daten versehentlich an Dritte weitergeben könnte, z. B. an Drittanbieterkomponenten für Werbung oder an Drittanbieterdienste, die von Ihrer App verwendet werden. Wenn Sie nicht wissen, warum für eine Komponente oder einen Dienst personenbezogene Daten erforderlich sind, geben Sie diese nicht an. Im Allgemeinen verringert sich das Risiko von Problemen in diesem Bereich, wenn Sie den Zugriff auf personenbezogene Daten durch Ihre Anwendung einschränken.
Wenn Ihre App Zugriff auf sensible Daten benötigt, prüfen Sie, ob Sie sie an einen Server übertragen müssen oder ob Sie den Vorgang auf dem Client ausführen können. Sie sollten Code, der sensible Daten verwendet, auf dem Client ausführen, um die Übertragung von Nutzerdaten zu vermeiden. Achten Sie außerdem darauf, dass Nutzerdaten nicht versehentlich durch zu permissiv konfigurierte IPC-Mechanismen, von allen beschreibbare Dateien oder Netzwerk-Sockets für andere Anwendungen auf dem Gerät freigegeben werden. Eine zu permissive IPC ist ein Sonderfall des Lecks von berechtigungsgeschützten Daten, der im Abschnitt Berechtigungsanfragen behandelt wird.
Wenn eine Globally Unique Identifier (GUID) erforderlich ist, erstellen Sie eine große, eindeutige Zahl und speichern Sie sie. Verwenden Sie keine Smartphone-IDs wie die Telefonnummer oder die IMEI, die mit personenbezogenen Daten verknüpft sein könnten. Dieses Thema wird auf der Seite zu Best Practices für eindeutige Kennungen ausführlicher behandelt.
Seien Sie vorsichtig, wenn Sie auf dem Gerät Logs schreiben. Unter Android sind Protokolle eine freigegebene Ressource und stehen einer Anwendung mit der Berechtigung READ_LOGS
zur Verfügung. Auch wenn die Protokolldaten des Smartphones temporär sind und beim Neustart gelöscht werden, können durch eine unangemessene Protokollierung von Nutzerinformationen versehentlich Nutzerdaten an andere Anwendungen weitergegeben werden. Achten Sie darauf, keine personenidentifizierbaren Informationen zu erfassen, und beschränken Sie die Protokollnutzung in Produktions-Apps. Verwenden Sie zum einfachen Implementieren Debug-Flags und benutzerdefinierte Log
-Klassen mit leicht konfigurierbaren Protokollierungsebenen.
WebView
Da WebView
Webinhalte verwendet, die HTML und JavaScript enthalten können, kann eine unsachgemäße Verwendung zu häufigen Websicherheitsproblemen wie Cross-Site-Scripting (JavaScript-Injection) führen. Android bietet eine Reihe von Mechanismen, um die Auswirkungen dieser potenziellen Probleme zu verringern. Dazu wird die Funktion von WebView
auf die für Ihre Anwendung erforderlichen Mindestfunktionen beschränkt.
Wenn Ihre Anwendung JavaScript nicht direkt in einem WebView
verwendet, rufen Sie setJavaScriptEnabled
nicht auf. Diese Methode wird in einigen Beispielcodes verwendet. Wenn Sie Beispielcode, der diese Methode verwendet, in einer Produktionsanwendung wiederverwenden, entfernen Sie diesen Methodenaufruf, wenn er nicht erforderlich ist. Standardmäßig wird in WebView
kein JavaScript ausgeführt, sodass Cross-Site-Scripting nicht möglich ist.
Verwenden Sie addJavaScriptInterface()
mit besonderer Vorsicht, da damit JavaScript-Vorgänge aufgerufen werden können, die normalerweise für Android-Anwendungen reserviert sind. Wenn Sie addJavaScriptInterface()
verwenden, sollten Sie es nur auf Webseiten freigeben, auf denen alle Eingaben vertrauenswürdig sind. Wenn nicht vertrauenswürdige Eingaben zulässig sind, kann nicht vertrauenswürdiges JavaScript möglicherweise Android-Methoden in Ihrer App aufrufen. Im Allgemeinen empfehlen wir, addJavaScriptInterface()
nur für JavaScript freizugeben, das im APK Ihrer Anwendung enthalten ist.
Wenn Ihre Anwendung mit einem WebView
auf vertrauliche Daten zugreift, können Sie mit der Methode clearCache()
alle lokal gespeicherten Dateien löschen. Sie können auch serverseitige Header wie no-store
verwenden, um anzugeben, dass eine Anwendung bestimmte Inhalte nicht im Cache speichern soll.
Auf Geräten mit Plattformen älter als Android 4.4 (API-Level 19) wird eine Version von webkit
verwendet, die eine Reihe von Sicherheitsproblemen aufweist. Als Problemumgehung muss Ihre App, wenn sie auf diesen Geräten ausgeführt wird, bestätigen, dass in WebView
-Objekten nur vertrauenswürdige Inhalte angezeigt werden. Damit Ihre App nicht von potenziellen Sicherheitslücken in SSL betroffen ist, verwenden Sie das aktualisierbare Sicherheitsobjekt Provider
wie unter Sicherheitsanbieter zum Schutz vor SSL-Exploits aktualisieren beschrieben. Wenn Ihre Anwendung Inhalte aus dem offenen Web rendern muss, sollten Sie einen eigenen Renderer bereitstellen, damit Sie ihn mit den neuesten Sicherheits-Patches auf dem neuesten Stand halten können.
Anmeldedatenanfragen
Anmeldedatenanfragen sind ein Angriffsvektor. Hier sind einige Tipps, wie Sie die Sicherheit von Anmeldedatenanfragen in Ihren Android-Apps erhöhen können.
Freigabe von Anmeldedaten minimieren
- Vermeiden Sie unnötige Anmeldedatenanfragen. Um Phishing-Angriffe auffälliger und weniger erfolgreich zu machen, sollten Sie die Häufigkeit, mit der Nutzerdaten abgefragt werden, minimieren. Verwenden Sie stattdessen ein Autorisierungstoken und aktualisieren Sie es. Fordern Sie nur die für die Authentifizierung und Autorisierung erforderlichen Anmeldedaten an.
- Anmeldedaten sicher speichern Mit dem Anmeldedaten-Manager können Sie die passwortlose Authentifizierung mit Passkeys aktivieren oder die föderierte Anmeldung mithilfe von Schemata wie „Über Google anmelden“ implementieren. Wenn Sie die traditionelle Passwortauthentifizierung verwenden müssen, speichern Sie keine Nutzer-IDs und Passwörter auf dem Gerät. Führen Sie stattdessen die anfängliche Authentifizierung mit dem vom Nutzer angegebenen Nutzernamen und Passwort durch und verwenden Sie dann ein kurzlebiges, dienstspezifisches Autorisierungstoken.
- Begrenzung des Berechtigungsbereichs Fordern Sie keine weitreichenden Berechtigungen für eine Aufgabe an, die nur einen engeren Umfang erfordert.
- Beschränken Sie Zugriffstokens. Verwenden Sie Vorgänge und API-Aufrufe mit kurzlebigen Tokens.
- Authentifizierungsraten begrenzen Schnelle, aufeinanderfolgende Authentifizierungs- oder Autorisierungsanfragen können ein Anzeichen für einen Brute-Force-Angriff sein. Begrenzen Sie diese Raten auf eine angemessene Häufigkeit, damit die App weiterhin funktionsfähig und nutzerfreundlich bleibt.
Sichere Authentifizierung verwenden
- Passkeys implementieren Aktivieren Sie Passkeys als sichereres und nutzerfreundlicheres Upgrade für Passwörter.
- Fügen Sie biometrische Daten hinzu. Bieten Sie die Möglichkeit zur biometrischen Authentifizierung, z. B. per Fingerabdruck oder Gesichtserkennung, für zusätzliche Sicherheit.
- Föderierte Identitätsanbieter verwenden Credential Manager unterstützt Anbieter für die föderierte Authentifizierung, z. B. Über Google anmelden.
- Kommunikation verschlüsseln: Verwenden Sie HTTPS und ähnliche Technologien, um die Daten zu schützen, die Ihre App über ein Netzwerk sendet.
Sichere Kontoverwaltung
- Mit
AccountManager
eine Verbindung zu Diensten herstellen, auf die mehrere Anwendungen zugreifen können Verwende die KlasseAccountManager
, um einen cloudbasierten Dienst aufzurufen, und speichere keine Passwörter auf dem Gerät. - Nachdem du mit
AccountManager
eineAccount
abgerufen hast, verwendeCREATOR
, bevor du Anmeldedaten angibst, damit du nicht versehentlich Anmeldedaten an die falsche Anwendung weitergibst. - Wenn Anmeldedaten nur von von Ihnen erstellten Anwendungen verwendet werden, können Sie die Anwendung, die auf die
AccountManager
zugreift, mitcheckSignatures
überprüfen. Wenn die Anmeldedaten nur von einer Anwendung verwendet werden, können Sie alternativ einenKeyStore
zum Speichern verwenden.
Bleiben Sie wachsam
- Halten Sie Ihren Code auf dem neuesten Stand. Aktualisieren Sie Ihren Quellcode, einschließlich aller Bibliotheken und Abhängigkeiten von Drittanbietern, um sich vor den neuesten Sicherheitslücken zu schützen.
- Verdächtige Aktivitäten im Blick behalten Prüfen Sie, ob es Anzeichen für einen möglichen Missbrauch gibt, z. B. Muster für den Missbrauch von Autorisierungen.
- Code prüfen Führe regelmäßige Sicherheitsprüfungen deiner Codebasis durch, um nach potenziellen Problemen mit Anmeldedatenanfragen zu suchen.
API-Schlüsselverwaltung
API-Schlüssel sind eine wichtige Komponente vieler Android-Apps, die es ihnen ermöglicht, auf externe Dienste zuzugreifen und wichtige Funktionen wie die Verbindung zu Kartendiensten, Authentifizierungs- und Wetterdiensten auszuführen. Die Offenlegung dieser sensiblen Schlüssel kann jedoch schwerwiegende Folgen haben, einschließlich Datenpannen, unbefugten Zugriffs und finanzieller Verluste. Um solche Szenarien zu vermeiden, sollten Entwickler während des gesamten Entwicklungsprozesses sichere Strategien für die Verarbeitung von API-Schlüsseln implementieren.
API-Schlüssel müssen sorgfältig geschützt werden, um Dienste vor Missbrauch zu schützen. Wenn Sie eine Verbindung zwischen der App und einem Dienst mit einem API-Schlüssel sichern möchten, müssen Sie den Zugriff auf die API sichern. Wenn Ihre App kompiliert wird und der Quellcode Ihrer App API-Schlüssel enthält, kann ein Angreifer die App dekompilieren und diese Ressourcen finden.
Dieser Abschnitt richtet sich an zwei Gruppen von Android-Entwicklern: an diejenigen, die mit Infrastrukturteams an ihrer Pipeline für die kontinuierliche Bereitstellung arbeiten, und an diejenigen, die eigenständige Apps im Play Store bereitstellen. In diesem Abschnitt werden Best Practices für den Umgang mit API-Schlüsseln beschrieben, damit Ihre App sicher mit Diensten kommunizieren kann.
Generierung und Speicherung
Entwickler sollten den API-Schlüsselspeicher als kritische Komponente des Datenschutzes und der Nutzerprivatsphäre betrachten und einen mehrschichtigen Ansatz verfolgen.
Sichere Schlüsselspeicherung
Für eine optimale Sicherheit bei der Schlüsselverwaltung sollten Sie den Android Keystore verwenden und gespeicherte Schlüssel mit einem robusten Tool wie Tink Java verschlüsseln.
Ausschluss aus der Versionsverwaltung
Committe API-Schlüssel niemals in dein Quellcode-Repository. Wenn Sie API-Schlüssel in den Quellcode einfügen, besteht das Risiko, dass die Schlüssel in öffentlichen Repositories, freigegebenen Codebeispielen und versehentlich freigegebenen Dateien offengelegt werden. Verwenden Sie stattdessen Gradle-Plug-ins wie das secrets-gradle-plugin, um in Ihrem Projekt mit API-Schlüsseln zu arbeiten.
Umgebungsspezifische Schlüssel
Verwenden Sie nach Möglichkeit separate API-Schlüssel für Entwicklungs-, Test- und Produktionsumgebungen. Verwenden Sie umgebungsspezifische Schlüssel, um jede Umgebung zu isolieren. So verringern Sie das Risiko, dass Produktionsdaten offengelegt werden, und können manipulierte Schlüssel deaktivieren, ohne dass sich dies auf Ihre Produktionsumgebung auswirkt.
Nutzungs- und Zugriffssteuerung
Sichere API-Schlüsselpraktiken sind für den Schutz Ihrer API und Ihrer Nutzer unerlässlich. So bereiten Sie Ihre Schlüssel für eine optimale Sicherheit vor:
- Eindeutige Schlüssel für jede App generieren: Verwenden Sie separate API-Schlüssel für jede App, um manipulierten Zugriff zu identifizieren und zu isolieren.
- IP-Einschränkungen implementieren: Begrenzen Sie nach Möglichkeit die Nutzung des API-Schlüssels auf bestimmte IP-Adressen oder -Bereiche.
- Verwendung von API-Schlüsseln für mobile Apps einschränken: Sie können die Verwendung des API-Schlüssels auf bestimmte mobile Apps beschränken, indem Sie sie mit dem Schlüssel bündeln oder App-Zertifikate verwenden.
- Verdächtige Aktivitäten protokollieren und überwachen: Implementieren Sie Protokollierungs- und Überwachungsmechanismen für die API-Nutzung, um verdächtige Aktivitäten zu erkennen und potenziellen Missbrauch zu verhindern.
Hinweis: Ihr Dienst sollte Funktionen zum Einschränken von Schlüsseln auf ein bestimmtes Paket oder eine bestimmte Plattform bieten. Die Google Maps API schränkt den Schlüsselzugriff beispielsweise durch Paketnamen und Signaturschlüssel ein.
OAuth 2.0 bietet ein Framework zur Autorisierung des Zugriffs auf Ressourcen. Es definiert Standards für die Interaktion von Clients und Servern und ermöglicht eine sichere Autorisierung. Mit OAuth 2.0 können Sie die Verwendung von API-Schlüsseln auf bestimmte Clients beschränken und den Zugriffsbereich so definieren, dass jeder API-Schlüssel nur die für den beabsichtigten Zweck erforderliche Mindestzugriffsebene hat.
Schlüsselrotation und Ablauf
Um das Risiko von unbefugten Zugriffen durch nicht erkannte API-Sicherheitslücken zu verringern, ist es wichtig, API-Schlüssel regelmäßig zu wechseln. Der ISO 27001-Standard definiert ein Compliance-Framework für die Häufigkeit der Schlüsselrotation. In den meisten Fällen sollte ein Schlüsselrotationszeitraum zwischen 90 Tagen und 6 Monaten ausreichen. Mit einem robusten Schlüsselverwaltungssystem können Sie diese Prozesse optimieren und die Effizienz der Schlüsselrotation und des Ablaufdatums verbessern.
Allgemeine Best Practices
- SSL/HTTPS verwenden: Verschlüsseln Sie Ihre API-Anfragen immer mit HTTPS-Kommunikation.
- Zertifikats-Pinning: Für zusätzlichen Schutz können Sie Zertifikats-Pinning implementieren, um zu prüfen, welche Zertifikate als gültig gelten.
- Nutzereingaben validieren und bereinigen: Validieren und bereinigen Sie Nutzereingaben, um Injection-Angriffe zu verhindern, die API-Schlüssel offenlegen könnten.
- Best Practices für die Sicherheit einhalten: Implementieren Sie allgemeine Best Practices für die Sicherheit in Ihrem Entwicklungsprozess, einschließlich Techniken für sicheres Codieren, Codeüberprüfungen und Sicherheitslückenscans.
- Bleiben Sie auf dem Laufenden: Informieren Sie sich über die neuesten Sicherheitsbedrohungen und Best Practices für die API-Schlüsselverwaltung.
- Aktuelle SDKs: Achten Sie darauf, dass Ihre SDKs und Bibliotheken auf die neueste Version aktualisiert sind.
Kryptografie
Neben der Datenisolation, der Unterstützung der vollständigen Dateisystemverschlüsselung und sicheren Kommunikationskanälen bietet Android eine Vielzahl von Algorithmen zum Schutz von Daten mithilfe von Kryptografie.
Informieren Sie sich, welche JCA-Sicherheitsanbieter (Java Cryptography Architecture) Ihre Software verwendet. Verwenden Sie die höchste Ebene der vorhandenen Framework-Implementierung, die Ihren Anwendungsfall unterstützen kann. Verwenden Sie gegebenenfalls die von Google bereitgestellten Anbieter in der von Google angegebenen Reihenfolge.
Wenn Sie eine Datei sicher von einem bekannten Netzwerkspeicherort abrufen möchten, reicht möglicherweise eine einfache HTTPS-URI aus. Für diese Methode sind keine Kenntnisse der Kryptografie erforderlich. Wenn Sie einen sicheren Tunnel benötigen, sollten Sie HttpsURLConnection
oder SSLSocket
verwenden, anstatt ein eigenes Protokoll zu schreiben. Wenn Sie SSLSocket
verwenden, wird keine Hostnamenüberprüfung durchgeführt. Weitere Informationen finden Sie unter Warnungen zur direkten Verwendung von SSLSocket
.
Wenn Sie feststellen, dass Sie Ihr eigenes Protokoll implementieren müssen, implementieren Sie keine eigenen kryptografischen Algorithmen. Vorhandene kryptografische Algorithmen verwenden, z. B. die Implementierungen von AES und RSA in der Klasse Cipher
Beachten Sie außerdem die folgenden Best Practices:
- 256-Bit-AES für kommerzielle Zwecke verwenden (Falls nicht verfügbar, verwenden Sie 128-Bit-AES.)
- Verwenden Sie für die elliptische-Kurven-Kryptografie (EC) entweder 224- oder 256-Bit-Öffentliche-Schlüssel-Größen.
- Sie wissen, wann Sie die Blockmodi CBC, CTR oder GCM verwenden sollten.
- Vermeiden Sie die Wiederverwendung von IV/Zählern im CTR-Modus. Sie müssen kryptografisch zufällig sein.
- Wenn Sie die Verschlüsselung verwenden, implementieren Sie die Integrität mit dem CBC- oder CTR-Modus und einer der folgenden Funktionen:
- HMAC-SHA1
- HMAC-SHA-256
- HMAC-SHA-512
- GCM-Modus
Verwenden Sie einen sicheren Zufallszahlengenerator, SecureRandom
, um alle kryptografischen Schlüssel zu initialisieren, die von KeyGenerator
generiert wurden. Die Verwendung eines Schlüssels, der nicht mit einem sicheren Zufallszahlengenerator generiert wurde, verringert die Stärke des Algorithmus erheblich und kann Offlineangriffe ermöglichen.
Wenn Sie einen Schlüssel für die wiederholte Verwendung speichern möchten, verwenden Sie einen Mechanismus wie KeyStore
, der den langfristigen Speicher und Abruf kryptografischer Schlüssel ermöglicht.
Interprocess Communication
Einige Apps versuchen, IPC mit traditionellen Linux-Techniken wie Netzwerk-Sockets und freigegebenen Dateien zu implementieren. Wir empfehlen jedoch, stattdessen Android-Systemfunktionen für die interprozedurale Kommunikation zu verwenden, z. B. Intent
, Binder
oder Messenger
mit Service
und BroadcastReceiver
. Mit den Android-IPC-Mechanismen können Sie die Identität der Anwendung prüfen, die eine Verbindung zu Ihrem IPC herstellt, und Sicherheitsrichtlinien für jeden IPC-Mechanismus festlegen.
Viele der Sicherheitselemente werden für alle IPC-Mechanismen verwendet. Wenn Ihr IPC-Mechanismus nicht für die Verwendung durch andere Anwendungen vorgesehen ist, legen Sie im Manifest-Element der Komponente das android:exported
-Attribut auf false
fest, z. B. für das Element <service>
. Das ist nützlich für Anwendungen, die aus mehreren Prozessen innerhalb derselben UID bestehen, oder wenn Sie sich spät in der Entwicklung entscheiden, dass Sie die Funktionen nicht als IPC freigeben möchten, den Code aber nicht neu schreiben möchten.
Wenn andere Anwendungen auf Ihren IPC zugreifen können, können Sie mit dem Element <permission>
eine Sicherheitsrichtlinie anwenden. Wenn die IPC zwischen Ihren eigenen Apps erfolgt, die mit demselben Schlüssel signiert sind, verwenden Sie in android:protectionLevel
die Berechtigung signature-level
.
Intents
Für Aktivitäten und Broadcastempfänger sind Intents der bevorzugte Mechanismus für asynchrone IPC auf Android. Je nach Anwendungsanforderungen können Sie sendBroadcast
, sendOrderedBroadcast
oder eine explizite Absicht für eine bestimmte Anwendungskomponente verwenden. Aus Sicherheitsgründen werden explizite Absichten bevorzugt.
Achtung: Wenn Sie eine Intent verwenden, um eine Bindung an eine **Service**
herzustellen, sollten Sie eine explizite Intent verwenden, um Ihre App zu schützen. Die Verwendung einer impliziten Intent zum Starten eines Dienstes stellt ein Sicherheitsrisiko dar, da Sie nicht sicher sein können, welcher Dienst auf die Intent reagiert, und der Nutzer nicht sehen kann, welcher Dienst gestartet wird. Ab Android 5.0 (API-Level 21) wirft das System eine Ausnahme, wenn Sie **bindService()**
mit einer impliziten Intent aufrufen.
Beachte, dass geordnete Übertragungen von einem Empfänger konsumiert werden können und daher möglicherweise nicht an alle Anwendungen gesendet werden. Wenn Sie eine Absicht senden, die an einen bestimmten Empfänger gesendet werden muss, müssen Sie eine explizite Absicht verwenden, in der der Empfänger namentlich angegeben ist.
Absender eines Intents können prüfen, ob der Empfänger eine Berechtigung hat, indem sie beim Methodenaufruf eine nicht nullwertige Berechtigung angeben. Nur Apps mit dieser Berechtigung erhalten die Intent-Nachricht. Wenn Daten in einer Broadcast-Intent sensibel sein könnten, sollten Sie eine Berechtigung anwenden, damit sich schädliche Apps nicht ohne die entsprechenden Berechtigungen für den Empfang dieser Nachrichten registrieren können. In diesen Fällen können Sie auch den Empfänger direkt aufrufen, anstatt eine Übertragung zu starten.
Hinweis: Intent-Filter sind keine Sicherheitsfunktionen. Komponenten können mit expliziten Intents aufgerufen werden und enthalten möglicherweise keine Daten, die dem Intent-Filter entsprechen. Führen Sie eine Eingabevalidierung in Ihrem Intent-Empfänger durch, um zu prüfen, ob die Daten für den aufgerufenen Empfänger, Dienst oder die Aktivität richtig formatiert sind.
Dienste
Ein Service
wird häufig verwendet, um Funktionen für andere Anwendungen bereitzustellen. Jede Dienstklasse muss in der Manifestdatei eine entsprechende <service>
-Deklaration haben.
Standardmäßig werden Dienste nicht exportiert und können von keiner anderen Anwendung aufgerufen werden. Wenn Sie der Dienstdeklaration jedoch Intent-Filter hinzufügen, wird sie standardmäßig exportiert. Wir empfehlen, das Attribut android:exported
explizit zu deklarieren, damit es sich wie gewünscht verhält. Dienste können auch mit dem Attribut android:permission
geschützt werden. Andere Anwendungen müssen dann ein entsprechendes <uses-permission>
-Element in ihrem eigenen Manifest deklarieren, um den Dienst starten, beenden oder damit verknüpfen zu können.
Hinweis: Wenn Ihre App auf Android 5.0 (API-Level 21) oder höher ausgerichtet ist, verwenden Sie **JobScheduler**
, um Hintergrunddienste auszuführen.
Ein Dienst kann einzelne IPC-Aufrufe, die an ihn gesendet werden, mit Berechtigungen schützen. Rufen Sie dazu checkCallingPermission()
auf, bevor Sie die Implementierung des Aufrufs ausführen. Wir empfehlen, die deklarativen Berechtigungen im Manifest zu verwenden, da diese weniger anfällig für Fehler sind.
Achtung: Verwechseln Sie nicht Client- und Serverberechtigungen. Achten Sie darauf, dass die aufgerufene App die entsprechenden Berechtigungen hat, und prüfen Sie, ob Sie der aufrufenden App dieselben Berechtigungen gewähren.
Binder- und Messenger-Schnittstellen
Die Verwendung von Binder
oder Messenger
ist der bevorzugte Mechanismus für die RPC-Stil-IPC auf Android. Sie bieten klar definierte Schnittstellen, die bei Bedarf eine gegenseitige Authentifizierung der Endpunkte ermöglichen.
Wir empfehlen, Ihre App-Oberflächen so zu gestalten, dass keine oberflächenspezifischen Berechtigungsprüfungen erforderlich sind. Binder
- und Messenger
-Objekte werden nicht im Anwendungsmanifest deklariert. Daher können deklarative Berechtigungen nicht direkt auf sie angewendet werden. Sie übernehmen in der Regel Berechtigungen, die im Anwendungsmanifest für die Service
oder Activity
deklariert wurden, in der sie implementiert sind. Wenn Sie eine Benutzeroberfläche erstellen, für die Authentifizierung und/oder Zugriffssteuerungen erforderlich sind, müssen Sie diese Steuerelemente explizit als Code in die Binder
- oder Messenger
-Benutzeroberfläche einfügen.
Wenn Sie eine Benutzeroberfläche bereitstellen, für die Zugriffssteuerungen erforderlich sind, prüfen Sie mit checkCallingPermission()
, ob der Aufrufer die erforderliche Berechtigung hat. Dies ist besonders wichtig, bevor Sie im Namen des Aufrufers auf einen Dienst zugreifen, da die Identität Ihrer Anwendung an andere Schnittstellen übergeben wird.
Wenn Sie eine von einem Service
bereitgestellte Schnittstelle aufrufen, kann der bindService()
-Aufruf fehlschlagen, wenn Sie keine Berechtigung zum Zugriff auf den jeweiligen Dienst haben. Wenn Sie einem externen Prozess erlauben möchten, mit Ihrer App zu interagieren, dieser Prozess aber nicht die erforderlichen Berechtigungen dafür hat, können Sie die Methode clearCallingIdentity()
verwenden. Bei dieser Methode wird die Benutzeroberfläche Ihrer App so aufgerufen, als würde die App selbst den Anruf starten, anstatt der externe Anrufer. Sie können die Berechtigungen des Anrufers später mit der Methode restoreCallingIdentity()
wiederherstellen.
Weitere Informationen zum Ausführen von IPC mit einem Dienst finden Sie unter Gebundene Dienste.
Übertragungsempfänger
Ein BroadcastReceiver
verarbeitet asynchrone Anfragen, die von einem Intent
initiiert wurden.
Empfänger werden standardmäßig exportiert und können von jeder anderen Anwendung aufgerufen werden.
Wenn Ihre BroadcastReceiver
für die Verwendung durch andere Anwendungen vorgesehen ist, sollten Sie Sicherheitsberechtigungen für Empfänger mithilfe des Elements <receiver>
im Anwendungsmanifest anwenden. So wird verhindert, dass Apps ohne die entsprechenden Berechtigungen einen Intent an die BroadcastReceiver
senden.
Sicherheit durch dynamisch geladenen Code
Wir raten dringend davon ab, Code von außerhalb des APK Ihrer App zu laden. Dadurch steigt die Wahrscheinlichkeit einer Manipulation der Anwendung durch Code-Injection oder Code-Manipulation erheblich. Außerdem erschwert es die Versionsverwaltung und Anwendungstests und kann es unmöglich machen, das Verhalten einer Anwendung zu überprüfen. Daher ist es in einigen Umgebungen möglicherweise nicht zulässig.
Wenn Ihre Anwendung Code dynamisch lädt, ist es wichtig, dass der dynamisch geladene Code mit denselben Sicherheitsberechtigungen ausgeführt wird wie das APK der Anwendung. Der Nutzer entscheidet sich aufgrund Ihrer Identität, Ihre App zu installieren, und erwartet, dass Sie allen Code zur Verfügung stellen, der in der App ausgeführt wird, einschließlich Code, der dynamisch geladen wird.
Viele Anwendungen versuchen, Code von unsicheren Orten zu laden, z. B. über unverschlüsselte Protokolle aus dem Netzwerk oder von frei beschreibbaren Orten wie externen Speichern. An diesen Stellen kann jemand im Netzwerk die übertragenen Inhalte ändern oder eine andere App auf dem Gerät eines Nutzers die Inhalte auf dem Gerät ändern. Module, die direkt in Ihrem APK enthalten sind, können hingegen nicht von anderen Anwendungen geändert werden. Das gilt unabhängig davon, ob es sich bei dem Code um eine native Bibliothek oder eine Klasse handelt, die mit DexClassLoader
geladen wird.
Sicherheit in einer virtuellen Maschine
Dalvik ist die Laufzeit-VM (virtuelle Maschine) von Android. Dalvik wurde speziell für Android entwickelt, aber viele der Bedenken hinsichtlich sicheren Codes auf anderen virtuellen Maschinen gelten auch für Android. Im Allgemeinen müssen Sie sich keine Gedanken über Sicherheitsprobleme im Zusammenhang mit der virtuellen Maschine machen. Ihre Anwendung wird in einer sicheren Sandbox-Umgebung ausgeführt, sodass andere Prozesse auf dem System nicht auf Ihren Code oder Ihre privaten Daten zugreifen können.
Wenn Sie mehr über die Sicherheit von virtuellen Maschinen erfahren möchten, sollten Sie sich mit der vorhandenen Literatur zu diesem Thema vertraut machen. Zwei der beliebtesten Ressourcen sind:
In diesem Dokument geht es um Bereiche, die für Android spezifisch sind oder sich von anderen VM-Umgebungen unterscheiden. Für Entwickler mit Erfahrung in der VM-Programmierung in anderen Umgebungen gibt es zwei allgemeine Probleme, die beim Erstellen von Apps für Android anders sein können:
- Einige virtuelle Maschinen, z. B. die JVM oder die .NET-Laufzeit, dienen als Sicherheitsgrenze und isolieren Code von den Funktionen des zugrunde liegenden Betriebssystems. Unter Android ist die Dalvik-VM keine Sicherheitsgrenze. Die Anwendungs-Sandbox wird auf Betriebssystemebene implementiert, sodass Dalvik ohne Sicherheitseinschränkungen mit nativem Code in derselben Anwendung interagieren kann.
- Aufgrund des begrenzten Speicherplatzes auf Mobilgeräten möchten Entwickler häufig modulare Anwendungen entwickeln und dynamisches Klassenladen verwenden. Berücksichtigen Sie dabei sowohl die Quelle, aus der Sie die Anwendungslogik abrufen, als auch den Speicherort, an dem Sie sie lokal speichern. Verwenden Sie kein dynamisches Laden von Klassen aus nicht überprüften Quellen wie ungesicherten Netzwerkquellen oder externen Speichern, da dieser Code möglicherweise so geändert wird, dass er schädliches Verhalten aufweist.
Sicherheit in nativem Code
Im Allgemeinen empfehlen wir, für die Anwendungsentwicklung das Android SDK zu verwenden, anstatt nativen Code mit dem Android NDK zu verwenden. Anwendungen, die mit nativem Code erstellt wurden, sind komplexer, weniger portabel und enthalten mit größerer Wahrscheinlichkeit häufige Fehler bei der Beschädigung des Arbeitsspeichers, z. B. Pufferüberläufe.
Android wird mit dem Linux-Kernel erstellt. Wenn Sie mit den Best Practices für die Sicherheit der Linux-Entwicklung vertraut sind, ist das besonders nützlich, wenn Sie nativen Code verwenden. Die Sicherheitspraktiken von Linux fallen nicht in den Geltungsbereich dieses Dokuments. Eine der beliebtesten Ressourcen ist Secure Programming HOWTO – Creating Secure Software.
Ein wichtiger Unterschied zwischen Android und den meisten Linux-Umgebungen ist die Anwendungs-Sandbox. Unter Android werden alle Anwendungen in der Anwendungs-Sandbox ausgeführt, einschließlich derjenigen, die in nativem Code geschrieben wurden. Entwickler, die mit Linux vertraut sind, können sich das so vorstellen: Jede Anwendung erhält eine eindeutige User Identifier (UID) mit sehr eingeschränkten Berechtigungen. Weitere Informationen finden Sie im Überblick über die Android-Sicherheit. Sie sollten sich mit Anwendungsberechtigungen vertraut machen, auch wenn Sie nativen Code verwenden.