Sichern der Kommunikation auf Android

Bei all den jüngsten Datenschutzverletzungen ist der Datenschutz zu einem wichtigen Thema geworden. Fast jede App kommuniziert über das Netzwerk. Daher ist es wichtig, die Sicherheit der Benutzerinformationen zu berücksichtigen. In diesem Beitrag erfahren Sie die aktuellen Best Practices zur Sicherung der Kommunikation Ihrer Android-App.

Verwenden Sie HTTPS

Bei der Entwicklung Ihrer App sollten Sie Ihre Netzwerkanforderungen auf die wesentlichen Anforderungen beschränken. Stellen Sie sicher, dass sie über HTTPS statt über HTTP erstellt werden. HTTPS ist ein Protokoll, das den Verkehr so ​​verschlüsselt, dass es nicht leicht von Lauscher abgefangen werden kann. Das Gute an Android ist, dass die Migration so einfach ist wie das Ändern der URL http zu https

URL-URL = neue URL ("https://example.com"); HttpsURLConnection httpsURLConnection = (HttpsURLConnection) url.openConnection (); httpsURLConnection.connect ();

Tatsächlich können Android N und höhere Versionen HTTPS mithilfe der Netzwerksicherheitskonfiguration von Android erzwingen.

Wählen Sie in Android Studio die Option app / res / xml Verzeichnis für Ihr Projekt. Erstellen Sie die xml Verzeichnis, falls es noch nicht existiert. Wählen Sie es aus und klicken Sie auf Datei> Neue Datei. Nennen network_security_config.xml. Das Format für die Datei lautet wie folgt:

   example.com  

Um Android anzuweisen, diese Datei zu verwenden, fügen Sie den Namen der Datei zum Anwendungs-Tag im hinzu AndroidManifest.xml Datei:

Aktualisieren Sie Crypto-Anbieter

Das HTTPS-Protokoll wurde im Laufe der Jahre mehrfach genutzt. Wenn Sicherheitsforscher Sicherheitslücken melden, werden die Fehler häufig korrigiert. Durch das Anwenden der Patches wird sichergestellt, dass die Netzwerkverbindungen Ihrer App die aktuellsten Industriestandardprotokolle verwenden. Die neuesten Versionen der Protokolle enthalten weniger Schwachstellen als die vorherigen. 

Um die Kryptoanbieter zu aktualisieren, müssen Sie die Google Play-Dienste hinzufügen. Fügen Sie in Ihrer Moduldatei von build.gradle die folgende Zeile zum Abschnitt "Abhängigkeiten" hinzu:

Implementierung "com.google.android.gms: play-services-safetynet: 15.0.1"

Die SafetyNet-Services-API bietet viele weitere Funktionen, darunter die Safe Browsing-API, mit der URLs daraufhin überprüft werden, ob sie als bekannte Bedrohung markiert wurden, und eine reCAPTCHA-API, um Ihre App vor Spammern und anderem schädlichem Datenverkehr zu schützen.

Nachdem Sie Gradle synchronisiert haben, können Sie das aufrufen ProviderInstaller's installIfNeededAsync Methode:

public class MainActivity erweitert Activity implementiert ProviderInstaller.ProviderInstallListener @Override protected void onCreate (Bundle savedInstanceState) super.onCreate (savedInstanceState); ProviderInstaller.installIfNeededAsync (this, this); 

Das onProviderInstalled () Die Methode wird aufgerufen, wenn der Anbieter erfolgreich aktualisiert wurde oder bereits auf dem neuesten Stand ist. Andernfalls, onProviderInstallFailed (int errorCode, Intent recoveryIntent) wird genannt. 

Zertifikat und Public Key Pinning

Wenn Sie eine HTTPS-Verbindung zu einem Server herstellen, wird vom Server ein digitales Zertifikat ausgestellt und von Android überprüft, um sicherzustellen, dass die Verbindung sicher ist. Das Zertifikat kann mit einem Zertifikat einer zwischengeschalteten Zertifizierungsstelle unterzeichnet werden. Dieses von der zwischengeschalteten Behörde verwendete Zertifikat kann wiederum von einer anderen zwischengeschalteten Behörde usw. signiert werden. Dies ist vertrauenswürdig, solange das letzte Zertifikat von einer Stammzertifizierungsstelle signiert wird, die bereits vom Android-Betriebssystem als vertrauenswürdig eingestuft wird.

Wenn eines der Zertifikate in der Vertrauenskette nicht gültig ist, ist die Verbindung nicht sicher. Obwohl dies ein gutes System ist, ist es nicht narrensicher. Ein Angreifer kann das Android-Betriebssystem anweisen, benutzerdefinierte Zertifikate zu akzeptieren. Abhörproxys können ein vertrauenswürdiges Zertifikat besitzen. Wenn das Gerät von einem Unternehmen kontrolliert wird, hat das Unternehmen das Gerät möglicherweise so konfiguriert, dass es sein eigenes Zertifikat akzeptiert. Diese Szenarien ermöglichen einen "Mann in der Mitte" -Angriff, wodurch der HTTPS-Verkehr entschlüsselt und gelesen werden kann. 

Das Festlegen von Zertifikaten wird durch die Überprüfung des Serverzertifikats, das gegen eine Kopie des erwarteten Zertifikats übermittelt wird, zur Rettung von Daten durchgeführt. Dadurch wird verhindert, dass Verbindungen hergestellt werden, wenn sich das Zertifikat von dem erwarteten unterscheidet.

Um das Feststecken auf Android N und höher zu implementieren, müssen Sie einen Hash (sogenannte Pins) des Zertifikats in das Zertifikat einfügen network_security_config.xml Datei. Hier ist eine Beispielimplementierung:

   duckduckgo.com  lFL47 + i9MZkLqDTjnbPTx2GZbGmRfvF3GkEh + J + 1F3g = w9MWhhnFZDSPWTFBjaoeGuClsrCs7Z70lG7YNlo8t + s =   

Um die Pins für eine bestimmte Site zu finden, können Sie zu SSL Labs gehen, die Site aufrufen und auf klicken einreichen. Wenn Sie eine App für ein Unternehmen entwickeln, können Sie das Unternehmen danach fragen.

Hinweis: Wenn Sie Geräte unterstützen müssen, auf denen eine ältere Betriebssystemversion als Android N ausgeführt wird, können Sie die TrustKit-Bibliothek verwenden. Auf dieselbe Weise wird die Konfigurationsdatei für die Netzwerksicherheit verwendet.

Desinfektion und Validierung

Bei allen bisherigen Schutzmaßnahmen sollten Ihre Verbindungen ziemlich sicher sein. Vergessen Sie jedoch nicht die regelmäßige Programmvalidierung. Blindes Vertrauen in Daten, die vom Netzwerk empfangen werden, ist nicht sicher. Eine gute Programmierpraxis ist "Design by Contract", bei der die Inputs und Outputs Ihrer Methoden einen Vertrag erfüllen, der bestimmte Schnittstellenerwartungen definiert. 

Wenn Ihr Server beispielsweise eine Zeichenfolge von 48 Zeichen oder weniger erwartet, stellen Sie sicher, dass die Schnittstelle nur bis zu 48 Zeichen zurückgibt.

if (editText.getText (). toString (). length () <= 48)  ; //return something…  else  ; //return default or error 

Wenn Sie nur Zahlen vom Server erwarten, sollten Ihre Eingaben dies überprüfen. Dies hilft zwar, unschuldige Fehler zu vermeiden, verringert jedoch auch die Wahrscheinlichkeit von Angriffen durch Injektion und Speicherbeschädigung. Dies gilt insbesondere, wenn diese Daten an NDK oder JNI-nativen C- und C ++ - Code übergeben werden.

Gleiches gilt für das Senden von Daten an den Server. Senden Sie keine Daten blind, insbesondere wenn sie vom Benutzer erstellt wurden. Es ist zum Beispiel empfehlenswert, die Länge der Benutzereingaben zu begrenzen, insbesondere wenn sie von einem SQL-Server oder einer anderen Technologie ausgeführt wird, die Code ausführt. 

Obwohl die Sicherung eines Servers gegen Angriffe den Rahmen dieses Artikels sprengen würde, können Sie als mobiler Entwickler Ihren Teil dazu beitragen, indem Sie Zeichen für die Sprache entfernen, die der Server verwendet. Auf diese Weise ist die Eingabe nicht anfällig für Injektionsangriffe. Einige Beispiele sind das Entfernen von Anführungszeichen, Semikola und Schrägstrichen, wenn dies für die Benutzereingaben nicht unbedingt erforderlich ist:

string = string.replace ("\\", "") .replace (";", "") .replace ("\" "," ") .replace (" \ '"," ");

Wenn Sie genau wissen, welches Format erwartet wird, sollten Sie dies überprüfen. Ein gutes Beispiel ist die E-Mail-Validierung:

private final String emailRegexString = "^ [A-Za-z0-9 ._% + \\ -] + @ [A-Za-z0-9. \\ -] + \\. [A-Za-z]  2,4 $ "; private boolean isValidEmailString (String emailString) return emailString! = null && Pattern.compile (emailRegexString) .matcher (emailString) .matches (); 

Dateien können auch geprüft werden. Wenn Sie ein Foto an Ihren Server senden, können Sie prüfen, ob es ein gültiges Foto ist. Die ersten zwei Bytes und die letzten zwei Bytes sind immer FF D8 und FF D9 für das JPEG-Format.

private static boolean isValidJPEGAtPath (String pathString) löst IOException aus RandomAccessFile randomAccessFile = null; try randomAccessFile = new RandomAccessFile (pathString, "r"); long length = randomAccessFile.length (); wenn (Länge < 10L)  return false;  byte[] start = new byte[2]; randomAccessFile.readFully(start); randomAccessFile.seek(length - 2); byte[] end = new byte[2]; randomAccessFile.readFully(end); return start[0] == -1 && start[1] == -40 && end[0] == -1 && end[1] == -39;  finally  if (randomAccessFile != null)  randomAccessFile.close();   

Seien Sie vorsichtig, wenn Sie eine Fehlermeldung anzeigen, die direkt eine Nachricht vom Server anzeigt. Fehlermeldungen können privates Debugging oder sicherheitsrelevante Informationen offenlegen. Die Lösung besteht darin, dass der Server einen Fehlercode sendet, den der Client nachsieht, um eine vordefinierte Nachricht anzuzeigen.

Kommunikation mit anderen Apps

Während Sie die Kommunikation zum und vom Gerät schützen, müssen Sie auch den IPC schützen. Es gab Fälle, in denen Entwickler freigegebene Dateien hinterlassen oder Sockets zum Austausch vertraulicher Informationen implementiert haben. Das ist nicht sicher. Es ist besser zu benutzen Absichts. Sie können Daten mit einem senden Absicht indem Sie den Paketnamen wie folgt angeben:

Vorsatz = neuer Vorsatz (); intent.setComponent (neuer Komponentenname ("com.example.app", "com.example.app.The.Activity")); intent.putExtra ("UserInfo", "Beispielstring"); startActivity (Absicht);

Um Daten an mehrere Apps zu senden, sollten Sie erzwingen, dass nur mit Ihrem Signaturschlüssel signierte Apps die Daten erhalten. Ansonsten können die von Ihnen gesendeten Informationen von jeder App gelesen werden, die sich für den Empfang der Sendung registriert. Ebenso kann eine bösartige App eine Sendung an Ihre App senden, wenn Sie sich für den Empfang der Sendung registriert haben. Sie können eine Berechtigung zum Senden und Empfangen von Broadcasts verwenden Unterschrift wird als verwendet Schutzlevel. Sie können eine benutzerdefinierte Berechtigung in der Manifestdatei folgendermaßen definieren:

 

Dann können Sie die Erlaubnis wie folgt erteilen: 

Beide Apps müssen über die Berechtigungen in der Manifestdatei verfügen, damit sie funktioniert. So senden Sie die Sendung:

Vorsatz = neuer Vorsatz (); intent.putExtra ("UserInfo", "Beispielstring"); intent.setAction ("com.example.SOME_NOTIFICATION"); sendBroadcast (intent, "com.example.mypermission");

Alternativ können Sie verwenden setPackage (String) beim Senden einer Sendung, um sie auf eine Reihe von Apps zu beschränken, die dem angegebenen Paket entsprechen. Rahmen android: exportiert zu falsch In der Manifestdatei werden Broadcasts ausgeschlossen, die von außerhalb Ihrer App empfangen werden.

End-to-End-Verschlüsselung

Es ist wichtig, die Grenzen von HTTPS zum Schutz der Netzwerkkommunikation zu kennen. Bei den meisten HTTPS-Implementierungen wird die Verschlüsselung am Server beendet. Ihre Verbindung zum Server eines Unternehmens kann beispielsweise über HTTPS erfolgen. Sobald dieser Datenverkehr den Server erreicht, ist er unverschlüsselt. Sie können dann an andere Server weitergeleitet werden, indem Sie entweder eine andere HTTPS-Sitzung einrichten oder unverschlüsselt senden. Das Unternehmen kann die gesendeten Informationen einsehen, was in den meisten Fällen eine Voraussetzung für den Geschäftsbetrieb ist. Dies bedeutet jedoch auch, dass das Unternehmen die Informationen unverschlüsselt an Dritte weitergeben könnte.

In letzter Zeit gibt es einen Trend mit dem Namen "Ende-zu-Ende-Verschlüsselung", bei dem nur die beiden Endgeräte, die kommunizieren, den Verkehr lesen können. Ein gutes Beispiel ist eine verschlüsselte Chat-App, bei der zwei mobile Geräte über einen Server miteinander kommunizieren. Nur der Sender und der Empfänger können die Nachrichten des anderen Benutzers lesen.

Eine Analogie, die Ihnen hilft, die Ende-zu-Ende-Verschlüsselung zu verstehen, besteht darin, sich vorzustellen, dass jemand Ihnen eine Nachricht senden soll, die nur Sie lesen können. Dazu geben Sie ihnen eine Box mit einem geöffneten Vorhängeschloss (dem öffentlichen Schlüssel), während Sie den Vorhängeschlossschlüssel (privaten Schlüssel) behalten. Der Benutzer schreibt eine Nachricht, legt sie in die Box, sperrt das Vorhängeschloss und sendet es Ihnen zurück. Nur Sie können die Nachricht lesen, da Sie als einziger mit dem Schlüssel das Vorhängeschloss aufschließen können.

Bei der Ende-zu-Ende-Verschlüsselung senden sich beide Benutzer ihre Schlüssel. Der Server stellt nur einen Dienst für die Kommunikation bereit, kann jedoch den Inhalt der Kommunikation nicht lesen. Obwohl die Implementierungsdetails den Rahmen dieses Artikels sprengen, handelt es sich um eine leistungsstarke Technologie. Wenn Sie mehr über diesen Ansatz erfahren möchten, ist der GitHub-Repo für das Open-Source-Projekt Signal ein guter Ausgangspunkt.

Fazit

Mit all den neuen Datenschutzgesetzen wie der DSGVO wird Sicherheit immer wichtiger. Dies ist oft ein vernachlässigter Aspekt der Entwicklung mobiler Apps.

In diesem Lernprogramm haben Sie die bewährten Sicherheitsmethoden beschrieben, einschließlich der Verwendung von HTTPS, dem Festlegen von Zertifikaten, der Datenbereinigung und der End-to-End-Verschlüsselung. Diese Best Practices sollten als Grundlage für die Sicherheit bei der Entwicklung Ihrer mobilen App dienen. Wenn Sie Fragen haben, können Sie sie gerne weiter unten anzeigen. Wenn Sie hier sind, lesen Sie einige meiner anderen Tutorials zur Sicherheit von Android-Apps!