Apples wundersame Welt der iOS-Extensions

Teil 1: Die Möglichkeiten der iOS Network Extension

01.03.2017 von Mark Zimmermann  
Viele kennen Extensions als Erweiterung von Apps, damit diese mit Siri reden oder mit der Maps-App interagieren können beziehungsweise als Möglichkeit, alternative Tastaturen in iOS aufzunehmen. Diese Serie möchte Ihnen einen Einblick geben, welches Potential sich in den Extensions bei genauer Betrachtung versteckt.

Wer denkt, dass iOS ein geschlossenes System ist, hat sich nie richtig mit den Möglichkeiten der Extensions beschäftigt. Mit iOS 8 hat Apple erstmals das Konzept der Extensions eingeführt. Diese Einführung war revolutionär, denn bis dahin galt iOS als abgeschottetes System, das keine Freiheiten erlaubt. Im Vergleich zu Android können Entwickler zwar nicht wild darauf los entwickeln, aber trotzdem stehen alle Funktionen (und mehr) bei genauer Betrachtung zur Verfügung.

App Extensions bringen Flexibilität in iOS
Foto: Apple

In dieser Serie möchte ich Ihnen einigen Extensions zeigen, von denen Sie zu einer sehr hohen Wahrscheinlichkeit entweder noch nie etwas gehört haben oder das Potential nicht erkennen konnten.

Netzwerk Extension

Der Zugriff auf Netzwerke, genauer genommen auf WLAN-Netzwerke, erfolgt durch konfigurierte Einstellungen. Diese Konfigurationen können (bei Unternehmen) durch MDM-Server erfolgen oder durch manuelle Einträge am Gerät selbst. Häufig werden dabei SSIDs und Kennwörter dem Gerät bekannt gemacht und ab dann greift der Zugriff, sobald das WLAN in Reichweite ist.

Dies setzt aber einiges voraus. Zum einen muss das Gerät einer Firma gehören, damit es per MDM automatisiert den Zugriff konfiguriert bekommt oder der Anwender muss Kenntnis über die Geheimnisse des WLANs erlangen (Kennwort), damit er dies auf seinem Gerät konfigurieren kann.

Auch der Zugriff über Zertifikate, gerade im Firmenumfeld, setzt voraus, dass diese über einen vertraulichen, verlässlichen und abgesicherten Weg auf dem jeweiligen Endgerät, am besten Personenscharf, installiert werden.

Wenn man sich dies durchliest, sind folgende Fälle und Szenarien damit nicht möglich:

Viele Hersteller versprechen mit Captive Portals eine mögliche Lösung. Hierbei versucht ein Gerät eine ihm bekannte Webseite (im Falle von iOS captive.apple.com) zu erreichen, sobald ein WLAN-Kontakt besteht. Wird das Gerät bei dieser Anfrage umgeleitet, handelt es sich um ein WLAN mit Captive Portal. Hier wird eine Web-Maske zum Anmelden präsentiert, bei der sich der Anwender registriert, damit im Anschluss das Gerät Zugriff auf das Internet erhält. Dies wird meist bildschirmfüllend (z.B. iOS) oder in einem Webview-Fenster (z.B. MacOS) dargestellt. Diese Captive-Portal Lösungen können benutzerspezifische Anmeldungen mit Gültigkeitsdauer abbilden, sind aber umständlich für den Anwender zu bedienen.

Für iOS-User gibt es genau hier die Möglichkeit, dynamisch und flexibel Anwender für WLAN-Netzwerke zu berechtigen, egal welche Technologie oder welches Autorisierungsverfahren diese einsetzen. Dies geht soweit, dass die oben erwähnten Geheimnisse für ein WLAN nicht einmal notwendig sind und die Sicherheit trotzdem gewährleistet wird. Das Geheimnis: Eine App mit der Netzwerk-Extension: NEHotSpotHelper (https://developer.apple.com/reference/networkextension/nehotspothelper).

NEHotSpotHelper für Entwickler: Grundlagen

Damit diese Extension benutzt werden kann, muss der Entwickler die Berechtigung erst einmal online (https://developer.apple.com/contact/network-extension) beantragen. Wird dem Entwickler dies erlaubt, kann er das erworbene Entitlement in seinem App-Plist File bekannt machen:

<plist version="1.0">

<dict>

<key>get-task-allow</key>

<true/>

<key>application-identifier</key>

<string>XXXXXXX</string>

<key>com.apple.developer.team-identifier</key>

<string>XXXXXXX</string>

<key>com.apple.developer.networking.HotspotHelper</key>

</dict>

</plist>

Alle Apps mit NEHotSpotHelper müssen zusätzlich die Erlaubnis bekommen, im "Background-Mode" arbeiten zu dürfen.

Ist die Extension eingebaut, können Entwickler auf den Verbindungsaufbau einer jeden WLAN-Verbindung Einfluss nehmen. Vereinfacht ausgedrückt: Der Entwickler kann definieren, für welches WLAN sein Programmcode die Autorisierung übernehmen kann und das Betriebssystem lässt diesen Code dann schalten und walten. Dieser Umstand erlaubt es nun, das Geheimnis des WLANs im AppBundle zu verstecken und mit eigenen zusätzlichen Parametern (Zeitraum, Ort an dem dies funktionieren soll, eigenem User Login an der App) zu versehen.

NEHotSpotHelper für Entwickler: Praktischer Einsatz

Nutzt der Entwickler diese Extension, erfährt der Anwender davon nichts. Es kommt keine Sicherheitsabfrage und auch sonst keine optische Information darüber. Dies stellt in meinen Augen auch ein enormes Sicherheitsrisiko dar, denn theoretisch könnte eine App mit dieser Berechtigung viele Daten erheben, die man nicht so einfach freigeben möchte. Neben der Information der gerade in Empfangsreichweite befindlichen WLAN-Netzwerke erfährt die Extension beispielsweise auch Informationen über die Signalstärke oder mit welchem WLAN sich der Anwender gerade verbunden hat. Es wäre somit ein Leichtes, diese Informationen an einen Daten sammelnden Server zu übermitteln.

Aufgrund der fehlenden Transparenz dem Anwender gegenüber sollte es zum guten Ton gehören, diesem mitzuteilen, dass man die Kontrolle über diverse WLAN-Verbindungsversuche übernehmen wird. Hierzu bietet die Extension an, das jeweilige WiFi in der WLAN Übersicht (Einstellungen -> WLAN) zu annotieren:

NEHotspotHelper.register(options: [kNEHotspotHelperOptionDisplayName: NSString(string: "…wird verwaltet von mir")], queue: DispatchQueue.main, handler: NetworkExtension.NEHotspotHelperHandler)

Klickt der Anwender (in der ersten Anmeldung muss er das von Hand tun) auf das verwaltete WLAN steht dem Entwickler in seiner App eine State Machine zur Verfügung, in welcher die wichtigsten Anmelderoutinen zur Verfügung stehen (siehe Bild).

State Machine der NeHotSpotHelper Extension

Aktiviert der Anwender eine WLAN-Verbindung prüft die App (commandtype: .evaluate) ob es sich um ein WLAN handelt, bei dem der Programmcode die Anmeldung übernehmen kann. Ist dem so, kann dies dem Betriebssystem durch network.setConfidence(.high) mitgeteilt werden.

Der eigentliche Anmeldeversuch (commandtype:.authenticate:) ist in dem Fall spannend, wenn es sich um ein Captive-Portal handelt. Im anderen Fall bietet die Extension die Möglichkeit, die Anmeldedaten an die standardisierten Verfahren (z.B. WPA2) programmatisch zu übermitteln. IM letzteren Fall werden somit nur Eigenschaften der Extension aufgerufen um eine Anmeldung zu vollziehen.

Bei einem Captive-Portal ist das Vorgehen etwas komplizierter. Der Anmeldeprozess, das Aushandeln von Session-, Portal-Tokens und ähnliches muss nachgebaut werden.

Die Abfragen müssen dabei genau wie im Browser verlaufen. Rufen Sie als erstes captive.apple.com auf und reagieren Sie auf die Rückmeldung. Entweder erhalten Sie bereits vom Router einen redirect oder einen HTML Response, der einen Browser dazu bewegen würde, einen redirect auszuführen.

Google Chrome bietet alles was man braucht, um Header, Post/Get Aufrufe usw. zu analysieren.

Anhand dieses einfachen Satzes merken Sie, dass Sie auch den Response auswerten und parsen müssen. Es ist nicht nur wichtig, die richtige URL zur richtigen Zeit aufzurufen und den Response zu parsen. Auch die Header Informationen müssen jeweils korrekt gesetzt werden:

.addValue("application/x-www-form-urlencoded; charset=UTF-8", forHttpHeaderField: "Content-Type")

.addvalue("http://captive.apple.com", forHttpHeaderField: "Referer")

Zum Setzen sind die Werte aus dem vorherigen Response wichtig. Was sich kompliziert anhört ist gar nicht so schwer. Sie können mit dem Chrome Browser, über dessen Entwickler Werkzeuge, einfach die notwendigen Parameter extrahieren und die komplette Anmeldestrecke mitschneiden. Der Rest ist Fleißarbeit und eine Qualitätssicherung, das nichts vergessen wird. Eine noch so kleine Abweichung, wie ein vergessenes Cookie oder ein vergessen User-Agent entscheiden hier über den Erfolg oder den Misserfolg. Natürlich müssen Sie das nicht unbedingt nach Implementieren, Ihr Infrastrukturbetreiber kann Ihnen sicherlich mit ausführlicher Dokumentation oder alternativen Web-Schnittstellen aushelfen.

Ist die Anmeldung schließlich erfolgreich, müssen Entwickler diesen Erfolg (oder Misserfolg) dem Betriebssystem mitteilen:

Erfolgsfall:

result.setNetwork(command.network!)

result.deliver()

Misserfolgsfall:

let result = command.createResponse(.failure)

result.setNetwork(command.network!)

result.deliver()

Besteht die Verbindung und muss diese "offen gehalten" werden, steht ebenfalls das Ausführen von Programmcode für den Betrieb (commandtype:.maintain:) als Möglichkeit zur Verfügung. Dieser Betriebsstatus wird aus zwei Gründen aufgerufen, einmal ca. alle 300 Sekunden (= 5 Minuten) nach einer erfolgreichen Anmeldung, um die Möglichkeit zur haben, die Verbindung aufrecht zu halten. Aber der Code wird auch dann ausgeführt, wenn es in der Vergangenheit einmal eine Erfolgreiche Anmeldung durch die Network Extension gegeben hat.

Network Extensions sind ein mächtiges Werkzeug. Erstellen Sie damit Apps für Ihre Belegschaft, um eine einfachere und differenziertere Anmeldung zu ermöglichen. Messen Sie die Ausleuchtung Ihrer WLAN-Netze. Vergeben Sie tagesgültige Zugänge an Gäste oder Besucher. Sorgen Sie für automatisierte Anmeldungen per App, ohne langwierige Captive Portal Zugriffe. Nicht nur die Anmeldezeit wird damit optimiert, auch die Stabilität der Verbindung profitiert davon. (mb)