Sichere Softwareentwicklung unter Android

Werbung
BSI-Veröffentlichungen zur Cyber-Sicherheit
EMPFEHLUNG: IT-HERSTELLER
Sichere Softwareentwicklung
unter Android
Smartphones und Tablets gewinnen als tägliche Begleiter zunehmend an Bedeutung.
Gleichermaßen steigen auch die Anforderungen an die IT-Sicherheit dieser Geräte. Natürlich sollte
die Plattform bzw. das Betriebssystem (z. B. Apple iOS oder Google Android) selbst möglichst sicher
konzipiert sein. Ergänzend müssen allerdings die Anwendungen, sogenannte Apps, sorgsam und
unter Beachtung grundsätzlicher Regelungen entwickelt werden. Andernfalls kann selbst eine
sichere Plattform durch Schwachstellen in Anwendungen kompromittiert werden.
Mit Java als Programmiersprache finden Entwickler einen schnellen Einstieg in die Entwicklung von
Apps für das Betriebssystem Android. Allerdings unterscheidet sich das Sicherheitskonzept von
Android und dessen Java-Implementierung (DalvikVM) grundlegend von dem der konventionellen
Java Laufzeitumgebung. So ist die DalvikVM sehr viel enger mit dem Betriebssystem verbunden und
auch native Codeteile sind besser geschützt. Daher ist von App-Entwicklern auch immer ein
hinreichendes Detailwissen zu den sicherheitsrelevanten Spezifika der Android Plattform gefordert.
Dieses Dokument gibt Empfehlungen zur Entwicklung sicherer Anwendungen für das Betriebs­
system Android. Die Empfehlungen richten sich an App-Entwickler, denen die Grundlagen und
Begrifflichkeiten der Android Plattform1 bekannt sind. Die folgenden Aspekte werden behandelt:
1.
Allgemeines und Architektur
2.
Essenzielle Android-Bausteine
3.
Anwendungsebene
4.
Testen, Paketierung und Distribution
Allgemeines und Architektur
Bereits bei der Konzeption der Architektur der Apps ist das Minimalitätsprinzip bzgl. erforderlicher
Rechte und zu verarbeitenden bzw. zu erfassenden Daten zu befolgen. Sämtliche Daten sollten
sicher gespeichert werden. Dabei bieten sich je nach Anwendungsfall eine lokale Datenhaltung oder
eine Speicherung auf zugehörigen Serverkomponenten an. In beiden Fällen sollten die Daten
möglichst kryptografisch geschützt werden.
Es ist zu empfehlen, sämtliche Eingabedaten nicht ungeprüft zu verarbeiten, sondern stets einer
strikten Eingabevalidierung zu unterziehen. Dies gilt u. a. für Daten aus dem Internet,
Nutzereingaben, Aufrufe durch andere Apps, SMS-Inhalte, Bluetooth-Datenpakete, Protokolldaten
usw.
Die Architektur der Software sollte prinzipiell die Installation von Sicherheitspatches ermöglichen.
Zudem ist eine angemessene automatische Speicherung von Informationen zu bestimmten
1
http://developer.android.com/
BSI-CS 014 | Version 1.00 vom 30.07.2012
Seite 1 von 6
BSI-Veröffentlichungen zur Cyber-Sicherheit | Sichere Softwareentwicklung unter Android
Ereignissen ratsam. Auch hier gilt das Minimalitätsprinzip – insbesondere mit Hinblick auf das Aufzeichnen
sensitiver Nutzerdaten in Logdateien sowie Performanzaspekte.
In der Regel verwenden Apps Drittkomponenten in Form von verschiedensten Bibliotheken. Diese sollten
ausschließlich aus vertrauenswürdigen Quellen bezogen und hinsichtlich der geltenden Softwarelizenzen
geprüft werden. Darüber hinaus sollten Wartung, Pflege und Support für diese Bibliotheken sichergestellt
sein. Wie für die eigenen Codeteile der App ist auch für die verwendeten Bibliotheken eine zeitnahe
Aktualisierung vorzunehmen, falls Sicherheitspatches verfügbar sind.
Das Exception Handling sollte lückenlos implementiert sein. Die lokale und möglichst spezifische
Behandlung von Exceptions ist vorzuziehen. Globale Catch-all Klauseln können zusätzlich sämtliche nicht
zuvor aufgefangenen Exceptions verarbeiten.
Weiterhin hat es sich in der Praxis als sinnvoll erwiesen, dass Apps eigenständig untersuchen, ob es
Hinweise auf ein Rooting des benutzten Geräts gibt. Sicherheitskritische Apps sollten in diesem Falle ihre
Funktionsfähigkeit einschränken oder den Dienst verweigern. Eine verlässliche Erkennung gerooteter
Geräte ist allerdings nicht möglich.
Mit Android 2.2 wurde erstmals das Konzept der Device Administration eingeführt, mit der Apps im
Kontext einer Security Policy betrieben werden können. Dieses Konzept ist – bei entsprechendem
Anwendungsfall – zu unterstützen.
Das unter Entwicklern übliche Verfahren der „copy and paste“-Programmierung, bei dem Programmcode
aus externen Quellen wiederverwendet wird, sollte nicht bedenkenlos angewendet werden. Insbesondere
bei größeren Programmteilen sollte eine kritische Prüfung der kopierten Code-Zeilen auf Fehler oder
unerwünschte Funktionen durchgeführt werden.
Essenzielle Android-Bausteine
Permissions
Für Berechtigungen gilt das Minimalitätsprinzip sowohl für die von der App eingeforderten Rechte (usespermissions) als auch für die von der App selbst definierten Rechte (Permissions).
Für selbst definierte Permissions sind einfache Bezeichner und Erläuterungen zu wählen, die den Nutzer
nicht überfordern. Bezeichner und Erläuterungen sollten darüber hinaus auf Mehrsprachigkeit ausgelegt
sein (Localization). Das protectionLevel einer selbst definierten Berechtigung ist sorgfältig festzulegen,
damit keine trügerische Sicherheit resultiert. Wird eine selbst definierte Permission lediglich durch eigene
Apps desselben Entwicklers genutzt, so ist evtl. das protectionLevel “Signature“ ausreichend. In vielen
anderen Fällen ist “Dangerous“ sinnvoll – insbesondere wenn durch diese Permission eine Activity
abgesichert wird, über die z. B. indirekt ein Internetzugriff möglich ist.
Im Einzelfall ist abzuwägen, ob eine Permission für eine Aktion erforderlich ist oder ob alternative
Umsetzungsmöglichkeiten existieren. Beispielsweise kann eine Permission für den Zugriff auf Daten in
einer Datenbank durch eine App exklusiv über eine Activity realisiert werden, welche eine Bestätigung des
Nutzers einholt. Hier werden sonst häufig externe Intents definiert. Dadurch sind weniger Permissions für
eine App erforderlich und die Übersichtlichkeit bzw. Transparenz für den Nutzer wird erhöht.
Intents
Intents stellen das zentrale Element der Inter-Prozess-Kommunikation (IPC) unter Android dar und spielen
daher eine besondere Rolle bzgl. der Sicherheit einer App.
Empfänger von Intents, also Activities, Services und BroadcastReceiver, müssen Vorkehrungen gegen
bösartige oder manipulierte Intents treffen. Insbesondere ist zu beachten, dass die zur Vermittlung von
BSI-CS 014 | Version 1.00 vom 30.07.2012
Seite 2 von 6
BSI-Veröffentlichungen zur Cyber-Sicherheit | Sichere Softwareentwicklung unter Android
Intents verwendeten IntentFilter in Android keine Parametervalidierung durchführen, sondern nur der
Vermittlung auf der Ebene des Betriebssystems dienen. Darüber hinaus werden Intents ohne explizit
gesetzte Kategorien bei passender Aktion durchgelassen, auch wenn der Intent Filter diese Kategorie nicht
enthält.
Die Filterung der Attribute eines Intents sollte deklarativ über das Manifest erfolgen (z. B. Aktion, Kategorie,
Schema). Dies ist einfach umzusetzen und führt zu einer Prüfung auf OS-Ebene. Zudem sollte eine
pragmatische Filterung der Attribute eines Intents implementiert werden. Hierzu gehört eine Prüfung bzgl.
dem Vorhandensein aller erwarteten bzw. Nicht-Vorhandensein von nicht-erwarteten Key-Value-Paaren –
sogenannte Extras – eine Prüfung der URI-Formate sowie der Datentypen der Extra-Werte und der DefaultKategorien. Des weiteren sollte der Absender des Intents geprüft werden. Der Paketname kann allerdings
nur validiert werden, wenn der aufrufende Intent einen Rückgabewert akzeptiert.
Häufig werden durch aufgerufene Komponenten (z. B. Activity) einer App automatisch Intents angestoßen.
Sind diese Komponenten von außen – also durch andere Apps – zugreifbar, so muss besonders darauf
geachtet werden, dass hierdurch keine ungewollten Intents durch die eigene App gesendet werden können.
Ansonsten könnte eine bösartige App das eigene Programm nutzen, um einen Intent zu senden, für welchen
die bösartige App selbst nicht über die erforderlichen Berechtigungen verfügt. In einem solchen Fall bietet
sich statt normalen Intents die Verwendung von PendingIntents an, da bei Letzteren der Callback so
behandelt wird, als käme er vom Absender des (Pending)Intents. Somit gelten für die mit dem Intent
ausgelösten Aktivitäten dieselben Rechte, wie für die aufrufende App. PendingIntents sollten mittels
setComponent() an die jeweilige Komponente gebunden werden.
Activities
Activities bilden die Grundlage für die Benutzeroberfläche einer App. Besitzen sie das Attribut
android:exported=“true“ (default), können sie von anderen Apps mit beliebigen Intents über
entsprechend definierte Parametrierung von action, data, category oder extras gestartet werden. Ist nicht
erwünscht, dass andere Apps eine Activity initiieren können, sollte sie mit dem Attribut
android:exported=“false“ versehen werden.
Am sichersten sind Activities ohne IntentFilter und mit android:exported=“false“, da diese nicht
mittels Context.startActivity(Intent i) aufgerufen werden können. Bei der Kommunikation
zwischen Activities derselben App sollten daher möglichst nur explizite Intents (d. h. mit Angabe der Klasse,
welche die jeweilige Activity implementiert) mittels Intent.setComponent() verwendet werden. Die
dadurch gewonnene Sicherheit führt allerdings zu der Einschränkung, dass diese Activities nicht durch
andere Apps (bzw. Apps anderer Autoren) verwendet werden können. Wenn keine expliziten Intents infrage
kommen, sollten in jedem Fall geeignete Permissions festgelegt werden.
Beim Aufruf von Activities empfiehlt es sich, dass möglichst keine kritischen Daten als Teil der Intents
mitgegeben werden, damit ein Angreifer nicht einen höher priorisierten IntentFilter registriert und diese
Informationen abfängt.
Wenn eine kritische Activity durch ein Intent gestartet wird, sollte ggf. eine Bestätigung durch den Nutzer
eingeholt werden oder eine Absicherung durch Permissions (Attribut android:permission) erfolgen.
Somit können nur Apps mit der jeweiligen Permission diese Activity aufrufen. Dabei können sowohl
vordefinierte Berechtigungstypen genutzt als auch eigene definiert werden.
Sicherheitskritische Apps werden häufig mit einem Lock (z. B. PIN-Eingabe) versehen. In solchen Fällen ist
es wichtig, dass in jeder (von außen zugänglichen) Activity geprüft wird, ob dieser Lock aufgehoben wurde.
Andernfalls sollte zunächst ein automatischer Aufruf der Activity erfolgen, die für das Aufheben des Locks
zuständig ist.
BSI-CS 014 | Version 1.00 vom 30.07.2012
Seite 3 von 6
BSI-Veröffentlichungen zur Cyber-Sicherheit | Sichere Softwareentwicklung unter Android
Broadcasts & Receiver
Broadcasts sind Intents, die nicht für einen Empfänger bestimmt sind, sondern systemweit gelesen werden
können. Für BroadcastReceiver müssen geeignete Permissions definiert werden, damit nicht beliebige Apps
entsprechende Broadcasts versenden können. Zum Senden sicherer Broadcast Intents sollte
broadcastIntent() mit entsprechenden receiverPermissions versehen werden, über die der Empfänger
verfügen muss.
StickyBroadcasts können nicht mit einer Permission versehen werden. Somit ist es möglich, sie von jeder
App zu versenden und auch zu fälschen. StickyBroadcasts gewährleisten zudem nicht die Zustellung, da jede
App mit dem Recht BROADCAST_STICKY beliebige StickyBroadcasts löschen kann. Daher sollte diese Art
von Broadcasts nicht verwendet werden.
Services
Services dienen der Abarbeitung von Aufgaben im Hintergrund, ohne dass diese eine direkte Interaktion
mit dem Benutzer ermöglichen. Services können durch die Validierung der Rechte des Aufrufenden bei
onServiceConnected() mittels des folgenden Aufrufs abgesichert werden:
GetPackageManager().checkPermission(permissionToCheck,
name.getPackageName());
Zur Gewährleistung der Performanz und Stabilität einer App sollte der Service – insbesondere bei
Ressourcen-intensiven Aufgaben – explizit als separater Thread angelegt werden. Andernfalls kann der
Service die App beeinträchtigen und dazu führen, dass diese nicht mehr reagiert.
Content Providers
Bei Android werden Daten üblicherweise in einer SQLite-Datenbank verarbeitet. Der Zugriff auf diese
Datenbank erfolgt nicht direkt aus der Anwendungslogik, sondern über sogenannte Content Provider,
welche den Datenzugriff als Dienst über die darin implementierten Methoden anbieten.
Bei SQLite-basierten Content Providern ist es – analog zu konventionellen Webanwendungen –
erforderlich, geeignete Maßnahmen gegen SQL-Injections zu treffen:
•
Filterung bzw. Validierung von Parametern
•
Verwendung von parametrisierten Queries zur Trennung zwischen SQL-Logik und Daten
•
Deklaration von selection Strings als final
•
Vollständiger Verzicht auf “händische“ Erstellung von SQL-Queries auf String-Ebene
SQL-Statements sollten nicht zur Laufzeit zusammengesetzt werden. Bevorzugt ist die parametrierte
Methode db.query() zu verwenden, da hier die Parameter separat angegeben werden können. SQLKonstrukte, die in diesen Parametern enthalten sind, werden somit als Strings und nicht als SQL-Statement
behandelt. Die Verwendung von executeSQL(...) ist zu vermeiden, da hier die Ausnutzung einer SQLInjection-Schwachstelle am wahrscheinlichsten ist.
Für die Content Provider sollten die jeweiligen Permissions im Manifest angegeben werden, damit diese
durch die Plattform umgesetzt werden und somit der Zugriff beschränkt wird.
Auch wenn eine Komponente nur über Schreibrechte auf eine Datenbank verfügt, so können mittels
sukzessiver Aufrufe mit geschickt gewählten WHERE-Klauseln Rückschlüsse auf die Inhalte einer Datenbank
gezogen werden. Daher sollten Schreibrechte auf einen (SQL-)Provider prinzipiell so eingestuft werden wie
Lese-&Schreibrechte. Sämtliche Zugriffsberechtigungen auf Datenbanken bzw. Content Provider sollten
möglichst restriktiv vergeben werden. Zudem empfiehlt sich, im Content Provider geeignete
Filtermethoden zu implementieren.
BSI-CS 014 | Version 1.00 vom 30.07.2012
Seite 4 von 6
BSI-Veröffentlichungen zur Cyber-Sicherheit | Sichere Softwareentwicklung unter Android
Das dynamische Gewähren und Widerrufen von Zugriffsrechten über den Paketnamen sollte vermieden
werden, d. h. auf folgende Konstrukte ist zu verzichten:
•
android:grantUriPermission=“true“ und darauffolgende <grant-uri-permission> im Manifest
sowie grantUriPermission() im Code
•
Intents mit FLAG_GRANT_READ_URI_PERMISSION, FLAG_GRANT_WRITE_URI_PERMISSION
Anwendungsebene
Umsetzung von Benutzeroberflächen
Prinzipiell sind Benutzeroberflächen – insbesondere Activities – so zu gestalten, dass Nutzer nicht zu
unbeabsichtigten Aktionen oder zu einer unsicheren Konfiguration verleitet werden. Hierzu gehören
insbesondere sichere Default-Parameter und eine sichere Nutzerführung inkl. kontextsensitiver
Hilfselemente.
Über die Eigenschaft inputType der verschiedenen GUI-Elemente sollte die Art der eingegebenen Daten
eingeschränkt werden, um Fehleingaben zu verhindern. Eine anschließende Überprüfung der eingegebenen
Daten ist zu empfehlen (Validierung der Eingabedaten).
Eine App sollte eine gut sichtbare Kontaktmöglichkeit für Sicherheitsvorfälle enthalten, die der Anwender
nutzen kann. Zudem sollten kontextsensitive Hilfeelemente enthalten sein. Insbesondere sollte vor dem
Aufruf kostenpflichtiger Funktionen die explizite Zustimmung des Nutzers gefordert werden.
Gleichermaßen ist die Einwilligung des Nutzers bzgl. Allgemeiner Geschäftsbedingungen (AGB),
Datenschutzbestimmungen und anderen Regelungen einzuholen. Dies hat bevorzugt zum
Installationszeitpunkt bzw. bei der ersten Verwendung zu erfolgen. Darüber hinaus sollte dem Nutzer die
Möglichkeit gegeben werden, seine Zustimmung zu widerrufen (Opt-Out), sodass die App anschließend die
betroffenen Funktionen nicht mehr anbieten.
Kommunikation mit serverseitigen Komponenten
Wie bei Intents und GUI-Eingaben ist auch bei der Kommunikation mit Serverkomponenten eine strikte
Eingabe-Validierung erforderlich.
Prinzipiell sind sämtliche Verbindungen (Internet, SMS, Bluetooth, etc.) als unsicher anzusehen und mit
geeigneten Mechanismen zu schützen. Daher sollte die Kommunikation über das Internet möglichst immer
mittels SSL/HTTPS abgesichert werden. Hierzu kann entweder die entsprechende Java Standardbibliothek
oder der Apache HttpClient verwendet werden. Entsprechende Zertifikate müssen ggf. installiert werden,
sofern deren Wurzel nicht im Zertifikatsspeicher von Android enthalten ist. Dies erfolgt durch das
Hinzufügen als Ressource (vor Android 4) bzw. über eine KeyChain (ab Android 4). Hostnames sollten stets
explizit auf Übereinstimmung mit dem im Zertifikat angegebenen Servernamen geprüft werden, ebenso wie
das SSL-Zertifikat. Auf die Implementierung unsicherer HostVerifier ist zu verzichten.
Apps sollten möglichst auf eigene Server Sockets verzichten, d. h. nicht auf eigenen Ports lauschen und
Verbindungsanfragen annehmen.
Auch serverseitig sollten geeignete Sicherheitsmechanismen umgesetzt werden wie beispielsweise folgende:
•
Gewährleistung der sicheren Kommunikation (z. B. bei REST)
•
Härtung der Serverkomponenten
•
Authentisierung von API-Aufrufen (insbesondere bei kostenpflichtigen Diensten)
•
Monitoring der Servicenutzung hinsichtlich Anomalien (insbesondere bei kostenpflichtigen Diensten)
•
Regelmäßige Sicherheitsanalysen der verwendeten Softwarekomponenten und implementierten Schnittstellen
BSI-CS 014 | Version 1.00 vom 30.07.2012
Seite 5 von 6
BSI-Veröffentlichungen zur Cyber-Sicherheit | Sichere Softwareentwicklung unter Android
Authentisierung, Autorisierung und Session Management
Prinzipiell sollten nur hinreichend sichere Authentisierungsmechanismen verwendet werden. Im Falle von
Passwort-basierter Authentisierung sollten Passwort-Policies vorgegeben und durch die Programmlogik
durchgesetzt werden. Sofern praktikabel sind alternative, Token-basierte Verfahren wie z. B. OAuth zu
verwenden.
Hinsichtlich der Verwendung von Passwörtern und Token gelten die folgenden Grundsätze:
•
Keine Speicherung im Cache, in Logdaten oder in Backup-Dateien
•
Verschlüsselte Speicherung; nicht extern lesbar
•
Keine Verteilung über SMS oder andere offene Kanäle
•
Keine Speicherung im Programmcode, da einfaches Reverse Engineering möglich
Grundsätzlich ist zu prüfen, ob die Speicherung von Passwörtern überhaupt notwendig ist oder ob
Hashwerte ausreichen.
Files & Preferences
Apps sollten ihre Daten nicht auf der SD-Karte speichern, weil sie dort nicht verschlüsselt werden. Soll
trotzdem die SD-Karte als Speichermedium eingesetzt werden, ist zu beachten, dass dort VFAT als
Dateisystem zum Einsatz kommt und somit die Linux-typischen File Permissions nicht greifen. Ab Android
3 kann die Partition /data, die auf der SD-Karte liegt, verschlüsselt werden.
Rechte auf Dateien sind möglichst restriktiv zu vergeben, z. B. bei Methodenaufrufen wie
fos = openFileOutput(“file“, Context.MODE_PRIVATE);
Insbesondere kritische Dateien (z. B. Logfiles) dürfen keinesfalls MODE_WORLD_WRITEABLE deklariert sein.
Verwendet eine App externe Dateien, die beispielsweise von anderen Apps zugreifbar sind oder über das
Internet bezogen werden, so ist stets in der Entwurfs- und Entwicklungsphase der App auszuschließen, dass
eine (von außen erfolgte) Änderung der Dateien zu einer Schwachstelle führt.
Testen, Paketierung und Distribution
Prinzipiell sollte vermieden werden, dass mehrere Apps eines Entwicklers bzw. Distributors mit dem
gleichen Zertifikat signiert werden, um unter derselben UID zu laufen. Der private Schlüssel zum Signieren
der App muss besonders geschützt werden. Andernfalls könnte ein Angreifer z. B. eine App entwickeln, die
auf andere Apps Zugriff hat, weil diese mit dem gleichen Zertifikat signiert wurden.
Damit ein Angreifer nicht ohne größere Aufwände ein Reverse Engineering einer App durchführen kann,
empfiehlt sich eine Code Obfuscation. Hierzu ist im SDK das Tool ProGuard enthalten. Allerdings sei darauf
hingewiesen, dass Code Obfuscation Reverse Engineering lediglich aufwändiger macht, es aber nicht
verhindert.
Vor der Paketierung einer App muss sämtlicher Code aus Entwicklungs- oder Testzweigen entfernt werden.
Apps sollten mittels statischer und ggf. auch dynamischer Codeanalyse auf Schwachstellen hin untersucht
werden. Darüber hinaus sind Schnittstellen ggf. mittels Fuzzing-Methoden zu testen. Tests auf
Anwendungsebene sollten stets sowohl mit den Rechten eines Standardbenutzers als auch mit denen eines
privilegierten Benutzers erfolgen. Auf der Kommunikationsebene empfiehlt sich, eine Analyse hinsichtlich
unbeabsichtigter Datenlecks (z. B. über Metainformationen von Bildern) durchzuführen.
Mit den BSI-Veröffentlichungen publiziert das Bundesamt für Sicherheit in der Informationstechnik (BSI) Dokumente zu aktuellen Themen der
Cyber-Sicherheit. Kommentare und Hinweise können von Lesern an [email protected] gesendet werden.
BSI-CS 014 | Version 1.00 vom 30.07.2012
Seite 6 von 6
Zugehörige Unterlagen
Herunterladen