Android: TLS-Verifikation und Certificate-Pinning umgehen

1. Android austricksenCert-Pinning umgehen

Die Tage, an denen Android-Apps jedes untergeschobene TLS-Zertifikat ohne Widerspruch akzeptiert haben, sind längst gezählt. Heute muss man sich diverser Tricks und Techniken behelfen, um den verschlüsselten App-Datenverkehr abzufangen bzw. zu verändern.

Ab Android-Version 7.x (Nougat) akzeptieren Apps keine Benutzerzertifikate mehr oder setzen zusätzlich Certificate-Pinning ein, um das Aufbrechen von TLS-verschlüsselten Verbindungen zu erschweren. Als Pentester hat man es nicht leicht, eine App davon zu überzeugen, dass ein untergeschobenes Zertifikat gültig und vertrauenswürdig ist.

Im vorliegenden Beitrag möchte ich euch diverse Möglichkeiten vorstellen, mit denen sich die TLS-Zertifikatsprüfung unter Android umgehen lässt.

2. Android: Sicherheitsvorkehrungen unterlaufen

Das Unterschieben eines »vertrauenswürdigen« Zertifikats einer selbst kontrollierten Root-CA reichte bis einschließlich Android 6.x schon aus, um mit Tools wie mitmproxy, der Burp Suite oder Charles Proxy den App-Datenstrom zu analysieren. Und wenn man mal auf Apps stieß, die tatsächlich Certificate-Pinning implementiert hatten, konnte man diese Schutzvorkehrung einfach mit der Xposed-Erweiterung JustTrustMe aushebeln.

Ganz so einfach wie früher lassen sich die androideigenen Sicherheitsvorkehrungen heute nicht mehr unterlaufen – das gilt ebenso für Apps. Ab Android-Version 7.x vertrauen Apps standardmäßig nicht mehr den selbst installieren Benutzerzertifikaten. Den bereits mitgelieferten System-Zertifikaten vertrauen die Apps hingegen auch weiterhin »blind«.

Auch der Einsatz von Certificate-Pinning hat merklich zugenommen. Leider ist die Xposed-Erweiterung JustTrustMe nicht mit neuen Android-Versionen kompatibel.

Als Pentester steht man also vor der Herausforderung, die neuen Sicherheitsvorkehrungen von Android zu umgehen und benötigt weiterhin eine Alternative zu JustTrustMe. Werfen wir also mal einen Blick auf die Voraussetzungen, die notwendig sind, um Android »auszutricksen«.

Du kannst den Blog aktiv unterstützen!

Unabhängig. Kritisch. Informativ. Praxisnah. Verständlich.

Die Arbeit von kuketz-blog.de wird vollständig durch Spenden unserer Leserschaft finanziert. Sei Teil unserer Community und unterstütze unsere Arbeit mit einer Spende.

Mitmachen ➡

2.1 Voraussetzungen

Folgende Punkte sollten erfüllt sein, wenn ihr die TLS-Verifikation und das Certificate-Pinning unter Android 7.x (und höher) umgehen möchtet:

  • Magisk: Mit Magisk ist ein Systemless Root möglich – also die Erlangung von Root-Rechten, ohne die /system-Partition zu verändern. Wir benötigen Magisk insbesondere deshalb, weil es einen Root-Hider (Magisk Hide) mitbringt und vor Apps »verschleiern« kann, dass wir Root-Zugriff haben. Weiterhin bringt Magisk nützliche Module mit, die sich mit den Erweiterungen des Xposed-Frameworks vergleichen lassen. Die aktuelle Magisk-Version könnt ihr aus dem XDA-Forum beziehen.
  • Frida: Frida ist ein mächtiges Tool und basiert auf dem Client-Server-Prinzip. Der Server wird auf dem Smartphone zur Ausführung gebracht und ermöglicht anschließend die Ausführung bzw. »Injection« von JavaScript-Code innerhalb von Apps. Als Client-Umgebung nutze ich für Frida Kali Linux, auf dem auch alle weiteren Tools laufen. Die Installation von Frida ist via pip (Paketverwaltungsprogramm für Python-Pakete) innerhalb einer Minute erledigt.
  • Objection: Mit Objection können wir das Certificate-Pinning von Apps elegant aushebeln. Es handelt sich um eine Erweiterung für Frida, die sich selbst als »Runtime Mobile Exploration Toolkit« beschreibt. Via pip3 ist die Installation von Objection auf Kali Linux ebenfalls denkbar einfach.

Die genannten Tools benötigt ihr, um die TLS-Verifikation und das Certificate-Pinning von Apps zu umgehen. Anschließend steht es euch frei, einen (Intercepting-)Proxy wie bspw. mitmproxy, der Burp Suite oder Charles Proxy zu nutzen, um den App-Datenstrom mitzuschneiden / zu manipulieren.

3. Magisk: Trust User Certs

Wie bereits dargestellt vertrauen Apps ab Android-Version 7.x standardmäßig nicht mehr den selbst installieren Benutzerzertifikaten. Über das networkSecurityConfig-Attribut in der Datei AndroidManifest.xml können Entwickler allerdings Ausnahmen festlegen, welche Benutzerzertifikate akzeptiert werden. Standardmäßig sind dies natürlich keine Benutzerzertifikate, die wir selbst auf unserem Gerät nachinstallieren. Die Folge: Schon den herkömmlichen TLS-verschlüsselten Netzwerkverkehr einer App können wir ab Android Nougat nicht ohne weitere Modifikationen mitlesen bzw. »aufbrechen«.

Hier kommt nun das Magisk-Modul Trust User Certs in Spiel:

This module makes all installed user certificates part of the system certificate store, so that they will automatically be used when building the trust chain. This module makes it unnecessary to add the network_security_config property to an application’s manifest.

Selbst installierte Benutzerzertifikate werden mit dem Modul einfach zu System-Zertifikaten »aufgewertet«, denen Apps standardmäßig ohne murren vertrauen. Nach der Installation dieses Moduls wird der Android-Schutz kurzerhand ausgehebelt und Apps akzeptieren unser selbst ausgestelltes Zertifikat.

Trust User Certificate

Weitere Varianten, um den Schutz zu umgehen:

  • AndroidManifest.xml: Ihr könnt die App ebenfalls dekompilieren und über die  AndroidManifest.xml das networkSecurityConfig-Attribut um euer Benutzerzertifikat (bspw. PortSwigger CA) ergänzen.
  • Systemspeicher: Ein weiterer Ansatz führt über das manuelle Hinzufügen des Benutzerzertifikats zum Systemspeicher. Der Systemspeicher befindet sich unter »/system/etc/security/cacerts« und enthält eine Datei für jedes installierte Root-Zertifikat.

4. Hooking mit Frida & Objection

TLS-verschlüsselte Kommunikation können wir nun bereits mitlesen bzw. am Proxy terminieren. Schwierig wird es erst dann, wenn Apps zusätzlich Certificate-Pinning implementiert haben. Um diese Schutzvorkehrung zu umgehen müssen wir mit Frida und Objection arbeiten.

Zunächst verbinden wir das Gerät via USB mit dem Kali-Linux-System und starten anschließend den Frida-Server:

adb push frida-server-12.1.1-android-arm64 /data/local/tmp
adb shell
cd /data/local/tmp
chmod 755 frida-server-12.1.1-android-arm64 
./frida-server-12.1.1-android-arm64

Anschließend lauscht Frida lokal (127.0.0.1:27042) auf Verbindungen und wir können über unser Kali-Linux mit der Server-Instanz interagieren. Machen wir einen ersten Test, ob das funktioniert und listen via Frida alle Prozesse (Apps) auf, die derzeit auf dem Smartphone aktiv sind:

frida-ps -U
PID    Name
-----  --------------------------------------------------
1984   .dataservices
4445   adbd
529    adsprpcd
23574  android.process.acore
5831   android.process.media
[..]

Perfekt. Der Frida-Server beantwortet unsere Anfrage.

Als nächstes möchten wir nun das Certificate-Pinning einer App gezielt mit der Frida-Erweiterung Objection aushebeln. Beim Start von Objection müsst ihr dazu den Prozess-Namen der App als Parameter übergeben – diesen erfahrt ihr, nachdem die App gestartet wurde, mit dem oben dargestellten Befehl (frida-ps -U). Im Beispiel übergebe ich den PID-Namen von der Fahrdienst-App Uber:

objection --gadget "com.ubercab" explore

Um das Certificate-Pinning nun auszuhebeln, genügt ein Befehl innerhalb der Objection-Konsole:

android sslpinning disable

Vereinfacht ausgedrückt wird Frida nun mit Hilfe von Objection all jene Java-Methoden »filtern«, die App-Entwickler nutzen, um Certificate-Pinning in Apps zu implementieren:

Android TLS-Unpinning

Am Beispiel der Uber-App lässt sich erkennen, dass Objection den OkHttp 3.x-Client detektiert hat, der Entwicklern eine Certificate-Pinning-Klasse (CertificatePinner) bietet. Sobald die darin integrierte Java-Methode zur Überprüfung des Certificate-Pinnings aufgerufen wird, gibt Objection einen entsprechenden Hinweis auf der Konsole aus.

5. Wenn alle Stricke reißen: Reverse-Engineering

Neben den von Android bereitgestellten SSL- / TLS-Bibliotheken (TrustManager, Network Security Configuration) kennt Objection noch den bekannten HTTP-Client OkHttp, der ebenfalls die Möglichkeit für das Certificate-Pinning innerhalb von Apps mitbringt. Entscheiden sich Entwickler allerdings dazu, auf die bekannten Systembibliotheken zu verzichten und die TLS-Zertifikatsvalidierung mit einer Eigenimplementierung durchzuführen, dann stößt die Kombination aus Frida & Objection an ihre Grenzen.

Letztendlich bleibt uns in diesen Fällen nichts anderes übrig, als die App bspw. mit dex2jar zu dekompilieren und die entsprechenden Methoden-Aufrufe zu identifizieren, die für die Zertifikatsvalidierung verantwortlich sind:

d2j-dex2jar app.apk

Sobald ihr den Code identifiziert habt, der für die Zertifikatsvalidierung verantwortlich ist, habt ihr zwei Möglichkeiten:

  • Frida: Ihr baut euch einen Hook mit Frida und »hebelt« den entsprechenden Java-Funktionsaufruf aus bzw. unterdrückt seine Ausführung.
  • Code-Anpassung: Ihr modifiziert den Quelltext und kompiliert die App anschließend erneut.

Grundsätzlich halte ich einen Frida-Hook für die praktikablere Lösung. Dieses auch insbesondere deshalb, weil wir uns mit einer Veränderung und anschließenden Re-Kompilierung einer App schnell in einer rechtlichen Grauzone bewegen, die sich über das Frida-Hook elegant umgehen lässt.

6. Fazit

Mit jeder neuen Android-Version wird es für Pentester etwas schwieriger, die Sicherheitsvorkehrungen zu umgehen. Einerseits sind die gestiegenen Anforderungen zur Umgehung der TLS-Verifikation und Certificate-Pinning zu begrüßen, andererseits macht es uns Pentestern das Leben unnötig schwer. Die Kombination bestehend aus Magisk, Frida und Objection sollte nun aber auch über längere Zeit Bestand haben.

Wie wichtig die (Daten-)Analyse von Apps ist, das zeigen die zahlreichen App-Mitschnitte und Rezensionen auf mobilsicher.de. Wer den Kuketz-Blog nämlich schon länger verfolgt, der weiß: Die meisten (proprietären) Apps aus dem Google Play Store sind mit Trackern und Werbemodulen geradezu »zugepflastert« und versenden gerne mal ungefragt sensible Daten an Dritte.

Über den Autor | Kuketz

Mike Kuketz

In meiner freiberuflichen Tätigkeit als Pentester / Sicherheitsforscher (Kuketz IT-Security) schlüpfe ich in die Rolle eines »Hackers« und suche nach Schwachstellen in IT-Systemen, Webanwendungen und Apps (Android, iOS). Des Weiteren bin ich Lehrbeauftragter für IT-Sicherheit an der Dualen Hochschule Karlsruhe, sensibilisiere Menschen in Workshops und Schulungen für Sicherheit und Datenschutz und bin unter anderem auch als Autor für die Computerzeitschrift c’t tätig.

Der Kuketz-Blog bzw. meine Person ist regelmäßig in den Medien (heise online, Spiegel Online, Süddeutsche Zeitung etc.) präsent.

Mehr Erfahren ➡

SpendeUnterstützen

Die Arbeit von kuketz-blog.de wird zu 100% durch Spenden unserer Leserinnen und Leser finanziert. Werde Teil dieser Community und unterstütze auch du unsere Arbeit mit deiner Spende.

Folge dem Blog

Wenn du über aktuelle Beiträge informiert werden möchtest, hast du verschiedene Möglichkeiten, dem Blog zu folgen:

Bleib aktuell ➡


Diskussion

4 Ergänzungen zu “Android: TLS-Verifikation und Certificate-Pinning umgehen”

  1. Comment Avatar chrikru sagt:

    Danke für diesen hervorragenden Artikel!
    Die Methoden, die für die Traffic-Analyse bis Android 6.x funktionieren, sind mir bekannt gewesen, auch wenn ich sie nie selber ausprobiert habe.
    Da es ab Android 7 so viel schwieriger wird, wusste ich bisher nicht.

    Zufällig stolperte ich erst vor 2 Wochen über einen Beitrag der BlackHat 2018, der ein weiteres Framework – nach XPosed und Frida – vorstellt, um in den Ablauf von Android-Apps einzugreifen: ARTist.
    Dieses hat nach den Folien des Beitrags gleich ein fertiges Modul dabei, dass einen kompletten Mitschnitt des Netzwerktraffics erlaubt, in dem dieser vor/nach der Ver-/Entschlüsselung abgegriffen wird, wenn ich es richtig verstanden habe.

    Vielleicht schaust du dir ARTist mal an, es scheint mir sehr vielversprechend zu sein.

  2. Comment Avatar Ralf sagt:

    Eine Anmerkung zum „Systemspeicher“-Punkt (Zertifikat unter /system/etc/security/cacerts ablegen):
    Das einfach speichern des Zertifikates bringt ab Android 7 (oder früher??) nicht das gewünschte Ergebnis (da das Zertifikat nicht akzeptiert wird).
    Also Zertifikat wie gehabt mit openssl erstellen:

    openssl req -x509 -nodes -days 3650 -newkey rsa:4096 -keyout $filename"-ca.key" -out $filename"-ca-cert.cer"

    dann Diese Ausgabe:

    openssl x509 -in $filename"-ca-cert.cer" && openssl x509 -in $filename"-ca-cert.cer" -text -noout -fingerprint

    in einer Datei speichern. Der Name dieser Datei wird so ermittelt:

    openssl x509 -inform PEM -subject_hash_old -in $filename"-ca-cert.cer" -noout

    (zb c0e60322). Dann noch die Datei-Endung .0anhängen.
    Die fertige Datei dann unter /system/etc/security/cacerts ablegen + Neustarten.

    Getestet mit Android 7.12 und openssl 1.10h

  3. Comment Avatar Robert sagt:

    In Bezug auf das Testen und/oder Pentesten von mobilen Apps sei an dieser Stelle auf den Webservice htbridge hingewiesen. Neben Android-Apps können auch iOS-Apps automatisiert auf eine Vielzahl von sehr verschiedenen Dingen überprüft werden.

    Eine Liste mit ähnlichen Diensten gibt es hier: https://geekflare.com/mobile-app-security-scanner/

HilfeWenn du konkrete Fragen hast oder Hilfe benötigst, sind das offizielle Forum oder der Chat geeignete Anlaufstellen, um dein Anliegen zu diskutieren. Per E-Mail beantworte ich grundsätzlich keine (Support-)Anfragen – dazu fehlt mir einfach die Zeit. Kuketz-Forum

Abschließender Hinweis

Blog-Beiträge erheben nicht den Anspruch auf ständige Aktualität und Richtigkeit wie Lexikoneinträge (z.B. Wikipedia), sondern beziehen sich wie Zeitungsartikel auf den Informationsstand zum Zeitpunkt des Redaktionsschlusses.

Kritik, Anregungen oder Korrekturvorschläge zu den Beiträgen nehme ich gerne per E-Mail entgegen.