Seit einiger Zeit wirbt wieder mal ein neuer Messenger namens Bubcon [1] mit einfacher Nutzung bei gleichzeitig sicherer Verschlüsselung [2]. Vor ein paar Tagen wurde der Messenger nun auch in den App-Stores freigeschaltet. Da dieser mittlerweile bei einigen hundert Downloads liegt, ist es an der Zeit sich die Sicherheitskonzepte mal genauer anzuschauen. Ein Blick in die Protokolle liefern ein desaströses Bild. Wer vermeintlich sicher zu kommunizieren sollte wissen, wie es wirklich um den Messenger steht, um nicht am Ende eine böse Überraschung zu erleben.
Für einen groben Überblick über die Struktur der Software reicht ein kleiner Blick in das APK. Dank Tools wie dex2jar [3] und jd-gui [4] ist dies schnell bewerkstelligt. Mit dex2jar lässt sich zunächst aus der APK-Datei eine JAR-Datei extrahieren. Der Decompiler jd-gui kann dann den Source-Code aus der entstandenen JAR-Datei extrahieren.
Bei einem Blick in die verwendeten externen Pakete wird relativ schnell klar, dass es sich bei Bubcon vor allem um ein buntes Interface um einen XMPP-Client (oder auch Jabber-Client) handelt. Der Messenger basiert grundsätzlich auf der freien API Smack [5] mit allen Vor- und Nachteilen eines XMPP-Clients auf mobilen Endgeräten.
Der implementierte Client verbindet sich mit dem Server chat.bubcon.com auf dem XMPP Port 5222. Dahinter verbirgt sich die IP-Adresse 52.58.217.60, welche in der Range 52.32.0.0 - 52.63.255.255 liegt und damit von Amazon Technologies Inc. registriert wurde. Der Chat-Server läuft also auf einer Amazon Web Services (AWS) [6] Infrastruktur. Für einen Messenger, der sich mit „dem Schutz Deiner privaten Daten“ brüstet eine mehr als bedenkliche Wahl.
Auch die zusätzliche API, welche zunächst für die Account-Verwaltung dient, wurden AWS-Systeme gewählt. Neben Funktionen zur Registrierung, Rufnummernbestätigung und Kontaktlistenverwaltung übernimmt dieser Service wohl auch die Verwaltung von Chat-Rooms. Der Source-Code verrät, dass der Zugriff auf diese Services unverschlüsselt per HTTP über die Adresse http://chatapi.bubcon.com:8080/ erfolgt.
Auf der Basis der Informationen aus dem APK kann nun eine Analyse der tatsächlichen Übertragungsprotokolle erfolgen. Bubcon verspricht „keine Kompromisse bei der Sicherheit und dem Schutz Deiner privaten Daten.“ Neben Servern in Deutschland wird eine „End-to-End“ Verschlüsselung versprochen. Außerdem sollen Kontakte für den Anbieter nicht ersichtlich sein. Dies ist eine ganze Reihe von Versprechungen, die nacheinander geprüft werden sollten.
Der Registrierungsprozess läuft in der App wie folgt ab: Man akzeptiert die Datenschutzbedingungen und AGBs ungelesen mit einem Klick auf weiter, gibt seine Handynummer an und erhält eine SMS mit einem PIN-Code für die Anmeldung. Für einen Messenger, der private Daten schützen soll, ist eine feste Bindung an eine Handy-Nummer für die Registrierung schon bedenklich. Vor allem da andere Messenger eine Registrierung ganz ohne Adressinformationen unter einen Nickname erlauben. Schwaches Bild.
Besonders interessant ist die Frage, was nun unter der Haube passiert. Die Kommunikation mit der Chat-API lässt sich wunderbar mit Wireshark [7] verfolgen, da sie vollkommen unverschlüsselt erfolgt. Alternativ funktioniert hier jeder beliebige HTTP-Proxy. Dazu muss man nur die Verbindungen des Smartphone über einen Rechner leiten (z.B. durch entsprechende Adress- oder Routeneinträge im Router). Es offenbart sich ein gruseliges Bild:
POST /api-v1/account/register HTTP/1.1 Content-Type: application/x-www-form-urlencoded Content-Length: 24 Host: chatapi.bubcon.com:8080 Connection: Keep-Alive Accept-Encoding: gzip User-Agent: okhttp/2.7.5 phoneNumber=491712345678
HTTP/1.1 200 OK Content-Type: application/json;charset=UTF-8 Date: Sun, 21 Aug 2016 19:52:15 GMT Server: Apache-Coyote/1.1 Content-Length: 24 Connection: keep-alive {"data":{"status":"OK"}}
Hier wird die Telefonnummer des Nutzers vollkommen unverschlüsselt über das Internet verschickt. Dies macht es zum Kinderspiel z.B. in einem unverschlüsselten WLAN-Hotspot die Registrierung abzugreifen.
Auch bei der Bestätigung der Registrierungsinformationen wird es nicht besser. Auch diese Erfolgt unverschlüsselt wobei der Server in dem Fall ein Passwort übermittelt, welches zukünftig für alle Authentifizierungen verwendet wird. Schafft es jemand diese Informationen zu erlangen, so ist damit eine Authentifizierung gegen die Bubcon-Dienste möglich und der Account kann von einem Angreifer gekapert werden.
POST /api-v1/account/confirm-registration HTTP/1.1 Content-Type: application/x-www-form-urlencoded Content-Length: 39 Host: chatapi.bubcon.com:8080 Connection: Keep-Alive Accept-Encoding: gzip User-Agent: okhttp/2.7.5 regCode=987654&phoneNumber=491712345678
HTTP/1.1 200 OK Content-Type: application/json;charset=UTF-8 Date: Sun, 21 Aug 2016 19:53:21 GMT Server: Apache-Coyote/1.1 transfer-encoding: chunked Connection: keep-alive 28 {"data":{"password":"jgSK8MiJ2U1pkCRL"}} 0
Bestätigt wird der Account mit einer PIN von 6 Ziffern.
Als nächstes erfolgt eine Übertragung der Kontaktdaten aus dem Telefonbuch. Moment, hatte Bubcon nicht versprochen, dass niemand außer mir meine Kontakte lesen kann? Es werden zwar keine Namen und weitere Informationen übertragen, wohl aber alle Telefonnummern:
POST /api-v1/account/contacts HTTP/1.1 Authorization: Basic NDkxNzEyMzQ1Njc4OmpnU0s4TWlKMlUxcGtDUkw= Content-Type: application/x-www-form-urlencoded Content-Length: 21 Host: chatapi.bubcon.com:8080 Connection: Keep-Alive Accept-Encoding: gzip User-Agent: okhttp/2.7.5 contacts=491747110815
HTTP/1.1 200 OK Content-Type: application/json;charset=UTF-8 Date: Sun, 21 Aug 2016 20:24:26 GMT Server: Apache-Coyote/1.1 transfer-encoding: chunked Connection: keep-alive 23 {"data":{"items":["491747110815"]}} 0
Bubcon erzeugt also sehr wohl für jeden einzelnen Nutzer eine Liste aller Kontakte. Bei diesem Konto ist nur ein Kontakt im Telefonbuch vorhanden, daher wird hier auch nur ein Kontakt an Bubcon übertragen. Gleichzeitig offenbart sich hier eine weitere und fatale Sicherheitslücke. Auch hier erfolgt jegliche Übertragung vollkommen unverschlüsselt. Dabei können neben den Kontaktinformationen vor allem die Authentifizierungsdaten aus dem Header „Authorization: Basic NDkxNzEyMzQ1Njc4OmpnU0s4TWlKMlUxcGtDUkw=“ abgegriffen werden. Auch wenn die Informationen etwas kryptisch aussehen mögen, sind sie keineswegs verschlüsselt. Die Basic-Authorization verwendet legiglich ein Base64-Encoding [8], um alle Zeichen im Header sauber übertragen zu können. Dekodiert man die Daten, so erhält man den Benutzernamen und das Passwort:
$ echo "NDkxNzEyMzQ1Njc4OmpnU0s4TWlKMlUxcGtDUkw=" | base64 -d ; echo 491712345678:jgSK8MiJ2U1pkCRL
Schon ohne eine weitere Analyse der Kommunikationsprotokolle ist an dieser Stelle ersichtlich, dass ein Angreifer hier direkt Zugriff auf alle Telefonnummern aus den Kontaktlisten des Nutzers erlangen kann. So viel zum Datenschutz und der versprochenen Sicherheit.
Seit dem NSA-Skandal ist „End-to-End“ oder auf Deutsch auch „Ende-zu-Ende-Verschlüsselung“ zu einem Schlagwort geworden, welches viele Dienstanbieter für sich beanspruchen. Unweigerlich bedeutet eine sichere Ende-zu-Ende-Verschlüsselung, dass Dienstanbieter und auch Geheimdienste es schwer haben, Inhalte per Massenüberwachung zu erfassen. Daher ist ein Blick auf diese Verschlüsselung besonders spannend. Im Gegensatz zu anderen Anbietern verschweigt Bubcon auf der Webseite ja immerhin, auf welchen Algorithmen diese Verschlüsselung umgesetzt wurde. Dazu bietet Bubcon Chats bzw. Gruppen und Untergruppen mit mehreren Personen an. In dem Fall ist die Implementation der Ende-zu-Ende-Verschlüsselung eine besondere Herausforderung, da sich die Personen in einem Chat im Zweifel nicht alle persönlich kennen. Vor allem geeignete Verfahren für den Tausch der Schlüssel sind an der Stelle keineswegs trivial.
Bei Versuchen sich mit einem XMPP-Client mit chat.bubcon.com zu verbinden, stellt man bei der Analyse mit Wireshark fest, dass XMPP mit STARTTLS verwendet wird. Endlich: Der erste Anschein der versprochenen Verschlüsselung.
Ruft man das Zertifikat des Servers ab so sieht man, dass dieses selbst-signiert ist:
$ openssl s_client -connect bubcon.com:5222 -starttls xmpp CONNECTED(00000003) depth=0 C = FR, ST = Paris, L = Paris, O = ProcessOne, OU = IT, CN = ejabberd Community Server Test Certificate, emailAddress = contact@process-one.net verify error:num=18:self signed certificate verify return:1 depth=0 C = FR, ST = Paris, L = Paris, O = ProcessOne, OU = IT, CN = ejabberd Community Server Test Certificate, emailAddress = contact@process-one.net verify return:1 --- Certificate chain 0 s:/C=FR/ST=Paris/L=Paris/O=ProcessOne/OU=IT/CN=ejabberd Community Server Test Certificate/emailAddress=contact@process-one.net i:/C=FR/ST=Paris/L=Paris/O=ProcessOne/OU=IT/CN=ejabberd Community Server Test Certificate/emailAddress=contact@process-one.net --- Server certificate -----BEGIN CERTIFICATE----- MIIELTCCAxWgAwIBAgIJAJKLxkI3FV0AMA0GCSqGSIb3DQEBCwUAMIGsMQswCQYD VQQGEwJGUjEOMAwGA1UECAwFUGFyaXMxDjAMBgNVBAcMBVBhcmlzMRMwEQYDVQQK DApQcm9jZXNzT25lMQswCQYDVQQLDAJJVDEzMDEGA1UEAwwqZWphYmJlcmQgQ29t bXVuaXR5IFNlcnZlciBUZXN0IENlcnRpZmljYXRlMSYwJAYJKoZIhvcNAQkBFhdj b250YWN0QHByb2Nlc3Mtb25lLm5ldDAeFw0xNjAzMjkxMDAzNTBaFw0yNjAyMDUx MDAzNTBaMIGsMQswCQYDVQQGEwJGUjEOMAwGA1UECAwFUGFyaXMxDjAMBgNVBAcM BVBhcmlzMRMwEQYDVQQKDApQcm9jZXNzT25lMQswCQYDVQQLDAJJVDEzMDEGA1UE AwwqZWphYmJlcmQgQ29tbXVuaXR5IFNlcnZlciBUZXN0IENlcnRpZmljYXRlMSYw JAYJKoZIhvcNAQkBFhdjb250YWN0QHByb2Nlc3Mtb25lLm5ldDCCASIwDQYJKoZI hvcNAQEBBQADggEPADCCAQoCggEBAMvFjejCurQFL92vCUpIPAmLG3j+IMcB2j4u HeeuP+htdE5IuzrXhcPcaUPXWsYNbOZX6nPDeQ5WYUJt232lZSqXsyMzJDd6+Zgt gMbDc+S4RWDyLsLR0SCk4qB+udQntx7ET13XHOyB8Srqoo0gPRnSBjd1U3gQbdUF sby2sg5rOG/Jh4a5dnueC0JIxMRrAQH856v2MVCM1Rd9Pe6LPWW6t41DI4WM85kh TzLdkNOzI8Tn+pq52F2oumqBRzsD5fg7SdcLQzMMdQ+XyTlyqhZ6wPeiPoD6U8a9 AK97NhlHzz5UIbakX1dCiGSgGQuF6e55Ekf62xIQZ55xlAzr/s8CAwEAAaNQME4w HQYDVR0OBBYEFHxqafHb9lFsNN0CFEy5B7EHq/+8MB8GA1UdIwQYMBaAFHxqafHb 9lFsNN0CFEy5B7EHq/+8MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEB AFn4aAg1MsBJuT64Jmox9yfT/1Jmu1GE3smguhpVcwd+Ske8WlaWpwwv3aj8/RFp ipycwh1lkgfyrCZWunwSpWJ2Gu2hl7/b/H50MUuRSQPFuuatCGGqn0mAa0lIhn1H bMlZj+IqUY32ijtD0bXZ3vTAj8ZKMYFHN7y0A3hxGS0YNNCUV00P1YR5+7OImdXa 1wWVgufWSnOfGZb7sjOK+eNqZioYYIUcG3pbuAxDZruZ3HoUqkQmtMcYtZIa0QJG D2k83qCgbly1U/hPwa/0l/VOqRTxRzVscluB2BQZHU96Ovxd5i8NmIeDBgSHEe6B cmSdjPgVbeIrFkCgJDrvAww= -----END CERTIFICATE----- subject=/C=FR/ST=Paris/L=Paris/O=ProcessOne/OU=IT/CN=ejabberd Community Server Test Certificate/emailAddress=contact@process-one.net issuer=/C=FR/ST=Paris/L=Paris/O=ProcessOne/OU=IT/CN=ejabberd Community Server Test Certificate/emailAddress=contact@process-one.net --- No client certificate CA names sent Peer signing digest: SHA512 Server Temp Key: ECDH, P-256, 256 bits --- SSL handshake has read 2249 bytes and written 597 bytes --- New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES256-GCM-SHA384 Server public key is 2048 bit Secure Renegotiation IS supported Compression: NONE Expansion: NONE No ALPN negotiated SSL-Session: Protocol : TLSv1.2 Cipher : ECDHE-RSA-AES256-GCM-SHA384 Session-ID: Session-ID-ctx: Master-Key: C2578ECAA0DD0556F9C6CE66CB3B5B4C3E0F7643CA16A1C4125BEDCF12D2A4CC4FDE6855E865399FAB84162885DEAFF6 Key-Arg : None PSK identity: None PSK identity hint: None SRP username: None Start Time: 1471851235 Timeout : 300 (sec) Verify return code: 18 (self signed certificate)
Es fällt direkt auf, dass in dem Zertifikat vollkommen unsinnige Issuer- und Subject-Informationen eingetragen sind. Offensichtlich hat sich niemand die Mühe gemacht auch nur ein sinnvolles Zertifikat zu erstellen. Weiterhin ist das Zertifikat eben „selbst-signiert“, also nicht von einer „echten Zertifizierungsstelle“ ausgestellt, was für Unternehmen eher unüblich ist. Ein selbst-signiertes Zertifikat ist natürlich kein Problem, wenn im Client eine geeinete Prüfung stattfindet. Leider wird aus dem Source-Code bzw. dem Applikations-Archiv relativ schnell ersichtlich, dass dort gar keine Zertifikate hinterlegt sind, gegen die geprüft werden könnte. Ein paar Zeilen Quellcode für einen XMPP-Proxy mit TLS-Support [9] später und die nächste Katastrophe rauscht durch die Konsole. Der Client prüft die für die Verschlüsselung genutzten SSL-Zertifikate tatsächlich überhaupt nicht auf deren Gültigkeit. Damit lassen sich Verbindungen von einem Angreifer unbemerkt umleiten und alle übertragenen Inhalte mitlesen. Auch hier erfolgt die Anmeldung wieder per Plaintext-Authentifizierung. Damit lassen sich auch hier wieder Benutzername und Passwort mitlesen.
<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='PLAIN'>ADQ5MTcxMjM0NTY3OABqZ1NLOE1pSjJVMXBrQ1JM</auth>
Password und Benutzername für die SASL-Authentifizierung liegen auch hier wieder im Base64-Encoding vor, ähnlich der HTTP-Authentifizierung. Der Unterschied ist, dass SASL statt dem Doppelpunkt NULL als Trennzeichen erwartet. Passwort und Benutzername sind identisch der Authentifizierung gegen chatapi.bubcon.com.
$ echo "ADQ5MTcxMjM0NTY3OABqZ1NLOE1pSjJVMXBrQ1JM" | base64 -d ; echo 491712345678jgSK8MiJ2U1pkCRL
Da nun der Datenstrom mitgelesen werden kann, wird es Zeit sich dem größten Verprechen zu widmen: Die Ende-zu-Ende Verschlüsselung...
<message to='491747110815@bubcon.com' id='...' type='chat'><body>Ich benutze jetzt Bubcon. Und weil Bubcon eine End-to-End Verschlüsselung nutzt, kann diesen Text hier niemand lesen. Damit fühle ich mich jetzt endlich sicher!</body><thread>12345678-9101-abcd-1234-987687657654</thread><request xmlns='urn:xmpp:receipts'/></message>
*badumtzzz* ... existiert überhaupt nicht.
Alle Nachrichten werden zwar mit einer sogenannten Transportverschlüsselung abgesichert, die jedoch vollkommen unbrauchbar ist, da sie sich mit einem einfachen XMPP-Proxy umgehen lässt. Dadurch ist es einem Angreifer jederzeit möglich alle Nachrichten abzufangen, mitzulesen und beliebig zu modifizieren. Außerdem ist es möglich die Login-Informationen abzugreifen. Im Gegensatz zu einer Ende-zu-Ende-Verschlüsselung werden die Nachrichten auf dem Server unverschlüsselt weiterverarbeitet und können dort von den Server-Betreibern ausgelesen werden. Da es sich um AWS-Systeme handelt hat neben den Entwicklern und Betreibern bei Bubcon theoretisch auch der Serverbetreiber, also Amazon, vollen Zugriff auf übermittelte Informationen.
Bubcon hatte das Ziel einen Messenger anzubieten, der sicher und gleichzeitig leicht bedienbar ist. Dabei fehlen dort offensichtlich alleine grundlegende Kenntnisse von Verschlüsselungstechnologien und deren (richtige) Anwendung. Statt eine bonbon-bunte Webseite und eine Reihe von Youtube-Videos mit falschen Werbeversprechungen und offensichtlichen Lügen hochzuziehen, hätten die Entwickler in Know-How investieren sollen. Die Software ist eine bittere Enttäuschung und ein weiteres Beispiel für das klägliche Versagen von falsch verstandenem Idealismus. Am meisten schmerzt, dass Apps wie Bubcon dazu führen, dass Nutzer immer weiter das Vertrauen in vorhandene und sichere Verschlüsselungsverfahren verlieren.
Letztlich ist Bubcon nichts anderes als ein zusammengebasteltes XMPP-Client-Server-Konstrukt und in Sachen Verschlüsselung nichtmal ein gutes. Daher kann man statt Bubcon auch einfach einen XMPP-Client seiner Wahl mit OTR, GPG oder sonst einer etablierten Ende-zu-Ende-Verschlüsselung nutzen. In Sachen Sicherheit und Privatsphäre fährt man damit sicherlich besser.
In den oben gelisteten Verbindungsprotokollen bzw. Ausschnitten wurden persönliche Daten wie Telefonnummern und Passwörter durch Platzhalter ersetzt. Die Inhalte der Datenübertragungen stammen aus entsprechenden Übertragungsprotokollen.
Nachdem ich gestern Kontakt mit dem CEO von Bubcon hatte, hat man mir dort zugesagt, die von mir aufgezählten Fehler binnen weniger Stunden zu beheben. Wahrscheinlich haben alle Bubcon-User mittlerweile ein entsprechendes Update bekommen. Da ich dies vielleicht nicht explizit erwähnt habe: Ich halte die Software für nicht reparierbar. Vor allem die fehlende Ende-zu-Ende-Verschlüsselung lässt sich nicht innerhalb weniger Stunden oder Tage nachpflegen. Eine solche Verschlüsselung benötigt eine intensive Planung und Konzeptionierung. Weiterhin müssen alle Schritte von jemandem mit einem genauen Verständnis der Verschlüsselungsverfahren geprüft werden.
Ich halte auch das Konzept der Serverstrukturen für viel zu kompliziert. Wenn man eine entsprechende Verschlüsselung implementieren will, so sollte man vielmehr neue Komponenten um die implementierten Verfahren herum entwickeln. Um Spezialisten, die sich wirklich mit den notwendigen Verfahren auskennen, kommt man dann natürlich nicht herum. Ich kann nur jedem davon abraten aus einer fixen Idee heraus eine Entwicklung für einen Crypto-Messenger zu starten.
Ich bekam grade noch den Hinweis, dass das Server-Zertifikat oben incl. zugehörigem private Key auf Github [10] zu finden ist. War wohl einfacher ein Zertifikat aus dem Internet zu kopieren, als ein neues zu erzeugen. Hat denen eigentlich mal jemand gesagt, dass man dann die Verschlüsselung auch weglassen kann? Ich hätte mir dann wohl den Aufwand mit dem XMPP-Proxy sparen können und einfach das Zertifikat in Wireshark laden können. Sowas ist nichtmal mehr ein Anfängerfehler sondern grobe Fahrlässigkeit. Der Hersteller bring mit Unwissenheit die persönlichen Daten seiner Nutzer in Gefahr.
BubCon hat nach eigenen Angaben die beschriebenen Mängel behoben. Der CCC konnte dies nicht überprüfen.
Autor: | nexus |
Mail: | nexus (at) hannover (.) ccc (.) de |
Twitter: | @Nexus511 |