Wenn Apps über das Internet kommunizieren, verschlüsseln heute alle seriösen App-Entwickler ihre Daten per SSL (das war nicht immer so). Und das ist sehr sinnvoll, nicht nur um Zuge der NSA-Enthüllungen der letzten Monate. Niemand möchte, dass beispielsweise die eigenen Google-Suchanfragen für jeden im freien WLAN des Cafés nebenan mitlesbar sind. Nicht selten sind diese äußerst privater Natur.
Trotzdem sind viele kleine Details zu beachten, damit SSL sinnvoll und nicht falsch angewandt wird. Und hier spielt SSL Pinning eine wichtige Rolle.
SSL Pinning
Mit SSL Pinning gibt man dem Client (in unserem Fall ist dies die App) fest vor, welches Zertifikat er auf dem Server zu erwarten hat. Findet er ein anderes Zertifikat vor, wird die Verbindung nicht akzeptiert. Ein großer Vorteil bei Entwicklung von Apps ist der Fakt, dass man wieder Kontrolle über den Client bekommt, und nicht nur über den Server. So kann man im Client das auf dem Server zu erwartende Zertifikat fest definieren und damit jedes andere (böse) Zertifikat ausschließen. Bei Webapplikationen ist die Kontrolle des Browsers des Users je nach Kundenstamm deutlich schwerer bis unmöglich.
SSL Pinning bringt nun gleich mehrere Vorteile:
- Man-In-The-Middle-Angriffe sind nicht möglich, da dem Nutzer gar kein falsches Zertifikat untergeschoben werden kann. Es wird im Code, und nicht über eine Auswahl des Users, genau ein gegebenes Zertifikat akzeptiert. Andere Zertifikate werden abgelehnt.
- Probleme mit kompromittierten Root-Zertifikate sind ausgeschlossen (was schon öfter der Fall war, als man annehmen sollte).
- Angreifer können (ihren eigenen) Traffic zwischen der App nicht analysieren, um damit eventuell bisher unbekannte Lücken zu finden oder mit gefälschten Anfragen Exploits zu finden. Mit Tools wie dem mitmproxy sind Analysen dieser Art in Browsern sehr einfach durchzuführen.
SSL Pinning für Android
Für Android Apps ist SSL Pinning recht einfach umzusetzen. Hier eignet sich das exzellente Library Project AndroidPinning von Moxie Marlinspike. Dieser Weg ist vor allem dann interessant, wenn man auf ein von einer CA signiertes Zertifikat angewiesen ist, weil man z.B. ein gemeinsames Zertifikat mit dem Webfrontend teilt. Ohne diesen Constraint wäre es natürlich auch möglich, komplett auf CA-signierte Zertifikate zu verzichten und eigene Zertifikate zu erstellen und die CA Chain damit komplett zu umgehen. Dieser Weg mag sogar der sicherere sein, ist aber nicht immer praktikabel.
Wir clonen zuerst die Library via git:
git clone https://github.com/moxie0/AndroidPinning
und binden das Library Project wie gewohnt in unsere App ein. Hilfe bieten hier auch die Android Developer Docs.
Dann benötigen wir eine Information im Zertifikat, die wir pinnen können. Hier eignet sich die SubjectPublicKeyInfom, die wir wie folgt aus dem entsprechenden Zertifikat extrahieren:
$ tools/pin.py dein-cert.pem Calculating PIN for certificate: O=api.cortex-media.de, OU=Go to https://www.thawte.com/repository/index.html, OU=Thawte SSL123 certificate, OU=Domain Validated, CN=api.cortex-media.de Pin Value: 425c3f8c27c44ab1e0818812cb7115e30140a31b
(oder alternative auch eine .crt Datei, je nachdem was vorliegt.)
Der PIN Value ist die Informationen, die wir in den nachfolgenden Schritten in der Android App hart verdrahten. Im unteren Beispiel nutzen wir die „425c3f8c27c44ab1e08
Wenn für die HTTP Kommunikation via HttpClient gearbeitet wird, kann der Client wie folgt initialisiert werden:
String[] pins = new String[] {"f30012bbc18c231ac1a44b788e410ce754182513"}; HttpClient httpClient = PinningHelper.getPinnedHttpClient(context, pins); HttpResponse response = httpClient.execute(new HttpGet("https://www.google.com/"));
Für die HttpsUrlConnection läuft die Initialisierung nahezu analog ab:
String[] pins = new String[] {"425c3f8c27c44ab1e0818812cb7115e30140a31b"}; URL url = new URL("https://www.google.com"); HttpsURLConnection con = PinningHelper.getPinnedHttpsURLConnection(context, pins, url);
Und das wäre dann auch schon alles: Kein anderes Zertifikat als angegebene wird akzeptiert und die SSL Kommunikation ist ein Stück weit sicherer.