Über unsMediaKontaktImpressum
Dr. Michael Spreitzenbarth 04. Juli 2017

Friendly Mobile Hacking – Warum ist dies gerade im Firmenumfeld wichtig?

Der Marktanteil von Smartphones und Tablets wächst signifikant im Gegensatz zu herkömmlichen PCs und ist im digitalen Zeitalter für Unternehmen nicht mehr wegzudenken. Auf dem Weg zur Arbeit fix die E-Mails checken, interne News kommunizieren, Echtzeiterfassung von Kundendaten sowie den Zugriff auf Firmenressourcen. Und das alles wo, wann und wie es der Nutzer gerne möchte.

Diese umfangreichen Funktionalitäten sind auch der Grund dafür, dass heutzutage 11 Exabytes Internet-Traffic pro Monat nur durch mobile Endgeräte erzeugt werden [1]. Auch die durchschnittliche tägliche Nutzungsdauer des Internets nach Endgeräten beweist, dass schon seit 2015 das mobile Endgerät das Mittel der Wahl ist, wenn es um Internetzugriff geht – Tendenz steigend [2]. Dies bereitet jedoch nicht nur neue Möglichkeiten für jeden Einzelnen und auch viele Firmen, sondern birgt auch ein hohes Maß an Gefahren und Risiken.

Möchte ein Unternehmen Apps für mobile Plattformen wie Android und iOS einsetzen um firmenrelevante Dokumente zu verarbeiten, oder einfach nur die Verwendung dieser Plattformen im Alltag des Mitarbeiters fördern, so haben die Unternehmen bei der Betrachtung und Auswahl der Apps eigentlich nur zwei Möglichkeiten:

  1. Den Werbeversprechungen des Herstellers der App vertrauen, oder
  2. eigenständiges Überprüfen der versprochenen Leistungen einer App – den sogenannten Pentest

Im Rahmen dieses Artikels möchte ich aufzeigen, wieso die erste Option keine gute Idee ist, wenn das Unternehmen plant, sensible Daten mit diesen Apps und Geräten zu verarbeiten.

Risiken

Beginnen möchte ich mit einem kurzen Einblick in die Risiken, die eine immer stärker wachsende mobile Kommunikationswelt in sich birgt. Speziell wenn es dabei um eine der unzähligen mobilen Applikationen (kurz Apps) geht und man diese für die Verarbeitung von sensiblen Daten nutzen möchte.

Apps und deren Sicherheit

Gerade installierte Applikationen bergen ein gewisses Sicherheitsrisiko für die auf dem Gerät befindlichen Daten und Zugriffsberechtigungen, sowohl unter Android als auch unter iOS. Abgesehen von Ransomware und anderen bösartigen Applikationen, welche vornehmlich unter Android bekannt sind, gibt es weitere Aspekte, die bei der Sicherheit von Applikationen berücksichtigt werden müssen. Hierbei ist vor allem interessant, wie die Applikation ihre Daten auf dem Gerät ablegt:

  • Sind die Daten (Zugangsdaten sowie Dokumente) verschlüsselt oder wird beispielsweise ein Passwort im Klartext abgelegt, dass so von einem Angreifer ohne erheblichen Aufwand ausgelesen werden kann?
  • Werden die Daten wie von den internen Firmenrichtlinien gefordert behandelt (Zugangsschutz, 2FA, Verschlüsselung, etc.)?
  • Sind die Zugriffsrechte auf die App selbst klar definiert, oder kann eine andere App ebenfalls auf die verarbeiteten Daten zugreifen?

Auch die Berechtigungen, die eine Applikation beim Installieren auf einem Gerät fordert, sind ein essenzieller Faktor, der berücksichtigt werden muss. Eine Applikation sollte Berechtigungen auf Funktionen nur anfragen, wenn diese auch wirklich benötigt werden. Überflüssig angefragte Berechtigungen bergen ein zusätzliches Risiko, dass unnötig getragen werden muss.

Doch der Aspekt der am häufigsten und einfachsten von einem Angreifer ausgenutzt werden kann, ist das Mitlauschen bei der Netzwerkkommunikation einer Applikation, denn diese Geräte arbeiten meist in öffentlichen oder schlecht gesicherten Netzen (Cafés, Flughäfen oder freie WLANs in Städten).

Kommunikation zwischen Apps und deren Backend-Systemen

Man-in-the-Middle-Angriffe sind wohl die einfachste Art, um kritische Daten, die bei der Kommunikation von Apps und deren Backend-Systemen übertragen werden, abzufangen. Hierbei werden Anmeldedaten, Konfigurationsdaten aber auch oft die sensiblen Inhalte übertragen. Um die Kritikalität und Integrität der Daten zu schützen, ist es hier besonders wichtig, Schutzmechanismen für die Kommunikation zwischen Apps und Backend-Servern zu implementieren.

Zunächst sollten kritische Daten – insbesondere Passwörter – niemals im Klartext übertragen werden. Für Passwörter eignen sich kryptographische Einweg-Hashfunktionen inkl. einzigartigem Salt, für andere kritische Daten, wie z. B. Kalkulationen, sollte man auf gängige Verschlüsselungsalgorithmen zurückgreifen.

Darüber hinaus muss auch der Kommunikationskanal geschützt werden. Für die Datenübertragung sollte dieses immer über HTTPS erfolgen, sodass der Kommunikationskanal selbst bereits verschlüsselt ist. Trotz verschlüsseltem Kanal gibt es für Angreifer noch Möglichkeiten, sich in die Kommunikation einzuklinken. Um dies zu verhindern, sollte das Zertifikat des Backend-Servers von einer bekannten Zertifizierungsstelle (Root-CA) signiert sein und von der Applikation selbst auf Vertrauenswürdigkeit, Gültigkeit und Richtigkeit überprüft werden. Nur so kann die Authentizität des Backend-Servers überprüft und der Kommunikationskanal abgesichert werden. Ist es für den Usecase der Applikation möglich, sollte man hier zusätzlich auf Certificate Pinning setzen, um es einem Angreifer noch schwerer zu machen, sich in die Verbindung einzuklinken.

HTTPS ohne korrekte Verifizierung der Zertifikate oder mit selfsigned Zertifikaten bietet hier eher einen Alibi-Schutz, als dass es die Kommunikation wirklich absichert.

Fazit der Risiken

Auch bei mobilen Endgeräten ist immer das schwächste Glied der Kette ausschlaggebend für das tatsächliche Sicherheitsrisiko. Da man als Unternehmen nur selten Einfluss auf die Updatepolitik des Geräteherstellers hat, sollte man sich diese genau betrachten bevor man gewisse Geräte für den Einsatz zulässt.

Abgesehen von den im Gerät schon vorhandenen Schwachstellen, sollten Firmen aber auf jeden Fall die Apps, die sie verwenden möchten, genau prüfen, denn hier kann man unnötige Angriffsfaktoren erkennen und schließen.

Beispiele für kritische Lücken in Apps

In diesem Abschnitt möchte ich anhand einzelner Beispiele zeigen, warum man dem Hersteller einer App nicht immer blind vertrauen sollte, auch wenn er angibt, dass er die Sicherheit seiner Kunden und deren Daten im Fokus hat.

Sicherer Mailer für Android

Wie man bereits aus der Forensik weiß, sollte man ein Auge auf alle Dateien haben, auf die die Applikation Zugriff hat oder die durch sie verwaltet werden.
Ein Beispiel dafür, dass eine solche erweiterte Suche über alle Dateien innerhalb der Sandbox einer App durchaus sinnvoll ist, zeigt uns eine sehr bekannte Applikation zur Synchronisation von PIM-Daten im Unternehmen. Sie verspricht eine sichere Synchronisation und Verwaltung von PIM-Daten auf einem Android-Smartphone. Dabei schützt sie diese Daten durch Verschlüsselung und verwendet dazu die PIN, die der Nutzer vergeben muss, um die App zu verwenden (eine sogenannte **Applikations-PIN**). Um hier als Angreifer oder Sicherheitsanalyst an die Daten zu kommen, muss also diese Applikations-PIN herausgefunden werden.

Schaut man sich innerhalb der Sandbox (*/data/data/com.honxx.xxx/*) etwas genauer um, so sieht man eine ganze Menge an Dateien, die unbekannte Dateiendungen haben und uns dadurch noch neugieriger machen sollten. Ein Beispiel für eine solche Datei ist die Datei mit dem Namen *xxxdroid.db.sc* (s. nachfolgendes Codebeispiel).

Codebeispiel - Sicherer Mailer für Android:

ASVersions=Versions:Microsof IIS /7.5 ,2.0 ,2.1 ,2.5 ,12.0 ,12.1 ,14.0 ,14.1
AccountID=Exchange Mail
. . . . . . .
Domain=#EFT1.7#I0VGVDE
FailedLoginAttemptCount=0
FolderSyncKey=1
LastPINPromptTime=1421767231987
LastPinChangeTime=1421766891980
LastPolicyGet=0
. . . . . . .
PasswordHistory=14141414
PasswordHistory=#EFT1.7#I0VGVDE
PasswordRecoveryEnabled=f al s e
PolicyKey=814518012
. . . . . . .
ServerName=#EFT1.7#I0VGVDE
UnapprovedInROMApplicationList=
UserID=#EFT1.7#I0VGVDE
. . . . . . .

In Zeile 12 (*PasswordHistory=14141414*) sehen wir einen Wert mit dem Namen *PasswordHistory*. Dieser Wert lässt darauf schließen, dass es sich hier unter Umständen um eine ältere PIN handelt. Für etwas Verwunderung sorgt jedoch, dass die direkt darauf folgende Zeile denselben Wert nochmals besitzt, diesmal aber mit einem verschlüsselten Inhalt.

Durch einfachen Test der Zeichenfolge *14141414* stellt man fest, dass dies kein älterer Wert – also die History – ist, sondern die aktuelle Applikations-PIN, also das einzige Geheimnis, das zur Verschlüsselung verwendet wird, und zugleich auch der einzige Schutz des Containers vor unberechtigtem Zugriff. Hat der Sicherheitsanalyst diesen Wert, so kann er sowohl über die Oberfläche wie
auch durch manuelles Entschlüsseln der Datenbanken auf alle sensiblen Daten innerhalb des Containers zugreifen und auch E-Mails im Namen des eingerichteten Nutzers versenden.

Dieses Finding wurde vom Hersteller inzwischen beseitigt, zeigt aber sehr gut, wie kleine Fehler beim Entwickeln einer App gravierende Folgen haben können.

CAD-App für iOS

Viele Apps, gerade wenn es um Szenarien geht wie z. B. "Arbeiten auf einer Baustelle" oder "Arbeiten in geschützten Bereichen", benötigen die nahezu komplette Funktionalität auch in dem Moment wo das mobile Endgerät offline ist. So auch die App, deren Probleme ich hier kurz beschreiben möchte.

Die App ist in der Lage, CAD-Zeichnungen auf einem iPad darzustellen und bietet zudem die Möglichkeit, Notizen oder Anmerkungen in diese Zeichnungen einzufügen. Also das klassische Beispiel für eine App die zur Abnahme von Gebäuden oder der Überprüfung ob diese dem Plan entsprechen verwendet werden kann. Damit das alles auch offline funktioniert, haben die Hersteller auch die Authentifizierung offline implementiert. Das selbst ist kein Problem, solange man es richtig macht.

Im Falle dieser App werden jedoch die Passwörter und Nutzernamen im Plain-Text in einer lokalen Datenbank mit

**NSFileProtectionCompleteUntilFirstUserAuthentication**

abgelegt. Hier sieht man sehr schön, dass zum Einen die Schutzklasse nicht restriktiv genug gewählt wurde (**NSFileProtectionComplete** wäre hier besser geeignet gewesen), zum Anderen zeigt sich auch, dass man sich über Sicherheit der Credentials keine Gedanken gemacht hatte. Passwörter sollten niemals im Plain-Text gespeichert werden! Noch gravierender an dieser App war jedoch, dass nicht nur die Credentials des lokalen Nutzers auf das iPad kopiert wurden, sondern die Credentials und kompletten Nutzerinformationen (Name, Email, Firma, Telefon, etc.) von allen Kunden der App – was zum Zeitpunkt des Tests mehr als 200 waren.

Durch diesen Fehler wäre es einem Angreifer oder Sicherheitsanalysten möglich gewesen, die Pläne von allen Kunden und all ihren Gebäuden einzusehen und zu verändern – die möglichen Auswirkungen hiervon möge man sich lieber nicht vorstellen.

Auch hier hat der Hersteller inzwischen reagiert und speichert nur noch gehashte Credentials der zuvor eingeloggten Nutzer ab.

Friendly Hacking

Um Fehler oder Schwachstellen wie die zuvor gezeigten, in einer App zu finden, ist es nötig, sich diese Apps und alle Dateien auf die sie Zugriff haben, genauer anzuschauen. Dies macht man üblicherweise im Rahmen eines "Pentests" oder umgangssprachlich durch "Friendly Hacking".

Beim Friendly Hacking ist neben dem Reversing das Debugging bzw. das Manipulieren von Variablen zur Laufzeit ein wichtiger Punkt. Durch ein spezielles Tool (meist Debugger genannt) ist es dem Analysten möglich, Applikationen zur Laufzeit zu beobachten und so Programmabläufe besser verstehen und auch den Fluss von Informationen nachvollziehen zu können. Passende Tools für diesen Zweck gibt es für Android in großer Zahl. Aus Erfahrungen ist neben der professionellen Version mit "IDA Pro" [3] vor allem "Codeinspect" [4] das Tool der Wahl, da es deutlich einfacher zu verwenden ist als IDA und im Bereich Android durch diverse Vorteile punkten kann.

Aber auch der eingebaute Debugger in Eclipse oder dem Android Studio kann hier – mit Abstrichen – verwendet werden. Bei Android kann der Applikationsentwickler das Hooken durch einen Debugger im Android-Manifest zu verhindern versuchen. Dies geschieht durch Setzen des xml-Tags android:debuggable="false". Sollte dieses Tag im Android-Manifest gesetzt sein, so gibt es nur zwei Möglichkeiten, dies zu umgehen:

  1. Vor dem eigentlichen Debugging wird die Applikation wie zuvor gezeigt dekompiliert, das Flag überschrieben und wieder eine lauffähige Applikation zusammengebaut.
  2. Es wird ein Hooker verwendet (wie z. B. das XPosed-Framework mit dem BuildProp-Enhancer), der zur Laufzeit dieses Flag von false auf true setzt.

Im weiteren Verlauf dieses Abschnittes werden wir uns ein paar einfache
Beispiele für das Debuggen und Manipulieren von Android-Applikationen
mittels Codeinspect ansehen.

Als Beispiel verwenden wir eine bekannte Malware-Applikation: "SuiConFo" [5]. Von ihr wissen wir, dass sie je nach Land, aus dem die SIM-Karte kommt, eine andere Nachricht versendet. Dies versuchen wir nun auch mit Codeinspect zu verifizieren. Dazu importieren wir die apk-Datei und setzen einen Breakpoint auf Zeile 34 (in Zeile 33 wurde auf getSimCountryIso() zugegriffen und das Ergebnis in die Variable String geschrieben) in der Datei MagicSMSActivity.jimple (s.Abb.1).

Zusätzlich setzen wir noch einen zweiten Breakpoint auf die Zeile 41 (hier wird die erste SMS versendet). In dieser Zeile können wir verifizieren, an welche Nummer welcher Text gesendet wird und somit feststellen, ob unsere Änderung von der Applikation übernommen wurde. Im Anschluss starten wir die Ausführung der Applikation im Emulator (s.Abb.2).

Sobald nun der Emulator gestartet und der Debugger erfolgreich mit der Applikation verbunden ist, startet die Ausführung. In dem Moment, wenn die Applikation dabei ist, die Zeile auszuführen, die wir mit dem Breakpoint markiert haben, wird sie angehalten – die Ausführung also in den Pause-Modus gesetzt – und wir sehen in Codeinspect die Variablen, die zu diesem Zeitpunkt im Speicher liegen (s.Abb.3).

Da wir schon etwas über die Applikation herausgefunden haben, wissen wir, dass der entscheidende Punkt die Rückgabe des "TelephonyManager" und somit der Rückgabewert von getSimCountryIso() ist. Unser Emulator hat hier us als aktuellen Rückgabewert. Diesen ändern wir nun auf de, um zu sehen, wie dies die Ausführung der Malware verändert. Um diese Änderung erfolgreich durchzuführen, müssen wir nur auf den entsprechenden Wert mit der rechten Maustaste klicken und dann Change Value auswählen. In dem nun erscheinenden Fenster können wir us löschen und manuell de eintippen. Dies ist wichtig, da Codeinspect unsere Eingabe auf diese Weise direkt wieder in ein gültiges Objekt umwandelt, das die Applikation im kommenden Schritt erwartet.

Im Anschluss klicken wir nun in der obersten Zeile auf Resume (F8), um die Applikation weiter ausführen zu lassen. Ab diesem Moment verwendet die Variable den von uns vergebenen Wert und nicht mehr den eigentlichen Rückgabewert der Funktion getSimCountryIso(). Sobald der zweite Breakpoint erreicht wird, sehen wir in den Variablen nun auch das Ergebnis: Es werden die Werte verwendet, die einer deutschen SIM-Karte entsprechen (s.Abb.4), und nicht die für einen Emulator typischen Werte.

Abb.5 zeigt entsprechend dazu auch die Warnmeldung der Premium-SMS mit den auf die Änderung resultierenden Werten.

Dieses Beispiel zeigt anhand einer recht simplen Malware, wie mächtig Werkzeuge wie Codeinspect sind, um Applikationen zu manipulieren oder um Sicherheitsabfragen des Entwicklers zu umgehen, selbst wenn der Code der Applikation deutlich komplexer oder gar verschleiert ist. Eine weitere nützliche Funktion von Codeinspect ist auch die Steuerung wichtiger Komponenten des Emulators. Diese Steuerung findet man unter DDMS->Emulator Control. Hier kann man über die grafische Oberfläche den Eingang von SMS-Nachrichten, Telefonanrufen oder auch die GPS-Daten des Endgerätes simulieren. Hierdurch ist es möglich, Nutzerinteraktionen der Applikation vorzugaukeln. Dies ist besonders dann von Interesse, wenn wir in der statischen Analyse (beim sogenannten "Reversing") festgestellt haben, dass die Applikation auf den Eingang einer bestimmten SMS-Nachricht wartet. Diese Nachricht können wir nun zur Laufzeit über die Oberfläche auslösen und genau beobachten, was die Applikation im Anschluss durchführt.

Ebenso kann man eigenen Java- oder Jimple-Code in die Applikation einfügen, der zur Laufzeit kompiliert wird. So kann man die Applikation manipulieren und neue Funktionen hinzufügen. Hierdurch kann man z. B. erreichen, dass die Applikation ihre Crypto-Schlüssel in eine Textdatei zur späteren Analyse wegschreibt oder zusätzliche Logausgaben erzeugt.

Fazit

Wie man ganz gut an den zwei erwähnten Beispielen gesehen hat, ist es für ein Unternehmen keine gute Idee, einfach den Versprechen der Hersteller blind zu vertrauen. Man sollte daher immer ein eigenständiges Überprüfen der versprochenen Leistungen einer App – den sogenannten Pentest – bevorzugen. Damit kann man sicherzustellen, dass die App auch so mit den ihr anvertrauten Daten umgeht, wie man das von ihr erwartet. Böse Überraschungen werden  dadurch schon im Vorfeld reduziert und im besten Fall sogar vollständig vermieden.

Autor

Dr. Michael Spreitzenbarth

Dr. Michael Spreitzenbarth arbeitet in einem weltweit operierenden CERT eines deutschen Großkonzerns, wo sein Fokus auf der Absicherung mobiler Endgeräte, Incident Handling auf mobilen Plattformen und der Analyse verdächtiger…
>> Weiterlesen
Das könnte Sie auch interessieren
Kommentare (0)

Neuen Kommentar schreiben