Zoom: Analyse des Datensendeverhaltens der Android-App

1. ReingezoomtZoom Datensendeverhalten

In Zeiten von Covid-19 sind Videokonferenzen unabdingbar. Besonders beliebt dafür ist die Software Zoom. Doch der Dienstleister sorgt derzeit für viele Negativ-Schlagzeilen, die insbesondere bei Datensicherheits- und Datenschutzfachleuten für Aufsehen sorgen.

Gemeinsam mit Martin Tschirsich [CCC-Vorträge] habe ich mir die Zoom-App für die Android-Plattform etwas genauer angesehen. Für die Analyse des Datensendeverhaltens war es notwendig einige Hürden bzw. Sicherheitsmaßnahmen wie TLS-Cert-Pinning zu umgehen. Der vorliegende Beitrag vermittelt also nicht nur einen Eindruck über den Austausch der Daten zwischen Zoom-App und Server, sondern wie aufwendig das Aushebeln von Sicherheitsmaßnahmen sein kann, bevor eine App-Analyse überhaupt möglich ist.

2. Sicherheitsmaßnahmen aushebeln

Die Voraussetzung für die Analyse des Datensendeverhaltens einer App ist die Fähigkeit, den Datenverkehr mitlesen zu können. Bei einer TLS-verschlüsselten Kommunikation setzt man hierbei meist auf den Ansatz des Man-in-the-Middle-Angriffs, bei dem der Netzwerkverkehr vollständig einsehbar oder sogar manipulierbar ist. Hierfür verwendet man bspw. einen Proxy wie mitmproxy, der Burp Suite oder Charles Proxy. Nachdem die Root-CA des Proxys auf dem Android-Gerät ausgerollt ist, kann man den TLS-verschlüsselten Datenverkehr mitlesen. Schwierig wird es erst dann, wenn Apps zusätzlich Certificate-Pinning einsetzen oder eine eigene Implementierung von TLS mitbringen, die nicht auf die Android-nativen Bibliotheken zurückgreifen.

Keine Frage: Im Grunde genommen ist es begrüßenswert, wenn Entwickler Certificate-Pinning in ihre Apps einbauen, aus der Sicht eines Pentesters oder Analyst für den Datenverkehr ist das allerdings eine zusätzliche Hürde, die es zunächst zu überwinden gilt. Je nach Implementierung, Einfallsreichtum oder auch Motivation der Entwickler, »etwas verstecken zu wollen«, ist der Schwierigkeitsgrad, das Certificate-Pinning auszuhebeln, unterschiedlich hoch.

Nachfolgend wird das Vorgehen beschrieben, wie wir es geschafft haben, das Cert-Pinning zu umgehen. Und zwar genau in jener Abfolge, in der wir auf die diversen Probleme gestoßen sind.

2.1 Split-APKs

Bei der Zoom-App musste zunächst die »Problematik« der Android Split-APKs gelöst werden. Hierbei besteht eine App bzw. die APK-Datei aus mehreren Teilen, ein sogenanntes App-Bundle. Im Detail besteht das Zoom-App-Bundle aus drei APK-Dateien:

  • us.zoom.videomeetings-base.apk
  • us.zoom.videomeetings-split_config.arm64_v8a.apk
  • us.zoom.videomeetings-split_config.xxhdpi.apk

Bei App-Bundles werden nur jene Teile einer App an das Gerät übermittelt und installiert, die für das Funktionieren auf der jeweiligen Systemplattform (CPU, Displayauflösung, Sprache etc.) benötigt werden. Kurz: App-Bundles sparen Bandbreite, Platz auf dem Gerät und Entwickler müssen nicht unterschiedliche APKs für jede Systemkonstellation pflegen, die das Android-Universum bietet.

Voraussetzung für das Umgehen des Certificate-Pinnings bei Zoom sind allerdings manuelle Eingriffe in den Quellcode. Nachdem diese Eingriffe erfolgt sind (Beschreibung folgt unter Ziffer 2.2 und 2.3) muss der veränderte Quellcode wieder kompiliert und signiert werden, also ein APK gebaut werden. Aus einem App-Bundle lässt sich allerdings nicht ohne Weiteres eine einzige (modifizierte) APK-Datei bauen, die später auf dem Gerät mittels adb installiert werden kann:

adb install <apk-file>

Zum Bauen einer einzigen Zoom-APK sind grob folgende Schritte notwendig:

  • Alle APK-Dateien des App-Bundles müssen zunächst in ihre ursprüngliche Form dekodiert bzw. überführt werden. Dazu eignet sich bspw. das Tool apktool.
  • Anschließend müssen diverse Dateien bzw. Unterordner aus den »us.zoom.videomeetings-split_*« Ordnern in das Verzeichnis der Basis-App (us.zoom.videomeetings-base) verschoben / kopiert werden. Dazu zählt unter anderem der Ordner /lib aus dem us.zoom.videomeetings-split_config.arm64_v8a-Verzeichnis.
  • Vor dem erneuten Zusammenbauen zu einer einzigen APK-Datei sind zudem Anpassungen an der AndroidManifest.xml notwendig. Unter anderem muss der Parameter »android:isSplitRequired=”true”« entfernt werden.
  • Nachdem die Anpassungen erfolgt sind, wird aus den Dateien und Verzeichnissen im Basis-App-Ordner, mit Hilfe von apktool, wieder eine APK-Datei gebaut – das Signieren danach nicht vergessen.
  • Anschließend kann die App, die sich nach dem Vorgang nun in einer einzigen APK-Datei befindet, auf dem Gerät installiert werden.

Hinweis

Mittlerweile ist es nicht mehr notwendig, die APK-Datei manuell zu bauen. Dank einem Pull-Request für Objection von Martin, lässt sich dieser Vorgang nun automatisieren.

2.2 App-Signatur

Nachdem das App-Bundle in einer (modifizierten) APK-Datei zusammengefasst und mit einer Signatur versehen wurde, ist die Installation auf dem Gerät möglich. Bei einem Test stellten wir allerdings fest, dass die App unmittelbar nach dem Start wieder abstürzt. Die Ursache für dieses Verhalten ist ein Signatur-Check, der mittels MD5-Hash prüft, ob die ursprüngliche Signatur der App unverändert bzw. noch intakt ist. Durch diverse Modifikationen bzw. dem Zusammenfassen der Split-APKs zu einem APK ist dies natürlich nicht mehr der Fall bzw. die selbst ausgestellte Signatur weicht vom Original ab und die Validierung schlägt letztendlich fehl. Ergebnis: Die Zoom-App stürzt ab.

Die Ursache für dieses Verhalten ist die Java-Funktion getCertificateFingerprintMD5 innerhalb der AppUtil.smali-Datei (com.zipow.cmmlib.AppUtil), die einen MD5-Hash der Signatur des Packages mit einem fest hinterlegten Wert in der Library libzLoader.so (split_config.arm64_v8a.apk/lib/arm64-v8a) vergleicht. Letztendlich war es also notwendig, den nativen Code innerhalb der libzLoader.so so zu modifizieren, dass die Signaturprüfung nicht mehr vorgenommen wird.

Dazu wurde die Library libzLoader.so mit Hilfe des Tools Ghidra dekompiliert, analysiert und anschließend via Hex-Editor die Signaturprüfung deaktiviert.

Anbei die Java-Funktion innerhalb com.zipow.cmmlib.AppUtil für das Auslesen des MD5-Fingerprints:

public static String getCertificateFingerprintMD5() {
   Signature[] signatures = ZMUtils.getSignatures(VideoBoxApplication.getNonNullInstance());
   return (signatures == null || signatures.length == 0 || signatures[0] == null) ? "" : StringUtil.safeString(ZMUtils.hexDigest(signatures[0].toByteArray(), MessageDigestAlgorithms.MD5)).toLowerCase();
}

2.3 TLS-Certificate-Pinning

Aufgrund von TLS-Certificate-Pinning war das Mitlesen des Zoom-Datenverkehrs zunächst nicht möglich. Diverse Verbindungen zu den Zoom-Servern waren geschützt und ließen sich nicht ohne weitere Modifikationen einsehen bzw. analysieren. Mit Hilfsmitteln wie Frida und Objection (näher beschrieben im Artikel »TLS-Verifikation und Certificate-Pinning umgehen«) lässt sich das Certificate-Pinning jedoch im Normalfall elegant aushebeln – im Fall von Zoom leider nicht.

Die Java-Funktion isIssuedByKnownRoot (us.zoom.net.AndroidCertVerifyResult) prüfte auf das Vorhandensein von Root-CAs, die für das Certificate-Pinning legitimiert sind. Der Aufruf dieser Funktion erfolgte aus der Library libzWebService.so (split_config.arm64_v8a.apk/lib/arm64-v8a), allerdings so, dass dieser Aufruf im Java-VM-Kontext nicht sichtbar war und von Frida mit den herkömmlichen Methoden nicht abgefangen bzw. dynamisch während der Laufzeit manipuliert werden konnte. Das Problem: Zoom nutzt für diverse Aufrufe das Android NDK, das die Entwicklung und Integration von Code in Sprachen wie C++ oder C ermöglicht. Standardmäßig kann sich Frida nicht in native Funktionen einklinken und damit ist ein Abfangen und Verändern der Methode nicht möglich. Mit der Interceptor-Funktion von Frida hatte ich ebenfalls kein Glück.

Mit einem einfachen Trick ist es dann letztendlich doch gelungen, das Certificate-Pinning auszuhebeln, welches hier wie so oft mittels Public-Key-Pinning umgesetzt ist: In der Zoom-Library libzWebService.so sind die Public-Key-Pins bzw. SHA-256-Hashwerte der vertrauenswürdigen öffentlichen Schlüssel gespeichert. Auf der Kommandozeile lassen sich die eingespeicherten Public-Key-Pins etwa mit folgendem Befehl auslesen:

strings libzWebService.so | grep -Ei ^[a-f0-9]{64}$

Es war dann ein leichtes, diese wiedererkennbaren 64-stelligen Hexadezimalfolgen in einem Hexeditor durch den Public-Key-Pin des eigenen Proxy-Zertifikates zu ersetzen.

3. Analyse Zoom-Datensendeverhalten

Eine tatsächliche Einschätzung über das Sicherheits- und Datenschutzniveau von Apps, Programmen, bzw. proprietärer Software generell, ist erst dann möglich, wenn das Datensendeverhalten analysiert werden kann. Zu diesem Zweck ist und wird es auch in Zukunft notwendig sein, Sicherheitsmaßnahmen wie TLS-Certificate-Pinning und weitere auszuhebeln, um eine Bewertung vornehmen zu können. In Fall von Zoom war einiges an Vorarbeit notwendig, um die nachfolgende Analyse letztendlich vornehmen zu können.

Die nachfolgende Analyse bezieht sich auf die Zoom-App für Android (Version 4.6.20553.0413). Durchgeführt wurde die Analyse bereits Ende Mai – selbstverständlich wird nicht jede Funktion bzw. Einstellung innerhalb der App von der Analyse erfasst. Aktuell liegt bereits Version 5.x von Zoom vor, die allerdings nicht betrachtet wurde.

Hinweis

Zoom verwendet für die Kommunikation nahezu flächendeckend TLS-Certificate-Pinning. Für wenige Verbindungen wie zu »xmppapi.zoom.us« allerdings nicht.

3.1 App-Start: Unmittelbar nach dem Start (keine Interaktion des Nutzers)

[1] Direkt nach dem Start findet zunächst eine Root-Erkennung statt, die sich allerdings einfach über ein Frida-Hook aushebeln lässt – Zoom sendet dabei eine Art »Ping« an den Hersteller. Unter anderem werden folgende Informationen übermittelt [zoom.us]:

  • User-Agent: Mozilla/5.0 (ZOOM.Android 9 x86)
  • App-Versionsnummer: 4.6.20553.0413
POST /ping HTTP/1.1
Host: zoom.us
User-Agent: Mozilla/5.0 (ZOOM.Android 9 x86)
Accept: */*
Cookie: srid=SaaSbeeTestMode00123578;zpk=hbWOkdwEQLzLzhdYgopKSJsxvYR7HDbemS31mBHU4KA%3D.BwcAAAFykpx%2BSAAAqMAkMTQyNGQ1ZTctZTY5MS00YzUzLWE2NzUtODBjMDY4MWIwOTZlAAAAZgAAAAAA%2FwAAAA%3D%3D;
ZM-CAP: 2535958231574926263,28580
ZM-PROP: Android.Zoom
Accept-Language: de-DE
ZM-LOCALE: Def
ZM-CID: 5QAHT428t3OiQzaYjEFztniOZ9vBY%2BHDlbCoH3b47ew%3D
ZM-NSGN:2,FQN1LdkukIJCQ6dkJeEf7+rcil3XkhrMSdone4gzj7E=,1591597629000
Content-Length: 151
Content-Type: multipart/form-data; boundary=------------------------c517cf2658e7ff9d
Connection: close

--------------------------c517cf2658e7ff9d
Content-Disposition: form-data; name="cv"

4.6.20553.0413
--------------------------c517cf2658e7ff9d--

[2] Als nächstes registriert sich die App bei Googles Firebase-Cloud-Messaging-Dienst (FCM), um Push-Nachrichten erhalten zu können [android.clients.google.com]:

POST /c2dm/register3 HTTP/1.1
Authorization: AidLogin 3987101947870341582:3138298696572731638
app: us.zoom.videomeetings
gcm_ver: 201817030
User-Agent: Android-GCM/1.5 (tissot PQ3A.190801.002)
Content-Length: 466
content-type: application/x-www-form-urlencoded
Host: android.clients.google.com
Connection: close
Accept-Encoding: gzip, deflate

X-subtype=849883241272&sender=849883241272&X-app_ver=46013&X-osv=28&X-cliv=fiid-12451000&X-gmsv=201817030&X-appid=fotfiDfqA-k&X-scope=*&X-gmp_app_id=1%3A849883241272%3Aandroid%3Ac8bcfd5684d8fea5&X-Firebase-Client=fire-android%2F+fire-core%2F16.1.0&X-app_ver_name=4.6.20553.0413&app=us.zoom.videomeetings&device=3987101947870341582&app_ver=46013&info=k5tycOgMC4QRQEb1aBJ6XhzSBVA3pRY&gcm_ver=201817030&plat=0&cert=7c92562f03903e0804b18095fa5fcd96e50e9866&target_ver=29

In diesem Datenpaket sind unter anderem folgende Informationen enthalten:

  • App-Versionsnummer: 4.6.20553.0413
  • Package-Name der App: us.zoom.videomeetings
  • FCM- bzw. GCM-Version: 201817030
  • Geräte-ID: 3987101947870341582

3.2 Registrierung eines Kontos

Als Nächstes wird ein neues Konto angelegt. Dies erfordert die Angabe folgender Informationen:

  • Geburtsdatum: 01. Juni 2000
  • E-Mail-Adresse: testmail@test.de
  • Vorname: Hans
  • Nachname: Wurst

Diese Informationen werden (sofern Häkchen bei »Ich bin mit den Service-Bestimmungen einverstanden« gesetzt) an Zoom übermittelt [zoom.us]:

POST /user/c HTTP/1.1
Host: zoom.us
User-Agent: Mozilla/5.0 (ZOOM.Android 9 x86)
Accept: */*
Cookie: srid=SaaSbeeTestMode00123578;zm_aid="";zm_haid="";zpk=cEvuqNuMnJoK0lEBK0kTlzCADLSCeU8RjUbHoxFc9Og%3D.BwcAAAFykqQ%2BqAAAqMAkNzg4NWM0YzgtZTlkZC00ZmQyLWFmYjItNmIxMzYwYzFiYmM5AAAAZgAAAAAA%2FwAAAA%3D%3D;
ZM-CAP: 2535958231574926263,28580
ZM-PROP: Android.Zoom
Accept-Language: de-DE
ZM-LOCALE: Def
ZM-CID: 5QAHT428t3OiQzaYjEFztniOZ9vBY%2BHDlbCoH3b47ew%3D
ZM-NSGN:2,kxo4Icbp06xw2i2FJHBbimQxe47DDUK1U7sYY49WcSI=,1591598137000
Content-Length: 573
Content-Type: multipart/form-data; boundary=------------------------313d2be07e4dfd48
Connection: close

--------------------------313d2be07e4dfd48
Content-Disposition: form-data; name="birthday"

2000-06-01
--------------------------313d2be07e4dfd48
Content-Disposition: form-data; name="cv"

4.6.20553.0413
--------------------------313d2be07e4dfd48
Content-Disposition: form-data; name="email"

testmail@test.de
--------------------------313d2be07e4dfd48
Content-Disposition: form-data; name="firstName"

Hans
--------------------------313d2be07e4dfd48
Content-Disposition: form-data; name="lastName"

Wurst
--------------------------313d2be07e4dfd48--

Im Anschluss erfolgt die Meldung:

Wir schickten eine E-Mail, um das Konto zu prüfen.

Die E-Mail von Zoom (Schalten Sie Ihr Zoom-Konto frei) ist gleich mal im Spam-Ordner gelandet. Anklicken – öffnen. Sie beinhaltet den Aktivierungslink für das eben angelegte Konto. Nach dem Anklicken wird man auf eine Webseite von Zoom geleitet, die die folgende Frage stellt:

Are you signing up on behalf of a school? [No]

Anschließend wird man namentlich begrüßt und soll ein Passwort setzen. Dieses wird nach Bestätigen mit OK über eine TLS-verschlüsselte Verbindung an Zoom übermittelt – es bleibt zu hoffen, dass das Passwort bei Zoom dann mit einem geeigneten Hash-Verfahren gespeichert wird und dort nicht im Klartext liegt [zoom.us]:

POST /set_password HTTP/1.1
Host: zoom.us
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0
Accept: application/json, text/javascript, */*; q=0.01
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: https://zoom.us/activate?
[...]

code=xl6Z5XZHDfTVdvq25Y94HEzyJLV3aqAGPMzRn1tXq1c.BQgAAAFykqRE9QAnjQARd2FyZXpAdHV0YW5vdGEuZGUBAGQAABZfQndRaFgwWFRhVzdvTWtJcElSekxBAAAAAAAAAAA&firstName=Hans&lastName=Wurst&password=meinpasswort&fr=client

Das Absenden der Informationen triggert allerdings auch noch eine Verbindung zu Wootric und einige weitere Tracker [eligibility.wootric.com]:

POST /eligible.json?account_token=NPS-0487a3ac&email=testmail%40test.de&end_user_created_at=1591598824&end_user_last_seen=1591598827514&language%5Bcode%5D=&language%5Baudience_text%5D=&language%5Bproduct_name%5D=&sdk_version=wootric-js-sdk-1.3.0&properties%5Bpricing%5D=Grey&properties%5Bdomain%5D=&properties%5Bage%5D=0&properties%5Bbaa%5D=Red&properties%5Bpaidhostnum%5D=0&properties%5Bzoomroomsnum%5D=0&properties%5Baudio%5D=Red&properties%5Bwebinar%5D=Red&properties%5Blmcapacity%5D=Red&properties%5Bsso%5D=Red&properties%5Bmanagedomain%5D=Red&properties%5Bzoomphone%5D=Red&properties%5Bzoomrooms%5D=Red HTTP/1.1
Host: eligibility.wootric.com
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0
Accept: application/json, text/javascript, */*; q=0.01
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: https://zoom.us/
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Content-Length: 232
Origin: https://zoom.us
Connection: close

location=%7B%22url%22%3A%22https%3A%2F%2Fzoom.us%2Finvite_colleague%3Fcode%3Dxl6Z5XZHDfTVdvq25Y94HEzyJLV3aqAGPMzRn1tXq1c.BQgAAAFykqRE9QAnjQARd2FyZXpAdHV0YW5vdGEuZGUBAGQAABZfQndRaFgwWFRhVzdvTWtJcElSekxBAAAAAAAAAAA%26fr%3Dclient%22%7D

Dem geübten Leser wird auffallen, dass hier die E-Mail-Adresse testmail@test.de an Wootric übermittelt wird – also ein personenbezogenes Datum. In der Datenschutzerklärung zu Zoom finden wir allerdings keinen Hinweis zu Wootric, sondern erst in der Liste der Auftragsdatenverarbeiter. Allerdings bleibt unklar, welche Daten genau an die Auftragsdatenverarbeiter übermittelt werden. Bei Wootric ist lediglich »Kundenbefragungsplattform« mit Standort USA angegeben.

Danach ist die Registrierung im Grunde abgeschlossen und das Meeting über Zoom kann starten. Optional besteht nun noch die Möglichkeit, Freunde und Kollegen einzuladen, indem die E-Mail-Adresse möglicher Kontakte angegeben wird. Diese Liste mit E-Mail-Adressen wird anschließend an Zoom übermittelt:

POST /invite_signup_colleagues?code=xl6Z5XZHDfTVdvq25Y94HEzyJLV3aqAGPMzRn1tXq1c.BQgAAAFykqRE9QAnjQARd2FyZXpAdHV0YW5vdGEuZGUBAGQAABZfQndRaFgwWFRhVzdvTWtJcElSekxBAAAAAAAAAAA&entry=onboarding HTTP/1.1
Host: zoom.us
[...]

emailList=max%40mustermann.de%2Cerika%40musterfrau.de&recaptcha=03AGdBq24iwRNkVt9T_V9xE5RL1Adlxp2Hv-X4U2sJGf7h2U3mKkkYLqihH2E4ONsadSUhxf1nmLqNCRwuUrr45cXIpIAbZzSfW87qPsXlKSa1Xl7wL3nX9mqfWDJaqpIGEsUMqIZJwFbeoOeJEuO-46qtuQdkCEuqRAQxyaQrP_IBpwM6YJLRiyBsAj1mwR8ASxfiKUoHWKWUJ1mlnaBOSWQHxWnygwUiSyox2uv4yQk2Z7sRAkgI5uiSdqAPPPCRQxNLvKpEvp6DAczyD-OUwbwKoBelJ3HWMnhMRT9B2qyLwl5M_T2IWiR4wAUyxO8VC1Mn5Xx3BiCtDUlMo0DUfX8lNg1mwNQpv4SAYkLNoc8P01t3na12290-nyj0-fJfjz2WVJuNe2VryD7RaDbkQmGBKop26Wy8mw

Diesen Vorgang halte ich für fragwürdig, da dem Zoom-Nutzer von den betroffenen Personen (vermutlich) keine Einwilligung vorliegt, die E-Mail-Adressen anzugeben und dadurch an Zoom zu übermitteln.

Unterstütze den Blog mit einem Dauerauftrag!

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 ➡

3.3 App-Nutzung

Nach der Registrierung und Aktivierung des Kontos kann nun mit der Angabe von E-Mail-Adresse und Passwort die Anmeldung an Zoom erfolgen [zoom.us]:

POST /login?stype=100 HTTP/1.1
Host: zoom.us
User-Agent: Mozilla/5.0 (ZOOM.Android 9 x86)
Accept: */*
Cookie: srid=SaaSbeeTestMode00123578;zm_aid="";zm_haid="";zpk=UDPKq%2Bbt96TJLoZKm2dhgVaPLcJiZKgO%2FItz%2BCdjYio%3D.BwcAAAFyktRi4AAAqMAkZjYxOTU1YjUtZGJlMS00YjZlLWIxM2ItM2YyMTFjN2I0MTEwAAAAZAAAAAAA%2FwAAAA%3D%3D;
ZM-CAP: 2535958231574926263,28580
ZM-PROP: Android.Zoom
Accept-Language: de-DE
ZM-LOCALE: Def
ZM-CID: 5QAHT428t3OiQzaYjEFztniOZ9vBY%2BHDlbCoH3b47ew%3D
ZM-NSGN:2,x9ad1WRvO97hqFfBzfHDYi2vaSDjE2ZVG0+nUiFWfxA=,1591601292000
Content-Length: 1110
Content-Type: multipart/form-data; boundary=------------------------dc9a2c603a56ddbb
Connection: close

--------------------------dc9a2c603a56ddbb
Content-Disposition: form-data; name="adc_hash"

0
--------------------------dc9a2c603a56ddbb
Content-Disposition: form-data; name="cdv"

4.6.11 (20553.0413)
--------------------------dc9a2c603a56ddbb
Content-Disposition: form-data; name="cid"

5QAHT428t3OiQzaYjEFztniOZ9vBY+HDlbCoH3b47ew=
--------------------------dc9a2c603a56ddbb
Content-Disposition: form-data; name="customized_type"

2
--------------------------dc9a2c603a56ddbb
Content-Disposition: form-data; name="cv"

4.6.20553.0413
--------------------------dc9a2c603a56ddbb
Content-Disposition: form-data; name="deviceId"

5QAHT428t3OiQzaYjEFztniOZ9vBY+HDlbCoH3b47ew=
--------------------------dc9a2c603a56ddbb
Content-Disposition: form-data; name="email"

test@testmail.de
--------------------------dc9a2c603a56ddbb
Content-Disposition: form-data; name="hash_macaddress"

LaGskiBoyolBej+Cm27WkezyCQrOpNxMpnC5mM3kx5k=
--------------------------dc9a2c603a56ddbb
Content-Disposition: form-data; name="password"

geheimesPasswort
--------------------------dc9a2c603a56ddbb--

Übermittelt werden unter anderem folgende Informationen:

  • App-Versionsnummer: 4.6.20553.0413
  • Eine Device-ID: 5QAHT428t3OiQzaYjEFztniOZ9vBY+HDlbCoH3b47ew=
  • Die E-Mail-Adresse: test@testmail.de
  • Die gehashte MAC-Adresse des Geräts: LaGskiBoyolBej+Cm27WkezyCQrOpNxMpnC5mM3kx5k=
  • Das Anmeldepasswort: geheimesPasswort

Nach der Anmeldung befindet man sich in der Standard-View von Zoom. Im Hintergrund werden einige Informationen übermittelt bzw. zwischen Client und Server ausgetauscht – auch über WebSockets. Nachfolgend werden nicht alle Verbindungen bzw. Mitschnitte dargestellt, sondern lediglich eine Auswahl.

Hinweis: Die Zoom-Standardeinstellungen (unter Einstellungen) wurden nicht angepasst. Alles Default-Werte.

[1] Die Verbindung zum Websocket-Server [zpns.zoom.us] beinhaltet folgende Informationen:

{"appType":"","deviceid":"2a676dabeafcc579-8f:31:73:9a:10:dc","devicetoken":"","dtype":32,"id":"f0d88f7d-eb31-4a40-8182-f5a78a0809b7","mail":"test@testmail.de","platform":"Android 9 x86","resource":"ZoomChat_mobile_7292dba22c3bb","token":"0Z0rqrwMCBbRyPIixRuEukY-uNnSIk5zOw9i8197B0c.DAYAAAFyktRquwACowAAI3VscXJsODA3cWdhcjRuYnpsNGFkZndAeG1wcC56b29tLnVzFlVsUVJMODA3UUdhUjRuYlpMNGFEZndkAAAAAAAAAAAAAAAAABZVSDNZRjBtWFJpS2h3UlNOSlJDUDVnEXdhcmV6QHR1dGFub3RhLmRl","type":"login","user":"ulqrl807qgar4nbzl4adfw@xmpp.zoom.us","version":"4.6.20553.0413","voiptoken":""}
  • Eine Device-ID: 2a676dabeafcc579-8f:31:73:9a:10:dc
  • Die E-Mail-Adresse: test@testmail.de
  • Userkennung: ulqrl807qgar4nbzl4adfw@xmpp.zoom.us
  • App-Versionsnummer: 4.6.20553.0413
  • Ressource: ZoomChat_mobile_7292dba22c3bb

[2] Beim Aufruf der Einstellungen -> Über -> Datenschutz wird der Nutzer (ohne Einwilligung) via Google getrackt, obwohl ein Cookie-Banner dies verhindern sollte:

  • Google Analytics
  • Google Tag Manager
  • Google Fonts
  • Google Apis

Beim Cookie-Banner wird anschließend gewählt Required Cookies / CCPA Opt-Out. Ein weiteres Tracking findet danach nicht statt.

Zusätzlich wird eine Verbindung via Websockets zu Zendesk (Cloud-basierte Kundendienstplattform) geöffnet und folgende Informationen übermittelt [widget-mediator.zopim.com]:

{"__type":"register","accountKey":"33y0EwbfRgktTe7hX8IWVxBObaDOr8XJ","mID":"ybjC6WvkB0OIAR","ua":"Mozilla/5.0 (Linux; Android 9; Mi A1 Build/PQ3A.190801.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/80.0.3987.132 Mobile Safari/537.36","dt":"mobile","theme":"simple","cookie_law":false,"rev":"a2e84ec3fc0a7507e1dcc0cd9c0b4c7c6519e194","source":"web_embeddable","source_ver":"!ERR","country_code":"geo","multisession":true,"gd_compatible":1,"title":"ZOOM PRIVACY POLICY - Zoom","url":"https://zoom.us/privacy?onlycontent=1","ref":""}

[3] Über Einstellungen -> Kontakte -> Telefonkontakte zuordnen lassen sich andere Kontakte finden, die ebenfalls ihre Telefonnummer bei Zoom hinterlegt haben. Der Vorgang macht eine Angabe und Übermittlung der eigenen Telefonnummer notwendig [zoom.us]:

POST /phone/bind_v3 HTTP/1.1
Host: zoom.us
User-Agent: Mozilla/5.0 (ZOOM.Android 9 x86)
Accept: */*
[...]

--------------------------16ce201377bd7bf9
Content-Disposition: form-data; name="countryCode"

49
--------------------------16ce201377bd7bf9
Content-Disposition: form-data; name="cv"

4.6.20553.0413
--------------------------16ce201377bd7bf9
Content-Disposition: form-data; name="deviceId"

2a676dabeafcc579-a0:42:ed:2c:01:dc
--------------------------16ce201377bd7bf9
Content-Disposition: form-data; name="phoneNumber"

+491000000
--------------------------16ce201377bd7bf9--

[4] Bei der Initialisierung eines Meetings wird zunächst der Logserver von Zoom mit Informationen versorgt [logfiles.zoom.us]:

POST /stat/append/TUr8aeRXkO%2BY2grEBjN1vacnTV3giX2ZNlZOFE4sgIw%3D HTTP/1.1
Host: logfiles.zoom.us
User-Agent: Mozilla/5.0 (ZOOM.Android 9 x86)
Accept: */*
Cookie: srid=SaaSbeeTestMode00123578;
ZM-CAP: 2535958231574926263,28580
ZM-PROP: Android.Zoom
ZM-VER-LOGPOLICY:4
XMS-Hash: 3FBTKL5U6R+h8bTQyijI6P0mwg5bD8gJBXXFfFO4vc4=
XMS-Timestamp: 1591604034000
XMS-Ver: 1.0
Content-Type: application/x-www-form-urlencoded;charset=UTF-8
ZM-NSGN:2,wUXiAHF6RRRgoO3HylnuxcResm+/Up7jwFQbZ3rY5Tc=,1591604034000
Content-Length: 1083
Connection: close

{"client_os":"android","client_type":"Zoom Main Client","client_version":"4.6.20553.0413","event":"Switch Tab","event_loc":"Main Tab","event_time":"5/20/2020 8:10:39","sub_event":"To Meetings","user_id":"UlQRL807QGaR4nbZL4aDfw","uuid":"5QAHT428t3OiQzaYjEFztniOZ9vBY+HDlbCoH3b47ew="}
{"PMI_enabled":false,"audio_options":0,"client_os":"android","client_type":"Zoom Main Client","client_version":"4.6.20553.0413","duration":0,"enable_join_before_host":false,"event":"Start Meeting","event_loc":"Meeting Tab","event_time":"6/8/2020 8:13:53","host_video":false,"in_meeting":false,"participant_video":false,"recurring_meeting":true,"require_password":true,"start_time":1591606800000,"sub_event":"Upcoming Meeting","user_id":"UlQRL807QGaR4nbZL4aDfw","uuid":"5QAHT428t3OiQzaYjEFztniOZ9vBY+HDlbCoH3b47ew="}

Die Übertragung beinhaltet also unter anderem folgende Informationen:

  • Client OS: Android
  • Client Version: 4.6.20553.0413
  • Eine User-ID: UlQRL807QGaR4nbZL4aDfw
  • Eine Device-ID: 5QAHT428t3OiQzaYjEFztniOZ9vBY+HDlbCoH3b47ew=
  • Start des Meetings: 5/20/2020 8:10:39
  • Generelle Informationen zum Meeting: Passwort notwendig usw.

Anschließend wird eine weitere bzw. mehrere Verbindungen zu Zoom-Servern geöffnet, um das Meeting zu initialisieren. Dabei werden unter anderem folgende Informationen übermittelt [www3.zoom.us / zoom.us / xmppapi.zoom.us / zpns.zoom.us / zoomva*.zoom.us, zoomca*.zoom.us, zoomgsb*.zoom.us, zoomny*.zoom.us, tunnel*.zoom.us]:

  • Versionsnummer der App: 4.6.20553.0413
  • E-Mail-Adresse: test@testmail.de
  • Passwort für das Meeting: 4u6TME
  • Nutzername: Hans Wurst
  • Eine Device-ID: 5QAHT428t3OiQzaYjEFztniOZ9vBY+HDlbCoH3b47ew=
  • […]

[5] Bei der Nutzung der integrierten Chat-Funktion wird eine Verbindung zur API von Giphy (Animierte GIFs etc.) aufgebaut [api.giphy.com]:

GET /v1/gifs?api_key=68052e8917914fa7a26a37b6bd724d73&ids=ehhuGD0nByYxO,QEIC6GZIEGStO,3oz8xQQP4ahKiyuxHy,3oz8xAFtqoOUUrsh7W,3oEdva9BUHPIs2SkGk,5mCQOcUfywmyI,WyeodYfrqvHCo,l0Ex3vQtX5VX2YtAQ HTTP/1.1
Host: api.giphy.com
User-Agent: Mozilla/5.0 (ZOOM.Android 9 x86)
Accept: */*
ZM-CAP: 2535958231574926263,28580
ZM-PROP: Android.Zoom
ZM-NSGN:2,QVtsUMC1g1r6GxjDmQY+fZavfQzyErdrisqgE+UA3zA=,1591606047000
Connection: close

[6] Ebenfalls integriert ist der Google-Tracker »Google Firebase Analytics«, der den Google-Cloud-Messaging (GCM) Nachfolger Firebase Cloud Messaging (FCM) standardmäßig mit Daten beliefert, sofern die Entwickler dies nicht aktiv deaktivieren [app-measurement.com]:

POST /a HTTP/1.1
Content-Encoding: gzip
Content-Length: 7733
Content-Type: application/x-www-form-urlencoded
User-Agent: Dalvik/2.1.0 (Linux; U; Android 9; Mi A1 Build/PQ3A.190801.002)
Host: app-measurement.com
Connection: close
Accept-Encoding: gzip, deflate

[Verschlüsselt]

Leider können wir die Daten nicht einsehen, da Google eine zusätzliche Verschlüsselung darüber legt.

[7] Über Einstellungen -> Problem melden kann ein Bug, Problem etc. an die Entwickler gemeldet werden. Fun fact: Wenn das Häkchen bei Protokoll senden nicht gesetzt ist, wird gar nichts übermittelt. Eigentlich würde man ja davon ausgehen, dies sei optional. Erst nach dem Setzen des Häkchens wird die Fehlerbeschreibung nebst weiteren Informationen und verschlüsselten Logfiles an Zoom übermittelt [logfiles.zoom.us]:

  • Feedback-ID: feedbackid__20200608-105605298_1_android_
  • Versionsnummer der App: 4.6.20553.0413
  • E-Mail-Adresse: test@testmail.de
  • E-Mail-Adresse des Supports: ZDC.PR@zoom.us
  • Fehlerbeschreibung
  • Verschlüsselte Log-Files

4. Fazit

Ganz sauber ist das Datensendeverhalten von Zoom nicht. Unter anderem wird der Nutzer via Google Firebase Analytics getrackt und die E-Mail-Adresse bei der Registrierung an den Auftragsdatenverarbeiter Wootric übermittelt. Solche Übermittlungen von personenbeziehbaren Daten an diverse Dienstleister (bei Zoom insgesamt 15) sind natürlich nicht unproblematisch. Als Nutzer muss man darauf vertrauen, dass die Dienstleister die übermittelten personenbezogenen Daten nicht für eigene Zwecke verwenden bzw. (in Zukunft) hoffentlich nicht von einem Datenleak betroffen sind.

Insgesamt ist die Datenschutzerklärung relativ umfangreich und gibt Auskunft darüber, welche Daten Zoom erfasst und verarbeitet. Und das sind so einige wie bspw. die Namen, Städte, Gesprächsdauer sowie Einstellungen und eindeutige Geräte-IDs aller Teilnehmer für jedes einzelne Meeting. Kommunikationsinhalte werden laut Angabe von Zoom nicht gespeichert. Leider gibt weder die Datenschutzerklärung noch die Liste der Auftragsdatenverarbeiter Auskunft darüber, welche Daten an die Auftragsverarbeiter übermittelt werden – lediglich der Zweck wird kurz angerissen. Das ist leider nicht sehr transparent.

Ein Datenschutzdesaster ist die Android-App von Zoom nicht, allerdings würde ich den Dienst nicht nutzen wollen. Es gibt etliche Dienste (bspw. Jitsi Meet, BigBlueButton, NextCloud Talk etc.) mit einer besseren Bilanz bei Privatsphäre und Sicherheit.

Bildquellen:

Zoom: xnimrodx from www.flaticon.com is licensed by CC 3.0 BY

Ü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 “Zoom: Analyse des Datensendeverhaltens der Android-App”

  1. Comment Avatar Christian sagt:

    Welche Version des Zoom Clients wurde getestet, 4.6?
    Denn mit einfachen Mittel finde ich kein Firebase mehr (wohl etwa ab Version 5).
    Und die Liste mit Auftragsverarbeitern ist aktueller auf Englisch über https://zoom.us/subprocessors

  2. Comment Avatar Ronald sagt:

    Interessant wären natürlich Aussagen zum analysierten Verhalten der iOS-Zoom-App sowie bei Nutzung von Zomm via Webclient (wenn man z.B. eine Einladung zu einem Zoom-Meeting erhielt und dann via https://zoom.us/join beitritt). Dieses wird ja auch sehr oft genutzt (weil sehr enfach).

  3. Comment Avatar Heiko sagt:

    Früher haben Xposed Module wie JustTrustMe ausgereicht um Pinning in den Bibliotheken , meist OKHTTP zu umgehen.
    Schade dass das so umständlich und manuell geworden ist und die Entwickler wieder ihre eigenenen Pinning Lösungen implementieren so dass man das Paket zerlegen, umbauen und wieder zusammensetzen muss in der Hoffnung dass es hinterher wieder funktioniert.

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.